资讯详情

在uni-App(Vue)中使用 SVG + JS 自定义动画:模拟关键帧

问题

为什么要用?SVG制作动画?

SVG它是矢量图形,放大后不会失真,动画看起来很丝滑,可以达到很多平面动画效果。CSS动画比不上

在Vue中使用SVG有哪些困难?

  • 注意载入顺序mounted() 记得在这个过程中输入动画 在destroyed() 过程结束后销毁。
  • 注意SVG内的锚点定位问题,将你所需的图形放在合适的位置上,并保证屏幕尺寸改变时不会影响到内部的位置。

示例

在这种情况下,我需要做一个Loading 当网络发起请求时,图标会显示在不同的页面上,loading 为此,我制作了一个可重用的组件来实现这一目标:

上传的gif因为压缩,看起来卡住了,其实很丝滑。 请添加图片描述 代码中有我自己创建的实现关键帧的方法,每隔10次ms 计算一次svg内图的属性,并赋值,10ms一帧已经超过了动画视觉标准。如果你想减少设备负载,你可以适当地提高它。如果你想榨干设备的性能,你可以提高它。

<template>  <view>   <svg height="100%" width="100%" viewBox="-20.654044750430295 -21.996557659208264 1241.3080895008607 1243.9931153184166" x="0" y="0" id="document" class="disable-on-play" fill="transparent">       <g id="elements" style="isolation: isolate;">           <defs id="dynamic-definitions">               <linearGradient id="ellipse-q79an5euegn--stroke" x1="0" y1="0.5" x2="1" y2="0.5" spreadMethod="pad" gradientUnits="objectBoundingBox">                   <stop id="ellipse-q79an5euegn--stroke-stop-0" offset="0" stop-color="rgb(0,163,255)"></stop>                   <stop id="ellipse-q79an5euegn--stroke-stop-1" offset="1" stop-color="rgb(0,52,232)"></stop>               </linearGradient>               <linearGradient id="ellipse-51gfnuexh6c--fill" x1="0" y1="0.5" x2="1" y2="0.5" spreadMethod="pad" gradientUnits="objectBoundingBox">
		                <stop id="ellipse-51gfnuexh6c--fill-stop-0" offset="0" stop-color="rgb(0,163,255)"></stop>
		                <stop id="ellipse-51gfnuexh6c--fill-stop-1" offset="1" stop-color="rgb(0,52,232)"></stop>
		            </linearGradient>
		            <linearGradient id="ellipse-th8rfzjaes--fill" x1="0" y1="0.5" x2="1" y2="0.5" spreadMethod="pad" gradientUnits="objectBoundingBox">
		                <stop id="ellipse-th8rfzjaes--fill-stop-0" offset="0" stop-color="rgb(0,163,255)"></stop>
		                <stop id="ellipse-th8rfzjaes--fill-stop-1" offset="1" stop-color="rgb(0,52,232)"></stop>
		            </linearGradient>
		        </defs>
		        <defs id="definitions"></defs>
		        <g id="elements-wrapper" width="1200" height="1200">
		            <ellipse ref="outter" id="ellipse-q79an5euegn" rx="500" ry="500" transform="matrix(0 -1 1 0 600 600)" 
					fill="none" stroke="url(#ellipse-q79an5euegn--stroke)" stroke-width="100" 
					stroke-linecap="round" :stroke-dasharray="d1 + ' ' + d2" 
					style="mix-blend-mode: normal; paint-order: fill;" 
					:stroke-dashoffset="strokeDashoffset"></ellipse>
		            <ellipse ref="inner" id="ellipse-51gfnuexh6c" rx="928.571429" ry="928.571429" 
					:transform="'matrix(' + sH + ' 0 0 ' + sW + ' 600 600)'" fill="url(#ellipse-51gfnuexh6c--fill)" 
					stroke="none" stroke-width="15" style="mix-blend-mode: normal; paint-order: fill;"></ellipse>
		        </g>
		    </g>
		    <path d="M-20.654044750430295 -21.996557659208264 h1241.3080895008607 v1243.9931153184166 h-1241.3080895008607 z M0 0 h1200 v1200 h-1200 z" fill-rule="evenodd" id="overlay"></path>    <!---->    <!---->
		    <g id="tool-selection">
		        <g></g>
		        <g>            <!---->            <!----></g>        <!----></g>
		</svg>
	</view>
</template>

<script>
	export default { 
        
		name:"ts-loading",
		data() { 
        
			return { 
        
				d1:0,
				d2:3600,
				strokeDashoffset:0,
				sH:0,
				sW:0,
				timer:null,
			};
		},
		computed:{ 
        
			
		},
		mounted() { 
        
			this.addInterval()
		},
		onShow() { 
        
			
		},
		destroyed() { 
        
			clearInterval(this.timer)
			this.timer = null
		},
		methods:{ 
        
			addInterval(){ 
        
				const that = this
				var t = 0; // 时间
				var et = 2000; //持续时间
				var keyframes = [0,1000,2000]
				var scaleFrames = [0,0.35,0]
				var stockeOffestFrames = [0,0,-3600]
				var stockDashes1Frames = [0,3600,3600]
				var stockDashes2Frames = [3600,3600,3600]
				var targetScale = 0;
				var targetstockeOffest = 0;
				var targetstockDashes1 = 0;
				var targetstockDashes2 = 3600;
				this.timer = setInterval(() =>{ 
        
				for (var i = 0; i < keyframes.length; i++) { 
        
					if(t === keyframes[i]){ 
        
						targetScale = scaleFrames[i + 1]
						targetstockeOffest = stockeOffestFrames[i + 1]
						targetstockDashes1 = stockDashes1Frames[i + 1]
						targetstockDashes2 = stockDashes2Frames[i + 1]
						break
					}
				}
				that.d1  = that.d1  + (targetstockDashes1 - that.d1 ) / 10
				that.d2 = that.d2 + (targetstockDashes2 - that.d2) / 10
				that.strokeDashoffset = that.strokeDashoffset + (targetstockeOffest - that.strokeDashoffset) / 10
				that.sH = that.sH + (targetScale - that.sH) / 10
				that.sW = that.sW + (targetScale - that.sW) / 10
				t += 10
				if(t >= et){ 
        
					t = 0;
					that.d1 = 0
					that.d2 = 3600
					that.strokeDashoffset = 0
					that.sH = 0
					that.sW = 0
					
				}
			},10)
			}
		}
	}
</script>

<style>
	.outter{ 
        
		stroke-width: 15;
		transform-origin: center;
		transform: rotateZ(-90deg);
		stroke: linear-gradient(to right,#00a3ff,#0034e8) 1 10;
	}
	.inner{ 
        
		transform-origin: center;
		background-color:  linear-gradient(to right,#00a3ff,#0034e8) 1 10;
	}
</style>

调用方式:

<view style="text-align: center;width: 100%" v-show="loading">
	<ts-loading style="margin: auto;" class="main-loading" ></ts-loading>
</view>

标签: 250v1200uf高压电容125v1200uf电机电容

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台