xAnimate - Library
这是一个非常强大且简单的动画操作类库,性能高,动画平缓。事件回调机制控制,灵活调度,可以方便的让你写交互类动画组件。
演示
在线预览
在线模拟尺寸:
使用
你可以参考demo页面/pages/index/xanimate,来进行参考使用。
ts
//导入参数类型
import { XANIMATE_OPIONS } from "@/uni_modules/tmx-ui/interface.uts"
//导入库
import { xAnimate } from "@/uni_modules/tmx-ui/index.uts"
你需要 new xAnimate(Unielement,options) 创建一个动画操作类,参数options类型为:XANIMATE_OPIONS。
第一个参数你可以通过this.$refs["xx"] as Unielement;来获得赋值给第一个参数
ts
//options类型为:XANIMATE_OPIONS。
export type XANIMATE_OPIONS = {
/** 时间 */
duration?:number,
/** 动画类型 */
timingFunction?:string,
/** -1表示无限循环播放,0表示不会播放,大于0表示播放该次数后停止播放 */
loop?:number,
/** 表示循环播放时,是否左右来回播放,而不是始终从开始到结束这样的状态播放 */
tyty?:boolean,
/** 四位数数组的动画映射值,优先级高于timingFunction */
bezier?:number[],
isDescPlay?:booelan,是否顺序执行动画,而不是一起调用动画属性。
/** 动画结束后的回调函数 */
complete?:()=>void,
/** 动画开始 */
start?:()=>void,
/** 动画运行中执行 */
frame?:(propress:number)=>void
}
xAnimate实例创建
函数 | 参数 | 说明 |
---|---|---|
xAnimate | (ele:Unielement,ops:XANIMATE_OPIONS) | 使用new xAnimate创建并返回一个xAnimate实例 |
实例属性
属性名 | 类型 | 说明 |
---|---|---|
easingList | Map<string,number[]> | 返回自带的map类的动画映射表 |
element | Unielement | 返回元素对象 |
timingFunction | String | 动画映射名称,默认为linear |
duration | Number | 动画持续时间,默认为500 |
running | Boolean | 当前是否运行中 |
pauseing | Boolean | 当前是否暂停中 |
progress | Number | 当前的播放进度0-1 |
reverse | Boolean | 当前是否反转了动画 |
tyty | Boolean | 当前是否是循环播放模式 |
loop | Number | 默认播放时,循环的次数,默认为1,-1时为永久循环播放 |
实例方法
attr函数可以链式调用不断的添加属性动画,达到联合播放动画的效果,isOnley:true时添加相同属性时以最后一次为准,否则允许相同属性动画
函数 | 参数 | 说明 |
---|---|---|
setAniReverse | (n:boolean|null=null) | 设置reverse返转状态 |
setLoops | (n:number|null = null) | 设置loop,播放时可持续播放的次数 |
setDurations | (n:number|null = null) | 设置duration,播放时可持续播放的时间 |
setTytys | (n:number|null = null) | 设置tyty,播放时loop循环时是否左右来回播放的模式 |
attr | (name:string,from : string, to : string,isOnley:boolean) | isOnley表示多次添加name时否保留最后一次,默认是ture,name是css合法的值比如left,right,opacity,border-width等,同时也支持颜色的设置比如:border-color,background颜色过渡动画,也支持transform,但需要设置为其属性名称比如:scale,translateX等 |
play | () | 播放或者继续播放动画 |
stop | () | 结束动画,并把动画设置到最后一贴的位置 |
pause | () | 暂停动画 |
enterFrame | (()=>void) | 刷新回调,回调速率与你的硬件有关系,如果在电脑大概72Hz屏幕上大概是16ms调用一次 |
以上方法均返回xAnimate实例,即可链式调用比如new xAnimate(ele,{ele:"xx"}).attr("left",'0%','100%').attr("opacity",'1','0').play()
示例
vue
<template>
<!-- #ifdef APP -->
<scroll-view style="flex:1">
<!-- #endif -->
<view class=" white round-10 overflow pa-24 mx-24 mb-24">
<text class="text-size-g text-weight-b">xAnimate - Library</text>
<text class="text-size-m text-grey mt-10 line-8">这是动画核心类库,异常简便,为你开发动画类组件和效果提供了高效流畅性能的动力</text>
<text class="text-size-m text-grey mt-10 line-8">不管是web还是安卓均采用系统及的刷新回调,使得动画异常流畅。</text>
</view>
<view class=" white round-10 overflow pa-24 mx-24 mb-24">
<text class="text-size-g text-weight-b">刷新回调</text>
<text class="text-size-m text-grey mt-10 line-8">可以利用此创建吸引视觉强交互动画</text>
</view>
<x-sheet>
<view ref="canvas" style="height: 150px;background-color: #f7f7f7;" class="mb-32">
</view>
<x-button :block="true" @click="enterFramAni">播放</x-button>
</x-sheet>
<view ref="vid" style="width:10%;height:100px; background-color: rgb(28, 132, 255);"></view>
<x-sheet>
</x-sheet>
<x-sheet class="flex flex-row">
<x-button width="160rpx" class="mr-10" size="normal" @click="play">播放/继续</x-button>
<x-button width="160rpx" class="mr-10" color="success" size="normal" @click="pause">暂停</x-button>
<x-button width="160rpx" class="mr-10" color="error" size="normal" @click="stop">停止</x-button>
<x-button width="160rpx" size="normal" color="orange" @click="setReverse">反转播放</x-button>
</x-sheet>
<view class=" white round-10 overflow pa-24 mx-24 mb-24">
<text class="text-size-g text-weight-b">联合动画动画及函数</text>
<text class="text-size-m text-grey mt-10 line-8">它是支持常见的动画类型比如:ease,linear等内置了24种常见动画,当然也是支持自定义动画函数。</text>
</view>
<x-sheet>
<view class="flex flex-row flex-row-center-center mb-24">
<view ref="scaleIds"
style="width:100px;height:100px;background-color: rgb(28, 132, 255);border-style: solid;border-color: rgb(255, 165, 0);border-width: 10px;">
</view>
</view>
<x-button :block="true" @click="palyScale">播放</x-button>
</x-sheet>
<view class=" white round-10 overflow pa-24 mx-24 mb-24">
<text class="text-size-g text-weight-b">动画按顺序执行</text>
<text class="text-size-m text-grey mt-10 line-8">支持官方所述的所有css动画属性:如border,left,width,opactiy等等</text>
<text class="text-size-m text-grey mt-10 line-8">如果要播放transfrom属性时,请直接写属性名比如:scale,scaleX等</text>
</view>
<x-sheet>
<view class="flex flex-row flex-row-center-center mb-24">
<view ref="unionAni" style="width:100px;height:100px;background-color: rgb(28, 132, 255);"></view>
</view>
<x-button :block="true" @click="palyunionAni">播放</x-button>
</x-sheet>
<view class=" white round-10 overflow pa-24 mx-24 mb-24">
<text class="text-size-g text-weight-b">其它属性</text>
<text class="text-size-m text-grey mt-10 line-8">loop:-1时可永久播放及tyty设置为true可来回循环动画衔接</text>
</view>
<x-sheet class="flex flex-row flex-row-center-center">
<view ref="repeatRef" style="width:50px;height:50px;background-color: rgba(28, 132, 255,1);"></view>
</x-sheet>
<x-sheet class="flex flex-row flex-row-center-between">
<x-button width="46%" class="mr-10" size="normal" @click="repeatPlay">播放/继续</x-button>
<x-button width="46%" class="mr-10" color="success" size="normal" @click="repeatPlayStop">暂停</x-button>
</x-sheet>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
ts
<script>
import { XANIMATE_OPIONS } from "@/uni_modules/interface.uts"
import { xAnimate } from "@/uni_modules/tmx-ui/index.uts"
export default {
data() {
return {
xani: null as null | xAnimate,
repeatAni: null as null | xAnimate,
xani2: null as null | xAnimate,
enterAni: null as null | xAnimate,
isRealCtx: false
};
},
onUnload() {
this.xani?.stop()
this.repeatAni?.stop()
this.xani2?.stop()
this.enterAni?.stop()
this.isRealCtx = false;
},
methods: {
enterFramAni() {
let width = 0
let height = 0
let ratio = 1;
let dom = this.$refs['canvas'] as UniElement;
let ctx = null as DrawableContext | null
width = dom.getBoundingClientRect().width!
height = dom.getBoundingClientRect().height!
// #ifdef APP
ctx = dom!.getDrawableContext()!
// #endif
// #ifdef WEB
let canvas = document.createElement("canvas") as HTMLCanvasElement;
if (dom.querySelector('canvas')) {
canvas = dom.querySelector('canvas')
} else {
dom.appendChild(canvas)
this.isRealCtx=true;
}
canvas.width = width
canvas.height = height
canvas.style = 'width:100%;height:100%'
ctx = canvas.getContext('2d')!
ratio = window.devicePixelRatio;
// #endif
if (this.enterAni == null) {
this.enterAni = new xAnimate(null, {} as XANIMATE_OPIONS);
}
let max = width - 20
let maxy = height - 20
let x = 0
let y = 0
let fz = 1
let fzy = 1
this.enterAni!.enterFrame(function () {
ctx!.reset()
ctx!.beginPath()
ctx!.fillStyle = "red"
x = x + 1 * fz
y = y + 3 * fzy
ctx!.arc(x * ratio, y * ratio, 10 * ratio, 0, Math.PI * 2)
ctx!.fill()
ctx!.beginPath()
// #ifdef APP
ctx!.update()
// #endif
if (x * ratio >= max) {
fz = -1;
}
if (x <= 0) {
fz = 1;
}
if (y * ratio >= maxy) {
fzy = -1;
}
if (y <= 0) {
fzy = 1;
}
})
},
palyunionAni() {
let ele = this.$refs['unionAni'] as UniElement
if (this.xani2 != null) {
this.xani2!.stop();
}
this.xani2 = new xAnimate(
ele,
{
timingFunction: 'easeInOutBack',
duration: 1000,
isDescPlay: true,
complete() {
console.log('动画结束')
}
} as XANIMATE_OPIONS)
this.xani2!.attr('background-color', 'orange', 'primary')
.attr('scale', '1', '0', false)
.attr('scale', '0', '1', false)
.attr('left', '0px', '100px', false)
.attr('left', '100px', '-100px', false)
.attr('rotate', '0deg', '360deg', false)
.attr('background-color', 'primary', 'orange', false)
.attr('background-color', 'orange', 'primary', false)
.attr('left', '-100px', '0px', false)
.play()
},
palyScale() {
let ele = this.$refs['scaleIds'] as UniElement
new xAnimate(
ele,
{
timingFunction: 'easeInOutBack',
complete() {
new xAnimate(
ele,
{
timingFunction: 'easeInOutBack',
} as XANIMATE_OPIONS)
.attr('border-color', 'yellow', 'red')
.attr('border-width', '0px', '20px')
.play()
}
} as XANIMATE_OPIONS)
.attr('border-color', 'red', 'yellow')
.attr('scale', '0', '1')
.attr('opacity', '0', '1')
.play()
},
play() {
if (this.xani == null) {
let ele = this.$refs['vid'] as UniElement
this.xani = new xAnimate(
ele,
{
duration: 1500,
start() {
console.log("动画开始")
},
complete() {
console.log("动画结束")
},
frame(propress : number) {
// console.log("动画进度", propress)
}
} as XANIMATE_OPIONS)
}
this.xani!
.attr('width', '10%', '100%')
.attr('background-color', 'rgba(28, 132, 255)', 'red')
.play()
},
stop() {
this.xani?.stop()
},
pause() {
this.xani?.pause()
},
setReverse() {
this.xani?.setAniReverse()
this.xani?.play()
},
repeatPlay() {
let ele = this.$refs['repeatRef'] as UniElement
if (this.repeatAni == null) {
this.repeatAni = new xAnimate(
ele,
{
loop: -1,
tyty: false,
duration: 1000
} as XANIMATE_OPIONS)
}
this.repeatAni!.attr('rotate', '0deg', '360deg').play()
},
repeatPlayStop() {
if (this.repeatAni != null) {
this.repeatAni!.pause();
}
}
}
}
</script>
css
<style lang="scss">
</style>