【VUE3】uni-app集成animation.css,按钮触发公共方法,无需绑定样式变量

animation是个好东西,实现了一些常用的方法。最近集成到uni-app中,发现网上的通常都是使用绑定变量的方式来实现。少了通过指定ref触发的模式,总感觉有那么别扭。撸了一上午代码,把这个功能实现了出来。

集成animation.css

集成animation.css没啥好说的,在网上下载4.1.1版的animate.min.css。然后修改头部,添加小程序的兼容补丁代码:

page {

  --animate-duration: 1s;

  --animate-delay: 1s;

  --animate-repeat: 1;

}

然后放到statics/css/animate.min.css

引入animation.css

在系统的全局文件导入即可,我使用uni-best的模板,导入的位置就是style/index.scss

// 增补字体库
@import '@/static/css/fonts.css';

// 增补动画库
@import '@/static/css/animate.min.css';

.test {
  // 可以通过 @apply 多个样式封装整体样式
  @apply mt-4 ml-4;

  padding-top: 4px;
  color: red;
}
/** 增补快速样式 **/
.x-items-left {
  // 水平排列
  @apply flex flex-row;
}

.x-items-center {
  // 水平排列,垂直居中
  @apply flex flex-row items-center;
}

.x-items-stretch {
  // 水平排列,垂直拉伸
  @apply flex flex-row items-stretch;
}

.x-items-between {
  // 水平排列,垂直居中,分散对齐
  @apply flex flex-row items-center justify-between;
}

.y-items-center {
  // 垂直排列,水平居中
  @apply flex flex-col items-center;
}

.y-items-stretch {
  // 垂直排列,水平拉伸
  @apply flex flex-col items-stretch;
}

.flex-center {
  // 完全居中,使用flex定位
  @apply flex justify-center items-center;
}

.absolute-center {
  // 完全居中,使用 absolute定位
  @apply absolute left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2;
}

编写执行方法

这里有个神坑,就是app(Android)下addEventListener后,removeEventListener相当不好使。移除一次后再添加就监测不到了,索性添加一个对象cache,手动判断保证只添加一次

下面代码也是在unibest环境下的

const ANIMATE_CSS_PERFIX = 'animate__'
const ANIMATE_CSS_CLASS = ANIMATE_CSS_PERFIX + 'animated'
const switchAnimateClass: (className: string, animationTypes?: string[]) => string = (
  className,
  animationTypes
) => {
  const classNames: string[] = className.split(/\s+/)
  if (!classNames.includes(ANIMATE_CSS_CLASS)) {
    // 没有指定动画,不处理
    return className
  }
  const filtered = classNames.filter(
    (item) => !(item.startsWith(ANIMATE_CSS_PERFIX) && item !== ANIMATE_CSS_CLASS)
  )
  if (animationTypes) {
    animationTypes.forEach((item) => filtered.push(ANIMATE_CSS_PERFIX + item))
  }
  return filtered.join(' ')
}

const instanceCache = new Set<any>()

/**
 * animatecss集成动画效果执行一次,如果循环执行直接设置样式即可
 * @param ref vue的对象ref
 * @param animationType 动画类型以及时间配置等,例如animate__headShake只需要输入headShake
 * @param callback 动画执行结束后的回调,可以实现连续动画(APP不支持)
 */
export function animatecss(ref: Ref, animationType: string | string[], callback?: () => void) {
  if (ref && ref.value) {
    if (process.env.UNI_PLATFORM === 'app') {
      const instance = ref.value
      // 如果提供了回调函数,则监听动画结束事件
      const animationTypes: string[] = [].concat(animationType)
      instance.className = switchAnimateClass(instance.className, animationTypes)
      const onAnimationEnd = () => {
        try {
          if (callback) {
            callback()
          }
        } finally {
          // 移除事件监听器,避免多次绑定
          const afterClass: string[] = instance.className.split(' ')
          nextTick(() => {
            instance.className = switchAnimateClass(instance.className)
          })
        }
      }
      if (!instanceCache.has(instance)) {
        instance.addEventListener('animationend', onAnimationEnd)
        instanceCache.add(instance)
      }
    } else {
      const instance = ref.value.$el
      const classList: DOMTokenList = instance.classList
      const animationTypes = [].concat(animationType).map((item) => ANIMATE_CSS_PERFIX + item)

      // 如果提供了回调函数,则监听动画结束事件
      classList.add(...animationTypes)

      const onAnimationEnd = () => {
        try {
          if (callback) {
            callback()
          }
        } finally {
          // 移除事件监听器,避免多次绑定
          instance.removeEventListener('animationend', onAnimationEnd)
          classList.remove(...animationTypes)
        }
      }
      instance.addEventListener('animationend', onAnimationEnd)
    }
  }
}

使用方法:元素预先添加animate__animated样式,再在调用时传入ref对象和要执行的动画方法即可

      <view class="x-items-left mb-60rpx">
        <view class="flex-1" />
        <view ref="tips" class="w-120rpx text-teal animate__animated">密码登录</view>
      </view>

执行动画

const tips = ref(null)

const getCode = (type: string = 'headShake') => {
  utils.animatecss(tips, type)
}

由于支持callback,你还可以把多个动画组合起来,例如这个:
摆一摆,再跳一跳

const getCode = (type: string = 'animate__headShake') => {
  utils.animatecss(tips, 'headShake', () => {
    utils.animatecss(tips, 'bounce')
  })
}

还可以添加多个控制参数指定,例如慢慢摇,快快跳

  utils.animatecss(tips, ['headShake', 'slower'], () => {
    utils.animatecss(tips, ['bounce', 'faster'])
  })

控制参数组合见animate.css官方网站

https://animate.style/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UniApp中,如果你想修改`uni.showModal`组件的样式UniApp 使用了 Vue.js 的单文件组件(.vue)来开发,并且提供了自定义主题和样式的能力。`uni.showModal`是一个原生API,但它允许你在组件内部通过`style`或` scoped slot`来覆盖默认样式。 1. **直接在组件内部**:你可以为`modal`元素添加一个`v-bind:class`属性,并根据需要动态绑定类名,然后在`.vue`文件的`<style>`标签或 scoped `style`块中定义对应的CSS规则。例如: ```html <template> <view v-bind:class="{ customModal: isCustom }"> <!-- modal内容 --> <uni-modal @onShow="showModal" @onHide="hideModal"> <view class="custom-modal-wrap"> <!-- 你的模态内容 --> </view> </uni-modal> </view> </template> <script> export default { data() { return { isCustom: false, // 根据需求控制是否使用自定义样式 }; }, methods: { showModal() { this.isCustom = true; }, hideModal() { this.isCustom = false; // 隐藏后恢复默认样式 }, }, styles: { .customModal: { /* 在这里编写你的自定义modal样式 */ background-color: '#f00'; // 例如改变背景颜色 width: '80%', // 可以调整宽度 padding: '20px', // 自定义内边距 }, .custom-modal-wrap { /* 可能需要的子元素样式 */ }, }, }; </script> ``` 2. **全局样式表**:如果你希望在整个应用中重用这些修改,可以在`app.vue`或`main.css`中添加全局样式。但请注意,这样可能会影响到所有使用`uni.showModal`的地方。 记得在隐藏`uni.showModal`后,将`isCustom`设置回`false`,以便切换回默认样式,防止样式混乱。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值