123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- <template>
- <!-- #ifdef H5||APP-PLUS -->
- <view class="c-lottie" :style="{width,height}" :lottieData="lottieData" :change:lottieData="lottie.render" :fun='fun'
- :change:fun='lottie.callPlayer'>
- <div :id='myCanvasId'></div>
- </view>
- <!-- #endif -->
- <!-- #ifdef MP -->
- <view class="c-lottie" :style="{width,height}">
- <canvas class="canvas" :id="myCanvasId" type="2d"></canvas>
- </view>
- <!-- #endif -->
- </template>
- <script>
- /**
- * c-lottie Lottie组件
- * @property {String} canvasId 画布id
- * @property {String} width 图像宽度 默认750rpx 单位rpx/px
- * @property {String} height 图像高度 默认750rpx 单位rpx/px
- * @property {String} src Lottie文件地址 小程序只支持网络地址
- * @property {String} data Lottie文件data
- * @property {Boolean} autoPlay 是否自动播放 默认true
- * @property {Boolean} loop 是否循环播放 默认值为 true
- * @property {String} renderer 渲染模式 默认值为canvas 可选值 svg|canvas 小程序不支持
- * @property {Boolean} isOnChange 是否开启播放进度监听 默认false false时不触发EnterFrame
- * @event {Function()} Complete 监听动画播放完成
- * @event {Function()} LoopComplete 监听当前循环播放完成
- * @event {Function()} EnterFrame 监听动画播放进度
- * @event {Function()} SegmentStart 监听开始播放一个动画片段
- * @event {Function()} dataReady 当动画的所有部分都已加载时触发
- * @event {Function()} dataFailed 当部分动画无法加载时触发
- * 组件内方法统一使用 call(funName, args) 调用player实例方法 详见文档
- * */
- import uuid from './js/uuid.js'
- // #ifdef MP&VUE3
- import lottie from 'lottie-miniprogram'
- // #endif
- // #ifdef MP&VUE2
- import lottie from '../../node_modules/lottie-miniprogram'
- // #endif
- // #ifdef MP
- let player, context, myCanvas;
- // #endif
- export default {
- props: {
- canvasId: {
- type: String
- },
- width: {
- type: String,
- default: '750rpx'
- },
- height: {
- type: String,
- default: '750rpx'
- },
- src: {
- type: String,
- },
- data: {
- type: String,
- },
- autoPlay: { //是否自动播放
- type: Boolean,
- default: true
- },
- loop: { //是否循环播放 默认值为 true
- type: Boolean,
- default: true
- },
- renderer: { //渲染模式 默认值为canvas 可选值 svg
- type: String,
- default: 'canvas',
- },
- isOnChange: {
- type: Boolean,
- default: false
- }
- },
- emits: ['Complete', 'LoopComplete', 'EnterFrame', 'SegmentStart','dataReady','dataFailed'],
- data() {
- return {
- fun: {}
- }
- },
- computed: {
- myCanvasId() {
- if (!this.canvasId) {
- return 'c' + uuid(18)
- } else {
- return this.canvasId
- }
- },
- lottieData() {
- return {
- myCanvasId: this.myCanvasId,
- width: this.width,
- height: this.height,
- src: this.src,
- data: this.data,
- autoPlay: this.autoPlay,
- loop: this.loop,
- renderer: this.renderer,
- isOnChange: this.isOnChange
- }
- }
- },
- watch: {
- lottieData() {
- // #ifdef MP
- this.render()
- // #endif
- }
- },
- methods: {
- call(name, args) {
- this.fun = {name,args}
- // #ifdef MP
- this.callPlayer(this.fun)
- // #endif
- },
- // #ifdef MP
- getContext() {
- return new Promise((resolve) => {
- const {
- pixelRatio
- } = uni.getSystemInfoSync()
- uni.createSelectorQuery()
- .in(this)
- .select(`#${this.myCanvasId}`)
- .fields({
- node: true,
- size: true
- })
- .exec(res => {
- const {
- width,
- height
- } = res[0]
- const canvas = res[0].node
- resolve({
- canvas,
- width,
- height,
- pixelRatio
- })
- })
- })
- },
- async render() {
- if (player) {
- // console.log(player);
- // call('stop')
- this.call('destroy', player)
- }
- let {
- canvas,
- width,
- height,
- pixelRatio
- } = await this.getContext()
- myCanvas = canvas
- context = canvas.getContext('2d')
- //避免出现锯齿问题
- context.scale(pixelRatio, pixelRatio)
- canvas.width = width * pixelRatio
- canvas.height = height * pixelRatio
- lottie.setup(myCanvas)
- player = lottie.loadAnimation({
- loop: this.loop,
- autoplay: this.autoPlay,
- // 动画json的本地数据
- animationData: this.data,
- //远程动画。一定要把json格式的文件放到服务器中,并且注意域名是合法的
- path: this.src,
- rendererSettings: {
- context,
- },
- })
- player.addEventListener('data_ready',(val)=>{ //当动画的所有部分都已加载时
- this.$emit('dataReady', val)
- })
- player.addEventListener('data_failed',(val)=>{ //当部分动画无法加载时
- this.$emit('dataFailed', val)
- })
- player.onComplete = (val) => { //动画播放完成触发
- // console.log('动画播放完成触发',val);
- this.$emit('Complete', val)
- }
- player.onLoopComplete = (val) => { //当前循环播放完成触发
- // console.log('当前循环播放完成触发',val);
- this.$emit('LoopComplete', val)
- }
- if (this.isOnChange) {
- player.onEnterFrame = (val) => { //播放动画的时候触发
- // console.log('播放动画的时候触发',val);
- this.$emit('EnterFrame', val)
- }
- }
- player.onSegmentStart = (val) => { //开始播放一个动画片段的时候触发
- // console.log('开始播放一个动画片段的时候触发',val);
- this.$emit('SegmentStart', val)
- }
- },
- callPlayer(val) {
- if (!val.name) return;
- let {name,args} = val
- // console.log(name, args);
- if (Array.isArray(args)) {
- player[name](...args)
- } else {
- player[name](args)
- }
- },
- // #endif
- // #ifndef MP
- receiveRenderData(val) {
- // console.log(val);
- this.$emit(val.name, val.val)
- }
- // #endif
- },
- mounted() {
- // #ifdef MP
- this.render()
- // #endif
- },
- beforeDestroy() {
- // 组件卸载销毁实例
- this.call('destroy')
- }
- }
- </script>
- <!-- #ifndef MP -->
-
- <!-- #ifdef VUE3 -->
- <script lang="renderjs" src='./js/render.js' module='lottie'></script>
- <!-- #endif -->
-
- <!-- #ifdef VUE2 -->
- <script lang="renderjs" module='lottie'>
- import lottieRender from "./js/render.js"
- export default {
- mixins:[lottieRender],
- }
- </script>
- <!-- #endif -->
- <!-- #endif -->
- <style lang="scss" scoped>
- .c-lottie {
- // width: v-bind(width);
- // height: v-bind(height);
- /* #ifndef MP */
- div {
- width: 100%;
- height: 100%;
- }
- /* #endif */
- .canvas {
- width: 100%;
- height: 100%;
- }
- }
- </style>
|