提交 13135a26 编写于 作者: 杜庆泉's avatar 杜庆泉

增加lottie-anim 示例

上级 0f3a5927
...@@ -1481,6 +1481,15 @@ ...@@ -1481,6 +1481,15 @@
} }
}, },
// #endif // #endif
// #ifdef APP-ANDROID
{
"path": "pages/template/lottie-anim/lottie-anim",
"style": {
"navigationBarTitleText": "lottie动画-需要自定义基座",
"enablePullDownRefresh": false
}
},
// #endif
// #ifdef APP || WEB // #ifdef APP || WEB
{ {
"path": "uni_modules/uni-pay-x/pages/success/success", "path": "uni_modules/uni-pay-x/pages/success/success",
......
...@@ -200,6 +200,15 @@ ...@@ -200,6 +200,15 @@
open: false, open: false,
pages: [] as Page[], pages: [] as Page[],
}, },
// #endif
// #ifdef APP-ANDROID
{
id: 'lottie-anim',
url: 'lottie-anim',
name: 'lottie动画-需要自定义基座',
open: false,
pages: [] as Page[],
},
// #endif // #endif
// #ifdef WEB // #ifdef WEB
{ {
......
<template>
<div>
<button @tap="changeUrl">播放本地动画资源</button>
<button @tap="changeServerUrl">播放远程动画资源</button>
<button @tap="changeAutoPlay">测试AutoPlay</button>
<button @tap="changeLoop">测试Loop</button>
<button @tap="changeAction(1)">测试action play</button>
<button @tap="changeAction(2)">测试action pause</button>
<button @tap="changeAction(3)">测试action stop</button>
<animation-view ref="animView" :path="animUrl" :autoplay="autoplay" :loop="loop" :action="action"
:hidden="hidden" @bindended="testAnimEnd"
:style="{width:widthNum+'rpx',height:heightNum+'px',background:yanse}">
</animation-view>
</div>
</template>
<script>
export default {
data() {
return {
hidden: false,
autoplay: false,
action: "play",
loop: false,
yanse: "red",
widthNum: 750,
heightNum: 200,
comShow: true,
animUrl: "/static/anim_a.json"
}
},
methods: {
changeAutoPlay: function() {
this.autoplay = !this.autoplay
},
changeUrl: function() {
if (this.animUrl == "/static/anim_a.json") {
this.animUrl = "/static/anim_b.json"
} else {
this.animUrl = "/static/anim_a.json"
}
},
changeServerUrl: function() {
this.animUrl = "https://b.bdstatic.com/miniapp/images/lottie_example_one.json"
},
changeAction: function(type:number) {
if (type == 1) {
this.action = "play"
} else if (type == 2) {
this.action = "pause"
} else if (type == 3) {
this.action = "stop"
}
},
changeLoop: function() {
this.loop = !this.loop
},
testAnimEnd: function() {
console.log("testAnimEnd");
}
}
}
</script>
此差异已折叠。
此差异已折叠。
## 1.0.5(2024-06-14)
调整iOS平台组件内的默认样式
## 1.0.4(2024-05-24)
+ 修复 Android uni-app x 正式包模式下,可能不展示动画的Bug
## 1.0.3(2024-04-11)
修复Android平台 修正组件名称为 `animation-view`
## 1.0.2(2024-03-22)
修复Android平台云打包编译失败的Bug
## 1.0.1(2023-04-07)
修复ios平台本地编译会报 swift 版本不兼容的bug
## 1.0.0(2023-01-16)
实现android/ios平台animation-view组件,仅支持nvue页面
{
"id": "uni-animation-view",
"displayName": "animation-view",
"version": "1.0.5",
"description": "使用uts组件开发,实现animation-view组件",
"keywords": [
"animation-view",
"lottie"
],
"repository": "",
"engines": {
"HBuilderX": "^3.7.0"
},
"dcloudext": {
"type": "component-uts",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-android": {
"minVersion": "21"
},
"app-ios": {
"minVersion": "11"
}
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
# animation-view
> animation-view组件是[uts插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html),需 HBuilderX 3.7.0+
> 使用文档:[https://uniapp.dcloud.net.cn/component/animation-view.html](https://uniapp.dcloud.net.cn/component/animation-view.html)
### 属性说明
|属性名|类型|默认值|说明|
|:-|:-|:-|:-|
| path | String | | 动画资源地址,支持本地路径和网络路径 |
| loop | Boolean | false | 动画是否循环播放 |
| autoplay | Boolean | true | 动画是否自动播放 |
| action | String | play | 动画操作,可取值 play、pause、stop |
| hidden | Boolean | true | 是否隐藏动画 |
| @bindended | EventHandle | | 当播放到末尾时触发 ended 事件(自然播放结束会触发回调,循环播放结束及手动停止动画不会触发) |
**注意**
* animation-view 仅App端nvue页面支持
* App端实现使用了Lottie三方SDK,参考开源项目:[Lottie for Android](https://github.com/airbnb/lottie-android)[Lottie for iOS](https://github.com/airbnb/lottie-ios)
* App-Android平台要求Android5(API Leavel 21)及以上系统
* App-iOS平台要求iOS11及以上版本系统
### 代码示例
```html
<template>
<div>
<animation-view class="animation" :path="path" :loop="loop" :autoplay="autoplay" :action="action"
:hidden="hidden" @bindended="lottieEnd">
</animation-view>
<button @click="playLottie" type="primary">{{status}}lottie动画</button>
</div>
</template>
<script>
export default {
data() {
return {
path: 'https://b.bdstatic.com/miniapp/images/lottie_example_one.json',
loop: false,
autoplay: false,
action: 'play',
hidden: false,
status: '暂停'
}
},
methods: {
playLottie() {
this.action = ('play' !== this.action) ? 'play' : 'pause';
this.status = ('pause' === this.action) ? '播放' : '暂停';
},
lottieEnd() {
this.status = '播放';
this.action = 'stop';
console.log('动画播放结束');
}
}
}
</script>
<style>
.animation {
width: 750rpx;
height: 300rpx;
background-color: #FF0000;
margin-bottom: 20px;
}
</style>
```
此差异已折叠。
{
"minSdkVersion": "21",
"dependencies": [
"com.airbnb.android:lottie:3.4.0"
]
}
<template>
<view class="defaultStyles">
</view>
</template>
<script lang="uts">
import Animator from 'android.animation.Animator'
import TextUtils from 'android.text.TextUtils'
import View from 'android.view.View'
import LottieAnimationView from 'com.airbnb.lottie.LottieAnimationView'
import LottieDrawable from 'com.airbnb.lottie.LottieDrawable'
import FileInputStream from 'java.io.FileInputStream'
class CustomAnimListener extends Animator.AnimatorListener {
comp: UTSComponent < LottieAnimationView >
constructor(com: UTSComponent < LottieAnimationView > ) {
super();
this.comp = com
}
override onAnimationStart(animation: Animator) {}
override onAnimationEnd(animation: Animator, isReverse: Boolean) {
this.comp.$emit("bindended")
}
override onAnimationEnd(animation: Animator) {}
override onAnimationCancel(animation: Animator) {}
override onAnimationRepeat(animation: Animator) {}
}
//原生提供以下属性或方法的实现
export default {
name: "animation-view",
/**
* 当播放到末尾时触发 ended 事件(自然播放结束会触发回调,循环播放结束及手动停止动画不会触发)
*/
emits: ['bindended'],
props: {
/**
* 动画资源地址,目前只支持绝对路径
*/
"path": {
type: String,
default: ""
},
/**
* 动画是否自动播放
*/
"autoplay": {
type: Boolean,
default: false
},
/**
* 动画是否循环播放
*/
"loop": {
type: Boolean,
default: false
},
/**
* 是否隐藏动画
*/
"hidden": {
type: Boolean,
default: false
},
/**
* 动画操作,可取值 play、pause、stop
*/
"action": {
type: String,
default: "stop"
}
},
data() {
return {
}
},
watch: {
"path": {
handler(newPath: string) {
if(this.$el != null){
let lottieAnimationView = this.$el!
if (!TextUtils.isEmpty(newPath)) {
if (newPath.startsWith("http://") || newPath.startsWith("https://")) {
lottieAnimationView.setAnimationFromUrl(newPath)
} else {
// uni-app x 正式打包会放在asset中,需要特殊处理
let realJsonPath = UTSAndroid.getResourcePath(newPath)
if(realJsonPath.startsWith("/android_asset")){
lottieAnimationView.setAnimation(realJsonPath.substring(15))
}else{
lottieAnimationView.setAnimation(new FileInputStream(realJsonPath),newPath)
}
}
}
if (this.autoplay) {
lottieAnimationView.playAnimation()
}
}
},
immediate: false
},
"loop": {
handler(newLoop: Boolean) {
if(this.$el != null){
if (newLoop) {
this.$el!.repeatCount = Int.MAX_VALUE
} else {
// 不循环则设置成1次
this.$el!.repeatCount = 0
}
if (this.autoplay) {
this.$el!.playAnimation()
}
}
},
immediate: false
},
"autoplay": {
handler(newValue: boolean) {
if(this.$el != null){
if (newValue) {
this.$el!.playAnimation()
}
}
},
immediate: false
},
"action": {
handler(newAction: string) {
if (newAction == "play" || newAction == "pause" || newAction == "stop") {
if(this.$el != null){
if (this.action == "play") {
this.$el!.playAnimation()
} else if (this.action == "pause") {
this.$el!.pauseAnimation()
} else if (this.action == "stop") {
this.$el!.cancelAnimation()
this.$el!.clearAnimation()
}
}
} else {
// 非法入参,不管
}
},
immediate: false
},
"hidden": {
handler(newValue: boolean) {
if(this.$el != null){
if (newValue) {
this.$el!.visibility = View.GONE
} else {
this.$el!.visibility = View.VISIBLE
}
}
},
immediate: false
},
},
methods: {
setRepeatMode(repeat: string) {
if(this.$el != null){
if ("RESTART" == repeat) {
this.$el!.repeatMode = LottieDrawable.RESTART
} else if ("REVERSE" == repeat) {
this.$el!.repeatMode = LottieDrawable.RESTART
}
}
},
},
NVLoad(): LottieAnimationView {
let lottieAnimationView = new LottieAnimationView($androidContext)
return lottieAnimationView
},
NVLoaded() {
if(this.$el != null){
this.$el!.repeatMode = LottieDrawable.RESTART;
this.$el!.visibility = View.GONE
this.$el!.repeatCount = 0
this.$el!.addAnimatorListener(new CustomAnimListener(this))
}
}
}
</script>
<style>
/* 定义默认样式值, 组件使用者没有配置时使用 */
.defaultStyles {
width: 750rpx;
height: 240rpx;
}
</style>
{
"deploymentTarget": "11",
"validArchitectures": [
"arm64",
"x86_64"
]
}
<template>
<view style="width: 375px;height: 120px;">
</view>
</template>
<script lang="uts">
import {
LottieAnimationView,
LottieAnimation,
LottieLoopMode
} from 'Lottie'
import {
URL,
Bundle
} from 'Foundation'
import {
UIView
} from "UIKit"
import {
UTSiOS
} from "DCloudUTSFoundation"
//原生提供以下属性或方法的实现
export default {
/**
* 组件名称,也就是开发者使用的标签
*/
name: "animation-view",
/**
* 组件涉及的事件声明,只有声明过的事件,才能被正常发送
*/
emits: ['bindended'], // 当播放到末尾时触发 ended 事件(自然播放结束会触发回调,循环播放结束及手动停止动画不会触发)
/**
* 属性声明,组件的使用者会传递这些属性值到组件
*/
props: {
/**
* 动画资源地址,支持远程 URL 地址和本地绝对路径
*/
"path": {
type: String,
default: ""
},
/**
* 动画是否自动播放
*/
"autoplay": {
type: Boolean,
default: false
},
/**
* 动画是否循环播放
*/
"loop": {
type: Boolean,
default: false
},
/**
* 是否隐藏动画
*/
"hidden": {
type: Boolean,
default: false
},
/**
* 动画操作,可取值 play、pause、stop
*/
"action": {
type: String,
default: "stop"
}
},
data() {
return {
}
},
watch: {
"path": {
handler(newValue: string, oldValue: string) {
if (this.autoplay) {
this.playAnimation()
}
},
immediate: false //创建时是否通过此方法更新属性,默认值为false
},
"loop": {
handler(newValue: boolean, oldValue: boolean) {
if (newValue) {
this.$el.loopMode = LottieLoopMode.loop
} else {
this.$el.loopMode = LottieLoopMode.playOnce
}
},
immediate: false //创建时是否通过此方法更新属性,默认值为false
},
"autoplay": {
handler(newValue: boolean, oldValue: boolean) {
if (newValue) {
this.playAnimation()
}
},
immediate: false //创建时是否通过此方法更新属性,默认值为false
},
"action": {
handler(newValue: string, oldValue: string) {
const action = newValue
if (action == "play" || action == "pause" || action == "stop") {
switch (action) {
case "play":
this.playAnimation()
break;
case "pause":
this.$el.pause()
break;
case "stop":
this.$el.stop()
break;
default:
break;
}
} else {
// 非法入参,不管
}
},
immediate: false //创建时是否通过此方法更新属性,默认值为false
},
"hidden": {
handler(newValue: boolean, oldValue: boolean) {
this.$el.isHidden = this.hidden
},
immediate: false //创建时是否通过此方法更新属性,默认值为false
},
},
expose: ['setRepeatMode'],
methods: {
// 需要对外暴露的方法
// 设置 RepeatMode
setRepeatMode(repeatMode: string) {
if (repeatMode == "RESTART") {
if (this.loop) {
this.$el.loopMode = LottieLoopMode.loop
} else {
this.$el.loopMode = LottieLoopMode.playOnce
}
} else if (repeatMode == "REVERSE") {
if (this.loop) {
this.$el.loopMode = LottieLoopMode.autoReverse
} else {
this.$el.loopMode = LottieLoopMode.repeatBackwards(1)
}
}
},
// 不对外暴露的方法
// 播放动画
playAnimation() {
// 构建动画资源 url
var animationUrl: URL | null
if (this.path.hasPrefix("http")) {
animationUrl = new URL(string = this.path)
} else {
const filePath = UTSiOS.getResourcePath(this.path)
animationUrl = new URL(fileURLWithPath = filePath)
}
if (animationUrl != null) {
// 加载动画 LottieAnimation
LottieAnimation.loadedFrom(url = animationUrl!, closure = (animation: LottieAnimation | null):
void => {
if (animation != null) {
// 加载成功开始播放
this.$el.animation = animation
this.$el.play(completion = (isFinish: boolean): void => {
if (isFinish) {
// 播放完成回调事件
this.fireEvent("bindended")
}
})
}
})
} else {
console.log("url 构建失败,请检查 path 是否正确")
}
}
},
created() { //创建组件,替换created
},
NVBeforeLoad() { //组件将要创建,对应前端beforeMount
//可选实现,这里可以提前做一些操作
},
NVLoad(): LottieAnimationView { //创建原生View,必须定义返回值类型(Android需要明确知道View类型,需特殊校验)
// 初始化 Lottie$el
const animationView = new LottieAnimationView()
// 默认只播放一次动画
animationView.loopMode = LottieLoopMode.playOnce
return animationView
},
NVLoaded() { //原生View已创建
/// 更新 props 中定义的属性值
if (this.loop) {
this.$el.loopMode = LottieLoopMode.loop
}
this.$el.isHidden = this.hidden
if (this.autoplay) {
this.playAnimation()
}
},
NVLayouted() { //原生View布局完成
//可选实现,这里可以做布局后续操作
},
NVBeforeUnload() { //原生View将释放
//可选实现,这里可以做释放View之前的操作
},
NVUnloaded() { //原生View已释放
//可选实现,这里可以做释放View之后的操作
},
unmounted() { //组件销毁
//可选实现
}
}
</script>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册