老规矩先上代码,
1 <template> 2 <div class="animate"> 3 <canvas id="canvas" width="300" height="300"></canvas> 4 <el-button id="toggle">▷</el-button> 5 </div> 6 </template> 7 8 <script> 9 import { fabric } from "fabric"; 10 export default { 11 data() { 12 return { 13 tempModel: [{ left: 0 }, { top: 0 }, { opacity: 0 }], 14 }; 15 }, 16 mounted() { 17 let playing = false; 18 var canvas = new fabric.Canvas("canvas", { backgroundColor: "#ddd" }); 19 var rect = new fabric.Rect({ 100, height: 50, left: 100, top: 100 }); 20 21 //animate(设置动画属性,动画结束值,可选对象) 22 //可选对象为动画详细信息,包括持续时间、回调、缓动等 23 //在每个动画帧上调用canvas.renderAll才能够看到实际的动画,重新渲染 24 rect.animate("angle", 360, { 25 duration: 2000, 26 onChange: () => playing && canvas.renderAll(), 27 onComplete: () => playing && setAnimate(rect), 28 easing: fabric.util.ease.easeInOutCubic, 29 }); 30 31 canvas.add(rect); 32 33 // 左上方按钮 34 document.querySelector("#toggle").addEventListener("click", (e) => { 35 const targetEl = e.target; 36 // When playing is true, it should save the statement. 37 if (playing) { 38 targetEl.innerHTML = "▷"; 39 this.tempModel.left = canvas.getObjects()[0].left; 40 this.tempModel.top = canvas.getObjects()[0].top; 41 this.tempModel.opacity = canvas.getObjects()[0].opacity; 42 } else { 43 // Else, it should load in the shape what'll move. 44 targetEl.innerHTML = "▢"; 45 // think about the initial suitation, it should be divided. 46 if (this.tempModel.left) { 47 rect.set("left", this.tempModel.left); 48 rect.set("top", this.tempModel.top); 49 rect.set("opacity", this.tempModel.opacity); 50 } 51 setAnimate(rect); 52 } 53 // Change statement model 54 playing = !playing; 55 }); 56 // 取得乱数 57 function getRandomInt(min, max) { 58 return Math.floor(Math.random() * (max - min + 1)) + min; 59 } 60 61 // 设定动画函数 62 function setAnimate(rect) { 63 // rect.animate("angle", 360, { 64 // duration: getRandomInt(1000, 5000), 65 // // easing: fabric.util.ease.easeInOutCubic, 66 // onChange: () => { 67 // canvas.renderAll(); 68 // }, 69 // onComplete: () => setAnimate(rect), 70 71 // // onComplete: () => playing && setAnimate(rect), 72 // }); 73 74 // 变化透明度 75 rect.animate("opacity", getRandomInt(0.2, 1), { 76 duration: getRandomInt(1000, 5000), 77 }); 78 // 变化座标 79 rect.animate("left", getRandomInt(0, 300), { 80 easing: fabric.util.ease.easeInOutCubic, 81 duration: getRandomInt(1000, 5000), 82 }); 83 // 变化座标 84 rect.animate("top", getRandomInt(0, 300), { 85 onChange: () => { 86 playing && canvas.renderAll(); 87 }, 88 onComplete: () => playing && setAnimate(rect), 89 easing: fabric.util.ease.easeInOutCubic, 90 duration: getRandomInt(1000, 5000), 91 }); 92 } 93 }, 94 }; 95 </script> 96 <style> 97 </style>
效果图
第一个旋转动画不知道为什么没了,不过这个保存暂停时状态,即将运动之前取出状态再装入的思路挺好的。