canvas 航線、彗星掃尾軌跡效果


背景

知識點

  • canvas基本知識

實現思路

  • 思路其實不難,主要有如下步驟
    - 1 繪制貝塞爾曲線,起始點、控制點、終點自定;
    - 2 定義小球數組,該小球數組記錄貝塞爾曲線上每一份對應的x, y坐標以及小球坐標點的透明度、半徑(小球的透明度由0->1降低,半徑逐漸增大),當小球數組長度超過指定數組長度,清除最先進入的一個小球對應的坐標;
    - 根據貝塞爾曲線軌跡繪制當前的小球數組。

  • ok,看一下效果圖吧:

  • 順附demo源碼:
    <!DOCTYPE HTML>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			html,
			body {
				padding: 0;
				margin: 0;
				
			}
			canvas {
				border: 1px solid red;
			}
		</style>
	</head>

	<body>
		<canvas id="canvas" width="500" height="500"></canvas>

		<script type="text/javascript">
			var canvas = document.getElementById('canvas');
			var ctx= canvas.getContext('2d');
			var width = canvas.width;
			var height = canvas.height;
		
			//畫貝塞爾曲線參數 起始 兩個控制點,終點以及當前和總的比例數
			let sx = 10,
			sy = 10,
			cx1 = 50,
			cy1 = 10,
			cx2 = 150,
			cy2 = 500,
			ex = 500,
			ey = 500,
			t = 0,
			n = 200;
			//小球運動軌跡信息數組
			let bubbles = [{a:1, x:1, y: 1, r:4, s: 1}];

			let bubbleNum = 0;
			function test() {
				t++;
				bubbleNum++;
				ctx.clearRect(0, 0, 5000, 5000);
				ctx.lineWidth = 3;
				ctx.strokeStyle = 'green'
				ctx.beginPath();
				ctx.moveTo(sx, sy);
				ctx.bezierCurveTo(cx1, cy1, cx2, cy2, ex, ey);
				ctx.stroke();
				//計算當前的貝塞爾曲線坐標
				let x = sx * Math.pow((1 - t / n), 3) + 3 * cx1 * (t / n) * Math.pow((1 - t / n), 2) + 3 * cx2 * Math.pow((t / n), 2) * (1 - t / n) + ex * Math.pow((t / n), 3);
    			let y = sy * Math.pow((1 - t / n), 3) + 3 * cy1 * (t / n) * Math.pow((1 - t / n), 2) + 3 * cy2 * Math.pow((t / n), 2) * (1 - t / n) + ey * Math.pow((t / n), 3);

				//移動操作
				if (bubbleNum > 50) {
					bubbles.shift()
				}

				for(var i=0;i<bubbles.length;i++){
					bubbles[i].a = (i+1)*0.02;
					bubbles[i].s = (i+1)*0.02;					
				}
				let b = {a: 1, s: 1, x: x, y: y};
				bubbles.push(b);
				//渲染bubble數組
				for (let j = 0; j < bubbles.length; j++) {
					let b = bubbles[j];
					ctx.save();
					ctx.beginPath();
					ctx.globalAlpha = b.a; // 值是0-1,0代表完全透明,1代表完全不透明
	    			ctx.fillStyle = 'greenyellow';
	   				ctx.arc(b.x, b.y, b.s * 4, 0, 2 * Math.PI, false);
	    			ctx.fill();
	    			ctx.restore();
				}
				
    			if (x == 500) {
					t = 0;
				}
				console.log(t);
				requestAnimationFrame(test);
			}
			
			test();
		</script>
	</body>

</html>
  • 效果是實現了,但是每次需要清除整個canvas畫布,如果需要重繪的內容較多,性能上估計需要進一步優化了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM