用画布canvas画个爱心

首先我们找一个爱心的方程式

 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.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);

猜你喜欢

转载自www.cnblogs.com/sukeryy/p/12383383.html