index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <template>
  2. <view style="width: 375px;height: 120px;">
  3. </view>
  4. </template>
  5. <script lang="uts">
  6. import {
  7. LottieAnimationView,
  8. LottieAnimation,
  9. LottieLoopMode
  10. } from 'Lottie'
  11. import {
  12. URL,
  13. Bundle
  14. } from 'Foundation'
  15. import {
  16. UIView
  17. } from "UIKit"
  18. import {
  19. UTSiOS
  20. } from "DCloudUTSFoundation"
  21. //原生提供以下属性或方法的实现
  22. export default {
  23. /**
  24. * 组件名称,也就是开发者使用的标签
  25. */
  26. name: "animation-view",
  27. /**
  28. * 组件涉及的事件声明,只有声明过的事件,才能被正常发送
  29. */
  30. emits: ['bindended'], // 当播放到末尾时触发 ended 事件(自然播放结束会触发回调,循环播放结束及手动停止动画不会触发)
  31. /**
  32. * 属性声明,组件的使用者会传递这些属性值到组件
  33. */
  34. props: {
  35. /**
  36. * 动画资源地址,支持远程 URL 地址和本地绝对路径
  37. */
  38. "path": {
  39. type: String,
  40. default: ""
  41. },
  42. /**
  43. * 动画是否自动播放
  44. */
  45. "autoplay": {
  46. type: Boolean,
  47. default: false
  48. },
  49. /**
  50. * 动画是否循环播放
  51. */
  52. "loop": {
  53. type: Boolean,
  54. default: false
  55. },
  56. /**
  57. * 是否隐藏动画
  58. */
  59. "hidden": {
  60. type: Boolean,
  61. default: false
  62. },
  63. /**
  64. * 动画操作,可取值 play、pause、stop
  65. */
  66. "action": {
  67. type: String,
  68. default: "stop"
  69. }
  70. },
  71. data() {
  72. return {
  73. }
  74. },
  75. watch: {
  76. "path": {
  77. handler(newValue: string, oldValue: string) {
  78. if (this.autoplay) {
  79. this.playAnimation()
  80. }
  81. },
  82. immediate: false //创建时是否通过此方法更新属性,默认值为false
  83. },
  84. "loop": {
  85. handler(newValue: boolean, oldValue: boolean) {
  86. if (newValue) {
  87. this.$el.loopMode = LottieLoopMode.loop
  88. } else {
  89. this.$el.loopMode = LottieLoopMode.playOnce
  90. }
  91. },
  92. immediate: false //创建时是否通过此方法更新属性,默认值为false
  93. },
  94. "autoplay": {
  95. handler(newValue: boolean, oldValue: boolean) {
  96. if (newValue) {
  97. this.playAnimation()
  98. }
  99. },
  100. immediate: false //创建时是否通过此方法更新属性,默认值为false
  101. },
  102. "action": {
  103. handler(newValue: string, oldValue: string) {
  104. const action = newValue
  105. if (action == "play" || action == "pause" || action == "stop") {
  106. switch (action) {
  107. case "play":
  108. this.playAnimation()
  109. break;
  110. case "pause":
  111. this.$el.pause()
  112. break;
  113. case "stop":
  114. this.$el.stop()
  115. break;
  116. default:
  117. break;
  118. }
  119. } else {
  120. // 非法入参,不管
  121. }
  122. },
  123. immediate: false //创建时是否通过此方法更新属性,默认值为false
  124. },
  125. "hidden": {
  126. handler(newValue: boolean, oldValue: boolean) {
  127. this.$el.isHidden = this.hidden
  128. },
  129. immediate: false //创建时是否通过此方法更新属性,默认值为false
  130. },
  131. },
  132. expose: ['setRepeatMode'],
  133. methods: {
  134. // 需要对外暴露的方法
  135. // 设置 RepeatMode
  136. setRepeatMode(repeatMode: string) {
  137. if (repeatMode == "RESTART") {
  138. if (this.loop) {
  139. this.$el.loopMode = LottieLoopMode.loop
  140. } else {
  141. this.$el.loopMode = LottieLoopMode.playOnce
  142. }
  143. } else if (repeatMode == "REVERSE") {
  144. if (this.loop) {
  145. this.$el.loopMode = LottieLoopMode.autoReverse
  146. } else {
  147. this.$el.loopMode = LottieLoopMode.repeatBackwards(1)
  148. }
  149. }
  150. },
  151. // 不对外暴露的方法
  152. // 播放动画
  153. playAnimation() {
  154. // 构建动画资源 url
  155. var animationUrl: URL | null
  156. if (this.path.hasPrefix("http")) {
  157. animationUrl = new URL(string = this.path)
  158. } else {
  159. const filePath = UTSiOS.getResourcePath(this.path)
  160. animationUrl = new URL(fileURLWithPath = filePath)
  161. }
  162. if (animationUrl != null) {
  163. // 加载动画 LottieAnimation
  164. LottieAnimation.loadedFrom(url = animationUrl!, closure = (animation: LottieAnimation | null):
  165. void => {
  166. if (animation != null) {
  167. // 加载成功开始播放
  168. this.$el.animation = animation
  169. this.$el.play(completion = (isFinish: boolean): void => {
  170. if (isFinish) {
  171. // 播放完成回调事件
  172. this.fireEvent("bindended")
  173. }
  174. })
  175. }
  176. })
  177. } else {
  178. console.log("url 构建失败,请检查 path 是否正确")
  179. }
  180. }
  181. },
  182. created() { //创建组件,替换created
  183. },
  184. NVBeforeLoad() { //组件将要创建,对应前端beforeMount
  185. //可选实现,这里可以提前做一些操作
  186. },
  187. NVLoad(): LottieAnimationView { //创建原生View,必须定义返回值类型(Android需要明确知道View类型,需特殊校验)
  188. // 初始化 Lottie$el
  189. const animationView = new LottieAnimationView()
  190. // 默认只播放一次动画
  191. animationView.loopMode = LottieLoopMode.playOnce
  192. return animationView
  193. },
  194. NVLoaded() { //原生View已创建
  195. /// 更新 props 中定义的属性值
  196. if (this.loop) {
  197. this.$el.loopMode = LottieLoopMode.loop
  198. }
  199. this.$el.isHidden = this.hidden
  200. if (this.autoplay) {
  201. this.playAnimation()
  202. }
  203. },
  204. NVLayouted() { //原生View布局完成
  205. //可选实现,这里可以做布局后续操作
  206. },
  207. NVBeforeUnload() { //原生View将释放
  208. //可选实现,这里可以做释放View之前的操作
  209. },
  210. NVUnloaded() { //原生View已释放
  211. //可选实现,这里可以做释放View之后的操作
  212. },
  213. unmounted() { //组件销毁
  214. //可选实现
  215. }
  216. }
  217. </script>