首页 > 其他分享 >【最新鸿蒙应用开发】——实现鸿蒙的动画效果

【最新鸿蒙应用开发】——实现鸿蒙的动画效果

时间:2024-07-10 11:55:44浏览次数:17  
标签:模态 动画 鸿蒙 width 最新 组件 转场 属性

鸿蒙动画效果

UI(用户界面)中包含开发者与设备进行交互时所看到的各种组件(如时间、壁纸等)。属性作为接口,用于控制组件的行为。例如,开发者可通过位置属性调整组件在屏幕上的位置。

属性值的变化,通常会引起UI的变化。动画可在UI发生改变时,添加流畅的过渡效果。如果不加入动画,属性将在一瞬间完成变化。造成突兀感的同时,容易导致用户失去视觉焦点。

img

动画的目的包括:

  • 使界面的过渡自然流畅。

  • 增强用户从界面获得的反馈感和互动感。

  • 在内容加载等场景中,增加用户的耐心,缓解等待带来的不适感。

  • 引导用户了解和操作设备。

在需要为UI变化添加过渡的场景,都可以使用动画,如开机、应用启动退出、下拉进入控制中心等。这些动画可向用户提供关于其操作的反馈,并有助于让用户始终关注界面。

ArkUI中提供多种动画接口(属性动画、转场动画等),用于驱动属性值按照设定的动画参数,从起始值逐渐变化到终点值。尽管变化过程中参数值并非绝对的连续,而是具有一定的离散性。但由于人眼会产生视觉暂留,所以最终看到的就是一个“连续“的动画。UI的一次改变称为一个动画帧,对应一次屏幕刷新。决定动画流畅度的一个重要指标就是帧率FPS(Frame Per Second),即每秒的动画帧数,帧率越高则动画就会越流畅。ArkUI中,动画参数包含了如动画时长、动画曲线等参数。动画曲线作为主要因素,决定了属性值变化的规律。以线性动画曲线为例,在动画时长内,属性值将从起点值匀速变化到终点值。属性过快或过慢的变化,都可能带来不好的视觉感受,影响用户体验。因此动画参数特别是动画曲线,需要结合场景和曲线特点进行设计和调整。

动画接口驱动属性值按照动画参数决定的规律,从原来的状态连续过渡到新的状态,进而在UI上产生的连续视觉效果。本文将按照如下结构,提供各种动画的使用方法和注意事项,使开发者快速学习动画。

img

  • 属性动画:最基础的动画类型,按照动画参数逐帧驱动属性的变化,产生一帧帧的动画效果。

  • 转场动画:为组件在出现和消失时添加过渡动画。为了保证动画一致性,部分接口动画曲线已内置,不支持开发者自定义。

    • 不推荐在应用内使用UIAbility组合所有的界面:UIAbility是一个任务,会在多任务界面独立显示一个卡片,UIAbility之间的跳转是任务之间的跳转。以应用内查看大图的典型场景为例,不建议应用内调用图库的UIAbility去打开图片查看大图,会导致任务的跳转,图库的UIAbility也会加入多任务界面中。正确的方式是应用内构建大图组件,通过模态转场去调起大图组件,一个任务内的所有的界面都在一个UIAbility内闭环。

    • 导航转场中,应使用Navigation组件实现转场动画。过去的page+router方式在实现导航转场过程中,因为page和page之间相互独立,其联动动画效果受限。不仅容易导致页面之间的割裂,并且不支持一次开发多端部署。

  • 组件动画:组件提供默认动效(如List的滑动动效)便于开发者使用,同时部分组件还支持定制化动效。

  • 动画曲线:介绍传统曲线和弹簧曲线的特点和使用方式。动画曲线影响属性值的运动规律,进而决定界面的动画效果。

  • 动画衔接:介绍如何实现动画与动画之间、手势与动画之间的自然过渡。

  • 高阶动画效果:介绍模糊、大阴影和颜色渐变等高阶效果接口的使用方法。

1. 属性动画

1.1. 介绍

  • 可动画属性:

    对于可动画属性,系统不仅提供通用属性,还支持自定义可动画属性。

    • 系统可动画属性:组件自带的支持改变UI界面的属性接口,如位置、缩放、模糊等。

    • 自定义可动画属性:ArkUI提供@AnimatableExtend装饰器用于自定义可动画属性。开发者可从自定义绘制的内容中抽象出可动画属性,用于控制每帧绘制的内容,如自定义绘制音量图标。通过自定义可动画属性,可以为ArkUI中部分原本不支持动画的属性添加动画。

  • 不可动画属性:zIndex、focusable等。

1.2. animation & animateTo

通过可动画属性改变引起UI上产生的连续视觉效果,即为属性动画。属性动画是最基础易懂的动画,ArkUI提供两种属性动画接口animateToanimation驱动组件属性按照动画曲线等动画参数进行连续的变化,产生属性动画。

属性动画接口作用域原理使用场景
animateTo闭包内改变属性引起的界面变化。作用于出现消失转场。通用函数,对闭包前界面和闭包中的状态变量引起的界面之间的差异做动画。支持多次调用,支持嵌套。适用对多个可动画属性配置相同动画参数的动画。需要嵌套使用动画的场景。
animation组件通过属性接口绑定的属性变化引起的界面变化。识别组件的可动画属性变化,自动添加动画。组件的接口调用是从下往上执行,animation只会作用于在其之上的属性调用。组件可以根据调用顺序对多个属性设置不同的animation。适用于对多个可动画属性配置不同参数动画的场景。

1.2.1. 使用animation产生属性动画

相比于animateTo接口需要把要执行动画的属性的修改放在闭包中,animation接口无需使用闭包,把animation接口加在要做属性动画的可动画属性后即可。animation只要检测到其绑定的可动画属性发生变化,就会自动添加属性动画,animateTo则必须在动画闭包内改变可动画属性的值从而生成动画。

import curves from '@ohos.curves'
​
@Entry
@Component
struct AnimationDemo {
  @State animate: boolean = false;
  // 第一步: 声明相关状态变量
  @State rotateValue: number = 0; // 组件一旋转角度
  @State translateX: number = 0; // 组件二偏移量
  @State opacityValue: number = 1; // 组件二透明度
​
  // 第二步:将状态变量设置到相关可动画属性接口
  build() {
    Row() {
      // 组件一
      Column() {
      }
      .opacity(this.opacityValue)
      .rotate({ angle: this.rotateValue })
      // 第三步:通过属性动画接口开启属性动画
      .animation({ curve: curves.springMotion() })
      .backgroundColor('#317AF7')
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .borderRadius(30)
      .onClick(() => {
        this.animate = !this.animate;
        // 第四步:闭包内通过状态变量改变UI界面
        // 这里可以写任何能改变UI的逻辑比如数组添加,显隐控制,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画
        // 组件一的rotate属性发生变化,所以会给组件一添加rotate旋转动画
        this.rotateValue = this.animate ? 90 : 0;
        // 组件二的offset属性发生变化,所以会给组件二添加offset偏移动画
        this.translateX = this.animate ? 50 : 0;
        // 父组件column的opacity属性有变化,会导致其子节点的透明度也变化,所以这里会给column和其子节点的透明度属性都加动画
        this.opacityValue = this.animate ? 0.6 : 1;
      })
​
      // 组件二
      Column() {
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .backgroundColor('#D94838')
      .borderRadius(30)
      .opacity(this.opacityValue)
      .translate({ x: this.translateX })
      .animation({ curve: curves.springMotion() })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

img

1.2.2. 使用animateTo产生属性动画

animateTo(value: AnimateParam, event: () => void): void

animateTo接口参数中,value指定动画参数(包括时长、曲线等)event为动画的闭包函数,闭包内变量改变产生的属性动画将遵循相同的动画参数。

import curves from '@ohos.curves'
​
@Entry
@Component
struct AnimateToDemo {
  @State animate: boolean = false;
  // 第一步: 声明相关状态变量
  @State rotateValue: number = 0; // 组件一旋转角度
  @State translateX: number = 0; // 组件二偏移量
  @State opacityValue: number = 1; // 组件二透明度
​
  // 第二步:将状态变量设置到相关可动画属性接口
  build() {
    Row() {
      // 组件一
      Column() {
      }
      .rotate({ angle: this.rotateValue })
      .backgroundColor('#317AF7')
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .borderRadius(30)
      .onClick(() => {
        animateTo({ curve: curves.springMotion() }, () => {
          this.animate = !this.animate;
          // 第三步:闭包内通过状态变量改变UI界面
          // 这里可以写任何能改变UI的逻辑比如数组添加,显隐控制,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画
          // 组件一的rotate属性发生变化,所以会给组件一添加rotate旋转动画
          this.rotateValue = this.animate ? 90 : 0;
          // 组件二的透明度发生变化,所以会给组件二添加透度的动画
          this.opacityValue = this.animate ? 0.6 : 1;
          // 组件二的offset属性发生变化,所以会给组件二添加offset偏移动画
          this.translateX = this.animate ? 50 : 0;
        })
      })
​
      // 组件二
      Column() {
​
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .backgroundColor('#D94838')
      .borderRadius(30)
      .opacity(this.opacityValue)
      .translate({ x: this.translateX })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

img

说明

  • 在对组件的位置大小的变化做动画的时候,由于布局属性的改变会触发测量布局,性能开销大。scale属性的改变不会触发测量布局,性能开销小。因此,在组件位置大小持续发生变化的场景,如跟手触发组件大小变化的场景,推荐适用scale。

  • 属性动画应该作用于始终存在的组件,对于将要出现或者将要消失的组件的动画应该使用转场动画。

  • 尽量不要使用动画结束回调。属性动画是对已经发生的状态进行的动画,不需要开发者去处理结束的逻辑。如果要使用结束回调,一定要正确处理连续操作的数据管理。

2. ImageAnimator 帧动画

提供逐帧播放图片的能力

ImageAnimator不是容器组件,也不需要传递参数,只需要设置属性即可

1.1.1常用属性

参数名称参数类型参数描述
imagesArray<ImageFrameInfo>设置图片帧信息集合。 说明: 不支持动态更新。
stateAnimationStatus默认为初始状态,用于控制播放状态。
durationnumber单位为毫秒,默认时长为1000ms;duration为0时,不播放图片;值的改变只会在下一次循环开始时生效;当images中任意一帧图片设置了单独的duration后,该属性设置无效。 默认值:1000 从API version 10开始,该接口支持在ArkTS卡片中使用。
iterationsnumber默认播放一次,设置为-1时表示无限次播放。 默认值:1
。。。。

效果

runningDog.gif

思路:

  1. 创建符合要求的数组 ImageFrameInfo

  2. 渲染ImageAnimator组件

    1. .images() 指定 要渲染的帧动画 数组

    2. .duration()指定动画的切换时间

    3. .state()指定动画的播放状态

    4. .iterations() 指定执行次数

参考代码:

// xxx.ets
@Entry
@Component
struct ImageAnimatorExample01 {
  images: ImageFrameInfo[] = [
    { src: $r("app.media.loading_dog_0") },
    { src: $r("app.media.loading_dog_1") },
    { src: $r("app.media.loading_dog_2") },
    { src: $r("app.media.loading_dog_3") }
  ]
​
  @State state:AnimationStatus = AnimationStatus.Initial
​
  build() {
    Column({ space: 10 }) {
      ImageAnimator()
        .animatorFancy() // 抽取公共属性
        .images(this.images) // 动画数组
        .duration(this.images.length*100)// 持续
        .state(this.state)// 动画状态
        .iterations(-1)// 播放次数
​
      // 按钮控制区域
      Row({space:20}){
        Button('启动').onClick(()=>{
          this.state=AnimationStatus.Running
        })
        Button('暂停').onClick(()=>{
          this.state=AnimationStatus.Paused
        })
        Button('停止').onClick(()=>{
          this.state=AnimationStatus.Stopped
        })
      }
    }
    .width('100%')
    .height('100%')
​
  }
​
  @Styles
  animatorFancy() {
    .width(300)
    .aspectRatio(2)
    .padding(10)
    .borderRadius(10)
  }
}

3. 转场动画

3.1. 模态转场

模态转场是新的界面覆盖在旧的界面上,旧的界面不消失的一种转场方式。

表1 模态转场接口

接口说明使用场景
bindContentCover弹出全屏的模态组件。用于自定义全屏的模态展示界面,结合转场动画和共享元素动画可实现复杂转场动画效果,如缩略图片点击后查看大图。
bindSheet弹出半模态组件。用于半模态展示界面,如分享框。
bindMenu弹出菜单,点击组件后弹出。需要Menu菜单的场景,如一般应用的“+”号键。
bindContextMenu弹出菜单,长按或者右键点击后弹出。长按浮起效果,一般结合拖拽框架使用,如桌面图标长按浮起。
bindPopup弹出Popup弹框。Popup弹框场景,如点击后对某个组件进行临时说明。
if通过if新增或删除组件。用来在某个状态下临时显示一个界面,这种方式的返回导航需要由开发者监听接口实现。

使用bindContentCover构建全屏模态转场效果

bindContentCover接口用于为组件绑定全屏模态页面,在组件出现和消失时可通过设置转场参数ModalTransition添加过渡动效。

  1. 定义全屏模态转场效果bindContentCover

  2. 定义模态展示界面。

    // 通过@Builder构建模态展示界面
    @Builder MyBuilder() {
      Column() {
        Text('my model view')
      }
      // 通过转场动画实现出现消失转场动画效果,transition需要加在builder下的第一个组件 
      .transition(TransitionEffect.translate({ y: 1000 }).animation({ curve: curves.springMotion(0.6, 0.8) }))
    }

  3. 通过模态接口调起模态展示界面,通过转场动画或者共享元素动画去实现对应的动画效果。

    // 模态转场控制变量
    @State isPresent: boolean = false;
    ​
    Button('Click to present model view')
      // 通过选定的模态接口,绑定模态展示界面,ModalTransition是内置的ContentCover转场动画类型,这里选择None代表系统不加默认动画,通过onDisappear控制状态变量变换
      .bindContentCover(this.isPresent, this.MyBuilder(), {
                modalTransition: ModalTransition.NONE,
                onDisappear: () => {
                  this.isPresent = !this.isPresent;
                }
              })
      .onClick(() => {
        // 改变状态变量,显示模态界面
        this.isPresent = !this.isPresent;
      })

完整示例代码和效果如下。

import curves from '@ohos.curves';
​
interface PersonList {
  name: string,
  cardnum: string
}
​
@Entry
@Component
struct BindContentCoverDemo {
  private personList: Array<PersonList> = [
    { name: '王**', cardnum: '1234***********789' },
    { name: '宋*', cardnum: '2345***********789' },
    { name: '许**', cardnum: '3456***********789' },
    { name: '唐*', cardnum: '4567***********789' }
  ];
  // 第一步:定义全屏模态转场效果bindContentCover
  // 模态转场控制变量
  @State isPresent: boolean = false;
​
  // 第二步:定义模态展示界面
  // 通过@Builder构建模态展示界面
  @Builder
  MyBuilder() {
    Column() {
      Row() {
        Text('选择乘车人')
          .fontSize(20)
          .fontColor(Color.White)
          .width('100%')
          .textAlign(TextAlign.Center)
          .padding({ top: 30, bottom: 15 })
      }
      .backgroundColor(0x007dfe)
​
      Row() {
        Text('+ 添加乘车人')
          .fontSize(16)
          .fontColor(0x333333)
          .margin({ top: 10 })
          .padding({ top: 20, bottom: 20 })
          .width('92%')
          .borderRadius(10)
          .textAlign(TextAlign.Center)
          .backgroundColor(Color.White)
      }
​
      Column() {
        ForEach(this.personList, (item: PersonList, index: number) => {
          Row() {
            Column() {
              if (index % 2 == 0) {
                Column()
                  .width(20)
                  .height(20)
                  .border({ width: 1, color: 0x007dfe })
                  .backgroundColor(0x007dfe)
              } else {
                Column()
                  .width(20)
                  .height(20)
                  .border({ width: 1, color: 0x007dfe })
              }
            }
            .width('20%')
​
            Column() {
              Text(item.name)
                .fontColor(0x333333)
                .fontSize(18)
              Text(item.cardnum)
                .fontColor(0x666666)
                .fontSize(14)
            }
            .width('60%')
            .alignItems(HorizontalAlign.Start)
​
            Column() {
              Text('编辑')
                .fontColor(0x007dfe)
                .fontSize(16)
            }
            .width('20%')
          }
          .padding({ top: 10, bottom: 10 })
          .border({ width: { bottom: 1 }, color: 0xf1f1f1 })
          .width('92%')
          .backgroundColor(Color.White)
        })
      }
      .padding({ top: 20, bottom: 20 })
​
      Text('确认')
        .width('90%')
        .height(40)
        .textAlign(TextAlign.Center)
        .borderRadius(10)
        .fontColor(Color.White)
        .backgroundColor(0x007dfe)
        .onClick(() => {
          this.isPresent = !this.isPresent;
        })
    }
    .size({ width: '100%', height: '100%' })
    .backgroundColor(0xf5f5f5)
    // 通过转场动画实现出现消失转场动画效果
    .transition(TransitionEffect.translate({ y: 1000 }).animation({ curve: curves.springMotion(0.6, 0.8) }))
  }
​
  build() {
    Column() {
      Row() {
        Text('确认订单')
          .fontSize(20)
          .fontColor(Color.White)
          .width('100%')
          .textAlign(TextAlign.Center)
          .padding({ top: 30, bottom: 60 })
      }
      .backgroundColor(0x007dfe)
​
      Column() {
        Row() {
          Column() {
            Text('00:25')
            Text('始发站')
          }
          .width('30%')
​
          Column() {
            Text('G1234')
            Text('8时1分')
          }
          .width('30%')
​
          Column() {
            Text('08:26')
            Text('终点站')
          }
          .width('30%')
        }
      }
      .width('92%')
      .padding(15)
      .margin({ top: -30 })
      .backgroundColor(Color.White)
      .shadow({ radius: 30, color: '#aaaaaa' })
      .borderRadius(10)
​
      Column() {
        Text('+ 选择乘车人')
          .fontSize(18)
          .fontColor(Color.Orange)
          .fontWeight(FontWeight.Bold)
          .padding({ top: 10, bottom: 10 })
          .width('60%')
          .textAlign(TextAlign.Center)
          .borderRadius(15)// 通过选定的模态接口,绑定模态展示界面,ModalTransition是内置的ContentCover转场动画类型,这里选择DEFAULT代表设置上下切换动画效果,通过onDisappear控制状态变量变换。
          .bindContentCover(this.isPresent, this.MyBuilder(), {
            modalTransition: ModalTransition.DEFAULT,
            onDisappear: () => {
              this.isPresent = !this.isPresent;
            }
          })
          .onClick(() => {
            // 第三步:通过模态接口调起模态展示界面,通过转场动画或者共享元素动画去实现对应的动画效果
            // 改变状态变量,显示模态界面
            this.isPresent = !this.isPresent;
          })
      }
      .padding({ top: 60 })
    }
  }
}

img

3.2. 共享元素转场

当路由进行切换时,可以通过设置组件的 sharedTransition 属性将该元素标记为共享元素并设置对应的共享元素转场动效。

// 页面 A
组件(){
  
}
  .sharedTransition('标记', { duration: 500 })
​
// 页面 B
组件(){
  
}
  .sharedTransition('标记', { duration: 500 })

动画属性

名称参数类型是否必填参数描述
durationnumber描述共享元素转场动效播放时长。 默认值:1000。 单位:毫秒。
curveCurve | string | ICurve10+描述共享元素转场动效播放时长。 默认值:1000。 单位:毫秒。
delaynumber延迟播放时间。 默认值:0。 单位:毫秒。
motionPathMotionPathOptions运动路径信息。
zIndexnumber设置Z轴。
typeSharedTransitionEffectType动画类型。 默认值:SharedTransitionEffectType.Exchange。

效果

代码

Index.ets:

import router from '@ohos.router'

export interface ProjectItem {
  id:number
  img: ResourceStr
  title: string
  desc: string
  sub: string
}

@Entry
@Component
struct Index {
  @State projectItem: ProjectItem[] = [
    {
      id:1,
      img: $r('app.media.project02'),
      title: '后台管理系统',
      desc: '以Vue技理后台后台管理系统面试题面试整理',
      sub: '后台系统'
    },
    {
      id:2,
      img: $r('app.media.project01'),
      title: '在线问医生平台(医疗类)',
      desc: '通过vue3+ts实现的在线医疗问诊相关技术整理',
      sub: 'H5项目'
    },
    {
      id:3,
      img: $r('app.media.project03'),
      title: '鸿蒙知识点',
      desc: '以ArkTS与ArkUI为主的鸿蒙基础知识点讲解',
      sub: '鸿蒙应用'
    },
  ]

  build() {
    Column() {
      Row() {
        Text('项目').fontSize(20)
      }
      Column() {
        ForEach(this.projectItem, (item: ProjectItem) => {
          Row({ space: 10 }) {
            Image(item.img).height('100%')
              .sharedTransition(item.id.toString(),{duration:500
              // ,type:SharedTransitionEffectType.Static
              })
            Column() {
              Column({ space: 5 }) {
                Text(item.title).fontSize(18)
                Text(item.desc).fontSize(12).fontColor('#666')
              }
              .alignItems(HorizontalAlign.Start)

              Text(item.sub).fontSize(10)
                .padding(3).fontColor(Color.Green)
                .backgroundColor('rgb(241, 244, 244)')
            }.height('100%')
            .alignItems(HorizontalAlign.Start)
            .justifyContent(FlexAlign.SpaceBetween)
          }.width('100%').height(110)
          .padding({ top: 15, bottom: 15 })
          .onClick(() => {
            router.pushUrl({
              url: "pages/DetailItem",
              params: item
            })
          })
        })
      }
    }.width('100%').height('100%').padding(15)
  }
}

DetailItem.ets:

import router from '@ohos.router'
import { ProjectItem } from '../pages/Index'

@Entry
@Component
struct DetailPage {
  aboutToAppear(): void {
    const data = router.getParams() as ProjectItem
    this.data = data
  }

  @State data: ProjectItem = { id: 0 ,img: '', title: '', desc: '', sub: '' }
  @State isShow: boolean = true

  build() {
    Column() {

      Stack() {
        Column({ space: 30 }) {
          Row() {
            Text('<').fontColor('#fff').fontSize(30)
          }
          Row({ space: 10 }) {
            Image(this.data.img).height(150)
              .sharedTransition(this.data.id.toString(),{ duration:500
                // ,type:SharedTransitionEffectType.Static
              })

            Column() {
              Text(this.data.title).fontSize(20).fontColor('#fff')
              Text(this.data.desc).fontColor('#fff')
                .maxLines(2)
                .textOverflow({ overflow: TextOverflow.Ellipsis })
                .width('65%')

              Text(`学习进度:10%`).fontColor('#999')
            }
            .alignItems(HorizontalAlign.Start)
            .height(150).justifyContent(FlexAlign.SpaceAround)
          }
        }
        .padding(20)
        .alignItems(HorizontalAlign.Start)

        Image($r('app.media.project_bg'))
          .opacity(0.2).width('100%')
          .onClick(() => {
            router.back({
              url: "pages/Index"
            })
          })
      }
      .height('100%')
      .alignContent(Alignment.TopStart)
      .backgroundColor('#683a18')
      .bindSheet($$this.isShow, this.BindSheetContent(), {
        height: 520, showClose: false
      })
    }
  }

  @Builder
  BindSheetContent() {
    Row() {
      Text('问题列表').fontSize(25).fontWeight(500).margin(20)
    }.justifyContent(FlexAlign.Start).width('100%')
  }
}

标签:模态,动画,鸿蒙,width,最新,组件,转场,属性
From: https://blog.csdn.net/m0_68038853/article/details/140314952

相关文章

  • 在Ubuntu中安装docker最新的docker(被墙)(转)
    在目前的情况下download.docker.com访问不是特别稳定的情况下,可以使用阿里的地址来进行更新一、安装1、检查环境1.1卸载旧版dockersudosuaptremovedockerdocker-enginedocker.iocontainerdrunc2、安装依赖apt-yinstallca-certificatescurlgnupglsb......
  • 扫描光效动画css实现
            想实现扫描生效的动画,主要是通过伪元素(::after)的定义,通常用于在元素后面添加装饰性的内容。在这个例子中,伪元素创建了一个动画效果,让它看起来像是一个扫描光效果。    主要css如下:.element{position:relative;/*使伪元素绝对定位相对于这......
  • 【免费】最新最详细的华为OD2024机试题,ABCD卷,有答案,很全,很新
    最新最详细的华为OD2024机试题,ABCD卷,有答案,很全,很新!+目前461题,亲测资料非常完整好用!!最近考试换为CD卷,CD卷题库是一样的,D卷为双机位监控,某些外包公司应聘的为D卷。其中资料中JAVA,python,+JavaScript,C语言都有包含的,绝对会对你有所帮助!!获取方式:https://pan.quark.cn/s/9b122f......
  • 鸿蒙开发的语言应该怎么选?
    省流推荐ArkTS(支持HarmonyOSNext),放弃类JS开发方式,也不推荐仓颉鸿蒙开发的语言应该怎么选?在2024/06之前,官方文档【3.0/4.1】中尚有大篇幅的Web开发文档,并且在2019-2023年,每年的鸿蒙开发者大会上,多次提到过Web开发模式然而在2024年开发者大会上,官方不在提及这......
  • 【全开源】2024最新版在线客服系统PHP源码(全新UI+终身使用+安装教程)
    PHP在线客服系统主要功能:1.用户信息用户提交:新用户可以通过表单留言输入相关信息,如用户名、密码、邮箱等,完成后获得唯一的用户ID和密码。2.客服管理客服信息管理:管理客服人员的基本信息,如姓名、工号、权限等。客服工作状态:实时显示客服人员的在线/离线状态,方便客户选择合......
  • 【2024最新】零基础如何学习挖漏洞?看这篇就够了(超详细)
    文章目录前言什么是漏洞挖掘学习漏洞挖掘的正确顺序漏洞挖掘需要具备的知识漏洞挖掘需要做什么有关漏洞挖掘的其他想法漏洞的复杂性团队工作写在最后==如何入门学习网络安全【黑客】==【----帮助网安学习,以下所有学习资料文末免费领取!----】大纲学习教程面试刷题资料......
  • 面壁智能发布端侧 AI 应用开发平台;快手推出肖像动画技术 LivePortrait丨 RTE 开发者日
      开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(Real-TimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编辑的个人观点,......
  • Stable Diffusion 七月份最新整合包!本地安装保姆级教程~
    什么是stablediffusion?stablediffusion是在2022年发布的基于扩散模型的文本到图像生成模型,起初它只有一堆api供开发者使用,可以说非常难上手,随着2023年5月由AUTOMATIC1111大佬基于SDAPI开发的SDWebUI的发布,SD第一次有了操作界面,福音,绝对的福音,感谢大佬~更新到今天,功能......
  • SpringBoot彩蛋之定制启动画面
    写在前面在日常开发中,我们经常会看到各种各样的启动画面。例如以下几种①spring项目启动画面②mybatisplus启动画面③若依项目启动画面还有很多各式各样好看的启动画面,那么怎么定制这些启动画面呢?一、小试牛刀①新建一个SpringBoot项目②在项目的resources目录下新......
  • 【深度学习】探讨最新的深度学习算法、模型创新以及在图像识别、自然语言处理等领域的
    深度学习作为人工智能领域的重要分支,近年来在算法、模型以及应用领域都取得了显著的进展。以下将探讨最新的深度学习算法与模型创新,以及它们在图像识别、自然语言处理(NLP)等领域的应用进展。一、深度学习算法与模型创新新型神经网络结构Transformer及其变种:近年来,Transformer......