html5 canvas 完成光源沿不规律相对路径健身运动

2021-02-22 05:40 jianzhan

svg让动漫沿着不规律相对路径健身运动

查阅svg文本文档后发现,svg动漫健身运动有两种完成方法,且都十分简易,但针对100%完成设计方案师得出的实际效果有很大的间距

应用offset-path偏位相对路径和offset-roate偏位角度让元素沿着不规律相对路径走

<!DOCTYPE html>
	<html>
	<head>
		<title>offset-path/offset-roate</title>
	</head>
	<style type="text/css">
		* {
			padding: 0;
			margin: 0;
			box-sizing: border-box;
		}
		body {
			background: #000;
		}
		.line {
			width: 80px;
			height: 3px;
	        position: absolute;
	        background: red;
			offset-path: path("M10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500");
	        animation: move 10s linear infinite;
		}
		@keyframes move {
			100% {
				offset-distance: 2000px;
			}
		}
		.line1 {
			position: absolute;
			left: 100px;
			width: 20px;
			height: 20px;
			border-radius: 50%;
			background: red;
			offset-path: path("M0,0a72.5,72.5 0 1,0 145,0a72.5,72.5 0 1,0 ⑴45,0");
	   		offset-rotate: 0deg;
	   		animation: load 1.8s cubic-bezier(0.86, 0, 0.07, 1) infinite;
	   		animation-delay: 0.147s;
	    	animation-fill-mode: forwards;
		}
		@keyframes load {
			from {
		        offset-distance: 0;
		    }
		    to {
		        offset-distance: 100%;
		    }
		}
	</style>
	<body>
		<h2>相对路径偏位</h2>
		<div class="line"></div>
		<svg width="100%" height="600px" version="1.0" id="svg1">
			<path d="M10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500" fill="#tranparent" stroke="#FFF"></path>
		</svg>
		<h2>角度偏位</h2>
		<div class="line1">
		</div>
	</body>
	</html>

此种方法的限定是翻转元素没法随相对路径开展沒有规律性的转变

应用stroke-dasharray和stroke-dashoffset让相对路径边线动起来

stroke-dasharray:设定shap和text 边框虚线的实线长度与实线之间的间距(虚线长度)
stroke-dashoffser:设定边框线条相对默认设置部位的偏位(恰逢:向左,负值:向右)

<!DOCTYPE html>
	<html>
	<head>
		<title>stroke-dasharray/stroke-dashoffser</title>
	</head>
	<style type="text/css">
		* {
			padding: 0;
			margin: 0;
			box-sizing: border-box;
		}
		body {
			background: #000;
			color: #fff;
		}
		.move {
			animation: moving 5s infinite;
		}
		@keyframes moving {
			0% {
				stroke-dashoffset: 80px;
			}
			100% {
				stroke-dashoffset: ⑴600px;
			}
		}
	</style>
	<body>
	<h2>设定stroke-dasharray</h2>
	<b>storke-dasharray设定为80 ,此时实线和实线间距1样</b>
	<svg width="100%" height="600px" version="1.0" id="svg1">
		<path d="M10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500" fill="#tranparent" stroke="#FFF" stroke-dasharray="80"></path>
	</svg>
	<b>storke-dasharray设定为80 320,此时实线和是实线间距的1/4</b>
	<svg width="100%" height="600px" version="1.0" id="svg1">
		<path d="M10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500" fill="#tranparent" stroke="#FFF" stroke-dasharray="80 320"></path>
	</svg>
	<h2>设定stroke-dashoffset让边线相对原始部位产生偏位</h2>
	<svg width="100%" height="600px" version="1.0" id="svg1">
		<path d="M10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500" fill="#tranparent" stroke="#FFF" stroke-dasharray="80 320" stroke-dashoffset="40"></path>
	</svg>
	<h2>根据设定stroke-dasharray 和 stroke-dashoffset让边线动起来</h2>
	<svg width="100%" height="600px" version="1.0" id="svg1">
		<path d="M10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500" fill="#tranparent" stroke="#FFF"></path>
		<path d="M10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500" fill="#tranparent" stroke="red" stroke-dasharray="80 1600" stroke-dashoffset="0" class="move"></path>
	</svg>
	</body>
	</html>

此种方法根据边框偏位的实际效果能够设定追随相对路径的滚线条,可是没法设定线条的光源实际效果,即实线的黑影和实线的渐变色实际效果(渐变色地区需伴随着偏位相对路径的转变而转变)

canvas完成线条延不规律相对路径健身运动

线条完成

针对不规律相对路径,假如立即用画线条的方法完成光源,必须测算每个刚开始点和完毕点的部位,正中间还将会存在转折点点,测算起来十分不便,不能取
故这边采用canvas组成图型的方式,取线条和1个图型重合一部分(相近于灯罩)来完成光源实际效果
 

组成前
 


 

组成后
 

<!DOCTYPE html>
	<html>
	<head>
		<title>canvas完成不规律相对路径光效</title>
	</head>
	<style type="text/css">
		body {
			background: #000;
		}
		#wrap {
			position: absolute;
			width: 1200px;
			height: 600px
		}
	</style>
	<body>
		<div id="wrap">
			<canvas id="canvas" width="1200" height="600"></canvas>
		</div>
	</body>
	<script type="text/javascript">
		var path = 'M 10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500';
		var list = path.match(/([A-Z]([^A-Z]){1,})/g).map(item => {
			return {
				x: item.split(' ')[1],
				y: item.split(' ')[2],
				action: item.split(' ')[0],
			}
		});//获得每一个点部位
		var canvas = document.getElementById('canvas');
		var ctx = canvas.getContext('2d');
		ctx.strokeStyle = 'rgba(255,255,255,1)';
		function drawPath() {
			ctx.lineWidth = 3;
			ctx.beginPath();
			list.forEach(item => {
				if(item.action == 'M') ctx.moveTo(item.x, item.y);
				if(item.action == 'L') ctx.lineTo(item.x, item.y);
			});
			ctx.stroke();
		}
		drawPath();

		function drawLine() {
			//设定图型组成方法 默认设置source-over
			ctx.globalCompositeOperation = "destination-in";
			ctx.lineWidth = 60;
			ctx.beginPath();
			ctx.moveTo(40, 80);
			ctx.lineTo(200, 80);
			ctx.stroke();
		}
		drawLine();

	</script>
	</html>

让线条动起来

当大家完成好线条剩余就必须让线条动起来,因为线条是根据灯罩的方法来完成的,让线条健身运动只必须让灯罩动起来就好
 

<!DOCTYPE html>
	<html>
	<head>
		<title>canvas完成不规律相对路径光效</title>
	</head>
	<style type="text/css">
		body {
			background: #000;
		}
		#wrap {
			position: absolute;
			width: 1200px;
			height: 600px
		}
	</style>
	<body>
		<div id="wrap">
			<canvas id="canvas" width="1200" height="600"></canvas>
		</div>
	</body>
	<script type="text/javascript">
		var path = 'M 10 80 L 77.5 60 L 145 80 L 280 100 L 500 80 L 600 120 L 800 80 L 950 120 L 950 200 L 930 250 L 950 300 L 950 500';
		var list = path.match(/([A-Z]([^A-Z]){1,})/g).map(item => {
			return {
				x: item.split(' ')[1],
				y: item.split(' ')[2],
				action: item.split(' ')[0],
			}
		});//获得每一个点部位
		var step = 3;
		var x1, x2, y1, y2;//明确相对路径中最大最少点
		var timer;
		var canvas = document.getElementById('canvas');
		var ctx = canvas.getContext('2d');
		ctx.strokeStyle = 'rgba(255,255,255,1)';
		ctx.shadowColor = 'rgba(255,255,255,1)';
		ctx.lineCap = 'round';
		ctx.shadowBlur = 3;
		list.forEach(item => {
			x1 = !x1 || Number(item.x) < x1 ? Number(item.x) : x1;
			y1 = !y1 || Number(item.y) < y1 ? Number(item.y) : y1;
			x2 = !x2 || Number(item.x) > x2 ? Number(item.x) : x2;
			y2 = !y2 || Number(item.y) > y2 ? Number(item.y) : y2;
		});
		function drawPath() {
			ctx.lineWidth = 3;
			ctx.beginPath();
			list.forEach(item => {
				if(item.action == 'M') ctx.moveTo(item.x, item.y);
				if(item.action == 'L') ctx.lineTo(item.x, item.y);
			});
			//加上光效渐变色
			var grd = ctx.createLinearGradient(arrLine[arrLine.length - 1].x, arrLine[arrLine.length - 1].y, arrLine[0].x, arrLine[0].y);
			grd.addColorStop(0, 'rgba(255, 255, 255, 0)');   //界定渐变色线起始点色调
	        grd.addColorStop(1, 'rgba(255, 255, 255, 1)');  //界定渐变色线完毕点的色调
	        ctx.strokeStyle = grd;
			ctx.stroke();
		}
		//设计方案适合的原始线条情况
		var arrLine = Array(10).fill(0).map((item, inx) => {
			return {
				x: x1 - 20 * inx,
				y: y1 + 30,
			}
		});
		//随時间转变图型相对路径
		function getArrLine() {
			var isEnd
			arrLine = arrLine.map(item => {
				var x = item.x;
				var y = item.y;
				if(x < x2 - 30) {
					x = x + step > x2 ⑶0 ? x2 - 30 : x + step;
				} else if(x == x2 ⑶0 && y < y2) {
					y = y + step > y2 ? y2 : y + step;
				} else {
					isEnd = true;
				}
				return {
					x,
					y
				}
			});
			isEnd && timer && cancelAnimationFrame(timer);
		}
		//绘图图型
		function drawLine() {
			//设定图型组成方法 默认设置source-over
			ctx.globalCompositeOperation = "destination-in";
			ctx.lineWidth = 70;
			ctx.beginPath();
			arrLine.forEach((item, inx) => {
				if(inx == 0) {
					ctx.moveTo(item.x, item.y);
				} else {
					ctx.lineTo(item.x, item.y);
				}
			})
			ctx.stroke();
		}

		function start() {
			ctx.clearRect(0, 0, 1200, 600);
			ctx.globalCompositeOperation = 'source-over';
			drawPath();
			drawLine();
			getArrLine();
			timer = requestAnimationFrame(start);
		}

		timer = requestAnimationFrame(start);

	</script>
	</html>

这类完成方法也是有1定的标准限定,那便是相对路径可大致抽象性变成1个有1定规律性的图形或线条,例如上面demo中相对路径可抽象性变成1个矩形框的两侧,或是2条联接的平行线
大家务必从沒有实际标准的相对路径中抽象性出1个大致的标准,不一样相对路径标准不一样
上面的事例便是将不规律相对路径抽象性变成1个直角的标准相对路径
 

可提升点

这边寻找了2个可提升的点
1.時间方位上: 以便让动漫耗费较小,编码中的定时执行器早已用的是requestAnimationFrame, 可是因为光源的独特性(自带模糊不清实际效果),以便特性更为,尝试了2次requestAnimationFrame启用1次制图的方法,实际效果较前者没有显著差别
2.制图方位上: 从上图可发现,灯罩每次只圈发展方向径的1一部分,故制图中不必须每次都绘图所有相对路径,只必须找出灯罩前后左右的相对路径点,将这1段相对路径绘图出来就好

坑点

在进行这个动动漫实际效果以后遇到1个至今缘故不明的bug,伴随着显示屏置放時间的变长,动漫愈来愈慢,开启每日任务管理方法器,未见运行内存泄露或cpu应用率太高。开启performance,发现网页页面调帧比较严重,显示屏帧数愈来愈低,单独Frame CPU time愈来愈长,范畴看来,script和render和paint耗时未产生线形转变,仅有system時间愈来愈来长,愈来愈长,期待能被巨头告之缘故
1刚开始
 

到后来
 

处理的方法较为...,光源每循环系统1个周期,我消毁了以前的canvas并新建了canvas,顶层避开了system time不知道道为何愈来愈长的难题
chrome版本号:80.0.3987.163(宣布版本号) (64 位)

到此这篇有关html5 canvas 完成光源沿不规律相对路径健身运动的文章内容就详细介绍到这了,更多有关canvas 光源不规律健身运动內容请检索脚本制作之家之前的文章内容或再次访问下面的有关文章内容,期待大伙儿之后多多适用脚本制作之家!