首先我們找一個愛心的方程式
x=12*sin(t)-4*sin(3*t),y=13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t)
然后根據方程式繪制愛心,上代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style type="text/css"> body{ overflow: hidden; margin: 0; } </style> </head> <body> <canvas id="cv">您的瀏覽器不兼容canvas</canvas> <script> var cv = document.getElementById("cv"); var ctx = cv.getContext('2d'); var width = cv.width = window.innerWidth; var height = cv.height = window.innerHeight; var percision = 100; class Heart { constructor(x, y, size) { this.x = x || Math.random() * width; this.y = y || Math.random() * height; this.size = size || Math.random() * 2 + 1; //this.rotate = (this.speedx / this.speedy) * 100; //旋轉度數 this.vertices = new Array();//存放愛心坐標數組 for (var i = 0; i < percision; i++) { var t = Math.PI * 2 * (i / percision - 0.5); var tx = 12 * Math.sin(t) - 4 * Math.sin(3 * t); var ty = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t); this.vertices.push({ x: tx, y: -ty }); } } draw() {
ctx.save(); ctx.translate(this.x, this.y); //偏移繪制原點 ctx.beginPath(); //開始繪制 //ctx.rotate(this.rotate); //旋轉 ctx.scale(this.size, this.size); //縮放 this.vertices.forEach(element => { ctx.lineTo(element.x, element.y); //繪制輪廓 }); ctx.fillStyle = "red";//填充顏色 ctx.closePath(); //結束繪制 ctx.fill(); //填充輪廓 ctx.restore(); //返回之前保存過的路徑狀態和屬性 } }
new Heart(200,200,2).draw(); </script> </body> </html>
效果:
用愛心寫一個動畫:
var cv = document.getElementById("cv"); var ctx = cv.getContext('2d'); var width; var height; var percision = 100; var hearts = new Array(); ctx.strokeStyle = "red"; ctx.shadowBlur = 25; ctx.shadowColor = "hsla(0, 100%, 60%,0.5)"; //愛心方程式 x=12*sin(t)-4*sin(3*t),y=13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t) //屬性參考 https://www.w3school.com.cn/tags/html_ref_canvas.asp function onResize(){ width = cv.width = window.innerWidth; height = cv.height = window.innerHeight; } onResize(); class Heart { constructor(x, y, size) { this.x = x || Math.random() * width; this.y = y || Math.random() * height; this.size = size || Math.random() * 2 + 1; this.speedx = (Math.random() - 0.5) * 8 ; //x軸增量 this.speedy = (Math.random() - 0.5) * 8 ; //y軸增量 this.speedSize = Math.random() * 0.03 + 0.01; //size增量 //this.rotate = (this.speedx / this.speedy) * 100; //旋轉度數 this.vertices = new Array(); for (var i = 0; i < percision; i++) { var t = Math.PI * 2 * (i / percision - 0.5); var tx = 12 * Math.sin(t) - 4 * Math.sin(3 * t); var ty = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t); this.vertices.push({ x: tx, y: -ty }); } } draw() { this.x += this.speedx; this.y += this.speedy; this.size -= this.speedSize; ctx.save(); //保存狀態 ctx.translate(-1000, this.y); //偏移繪制原點 ctx.beginPath(); //開始繪制 //ctx.rotate(this.rotate); //旋轉 ctx.scale(this.size, this.size); //縮放 this.vertices.forEach(element => { ctx.lineTo(element.x, element.y); //繪制輪廓 }); ctx.globalAlpha = this.size; //設置透明度 ctx.shadowBlur = Math.round((3 - this.size) * 10); //陰影模糊 ctx.shadowColor = "hsla(0, 100%, 60%,0.5)"; //陰影顏色 ctx.shadowOffsetX = this.x + 1000; //設置或返回陰影距形狀的水平距離 用陰影繪制,本體藏在canvas之外 ctx.globalCompositeOperation = "screen"; //設置或返回新圖像如何繪制到已有的圖像上 ctx.closePath(); //結束繪制 ctx.fill(); //填充輪廓 ctx.restore(); //返回之前保存過的路徑狀態和屬性 } } function render(){ requestAnimationFrame(render); if(hearts.length < 99){ hearts.push(new Heart()); } ctx.clearRect(0,0,width,height); hearts.forEach((element,i) => { element.draw(); if(element.size < 0){ hearts.splice(i,1); } }) } window.requestAnimationFrame(render); window.addEventListener("resize", onResize); //告訴瀏覽器——你希望執行一個動畫,並且要求瀏覽器在下次重繪之前調用指定的回調函數更新動畫。 //該方法需要傳入一個回調函數作為參數,該回調函數會在瀏覽器下一次重繪之前執行 //若你想在瀏覽器下次重繪之前繼續更新下一幀動畫,那么回調函數自身必須再次調用window.requestAnimationFrame() var mouseMoved = false; function onMove(e){ mouseMoved = true; if(e.type === "touchmove"){ hearts.push(new Heart(e.touches[0].clientX, e.touches[0].clientY)); hearts.push(new Heart(e.touches[0].clientX, e.touches[0].clientY)); } else{ hearts.push(new Heart(e.clientX, e.clientY)); hearts.push(new Heart(e.clientX, e.clientY)); } } window.addEventListener("mousemove", onMove); window.addEventListener("touchmove", onMove);