javascript中canvas画爱心

1.效果如下


画单个爱心的效果如下:

2.HTML,CSS代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
    <script type="text/javascript" src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<style type="text/css" media="screen">
html,body,canvas{
    padding: 0;
    margin: 0;
    display: block;
}    
</style>
<body>
    <canvas id="heart">
    </canvas>
</body>
</html>

3.JS代码

首先单个爱心主要的思路是把爱心曲线分割成一个一个的点,然后利用直线把每一个点连接起来。这里我们需要知道的是爱心曲线的x,y方程 爱心方程 ,这个网站给出一些曲线的x,y表达式。
满屏幕的爱心就是把单个爱心重复画。

两个类

   function Point(x,y){
        this.x = x
        this.y = y
        this.scale = Math.random()*rand(1,3)
    }
    Point.prototype={
        mul:function(){
            this.x *= this.scale
            this.y *= this.scale
        }
    }
    function rand(min,max){
        return ~~(Math.random()*(max-min+1)+min)
    }
    function Position (cw,ch,x,y){
        this.cw=cw
        this.ch=ch
        this.offSetx = x||0
        this.offSety = y||0
        this.init()
    }
    Position.prototype={
        init:function(){
            if(this.offSetx ==0 && this.offSety== 0){
                this.offSetx = rand(20,this.cw-20)
                this.offSety = rand(20,this.ch-20)
            }
        }
    }
    function Heart (ctx,p) {
        this.points = []
        this.length = 0
        this.ctx = ctx
        this.position = p
        this.scale = (Math.random()+0.3)*rand(1,1.6)
        this.lightness = rand(30,80)
        this.init()
        // x = 16 sin^3 t
        // y = 13 cos t - 5 cos 2t - 2 cos 3t - cos 4t
        // http://www.wolframalpha.com/input/?i=x+%3D+16+sin%5E3+t%2C+y+%3D+(13+cos+t+-+5+cos+2t+-+2+cos+3t+-+cos+4t)
    }
    Heart.prototype = {
        init:function(){
            for (let i = 0; i < 2*Math.PI; i += 2*Math.PI/30) {
                let x = 16 * Math.pow(Math.sin(i), 3);
                let y = 13 * Math.cos(i) - 5 * Math.cos(2 * i) - 2 * Math.cos(3 * i) - Math.cos(4 * i);
                this.points.push(new Point(x, y));
            }
            this.length = this.points.length;
        },
        get: function(i) {
            return this.points[i];
        },
        draw:function(){
            this.ctx.save()
            this.ctx.beginPath()
            this.ctx.translate(this.position.offSetx,this.position.offSety)
            this.ctx.fillStyle = 'hsla(0 ,100%,'+this.lightness+'%,0.6)'
            this.ctx.lineWidtn = 2
            this.ctx.lineCap = 'round'
            this.ctx.scale(this.scale,this.scale)
            this.ctx.moveTo(this.get(0).x,-this.get(0).y)
            for(let i = 1 ;i < this.length ; i++){
                this.ctx.lineTo(this.get(i).x,-this.get(i).y)
            }
            this.ctx.closePath()
            this.ctx.fill()
            this.ctx.restore()
        }
    }
    function Canvas(ctx,cw,ch){
        this.heartNum = 66
        this.hearts=[]
        this.length = 0
        this.cw = cw
        this.ch = ch
        this.ctx = ctx
        this.init()
    }
    Canvas.prototype={
        init:function(){
            while(this.heartNum--){
                let p = new Position(this.cw,this.ch)
                this.hearts.push(new Heart(this.ctx,p))
            }
            this.length = this.hearts.length
        },
        drawHearts:function(){
            let i = this.length
            while(i--){
                this.hearts[i].draw()
            }
        }
    }

定义了四个类:
Point
用来保存点的坐标
Position
用来保存每一个爱心的偏移量,这些偏移量在后来做随机分布爱心的时候会用到
Heart
传入两个参数分别是,ctx:canvas的2d画布对象,Position对象p,里面包含有offSetx:x偏移量,offSety:y偏移量。
this.ctx.translate(this.position.offSetx,this.position.offSety)
意思是重新定义画布的基准点,定位到 (offSetx,offSety),这个点的在后面的设置中就是(0,0),在设置基准点的时候注意要用到this.ctx.save() this.ctx.restore(),因为基准点改变了,save是保存原来画布的设置,restore是还原原来画布的设置。
Canvas
整个画布对象,用来规定有多少爱心。

初始化以及执行

  $(function(){
       let c = document.getElementById('heart')
       let cw = c.width = $(window).width()
       let ch = c.height = $(window).height()
       let ctx = c.getContext('2d')
       let canvas = new Canvas(ctx,cw,ch)
       canvas.drawHearts() 
   })

4.说明

我想把每个爱心的大小也随机一下,this.ctx.scale这个方法一定要放在绘制的前面

this.ctx.scale(this.scale,this.scale)
this.ctx.moveTo(this.get(0).x,-this.get(0).y)
for(let i = 1 ;i < this.length ; i++){
	this.ctx.lineTo(this.get(i).x,-this.get(i).y)
}
this.ctx.closePath()
}   
发布了25 篇原创文章 · 获赞 1 · 访问量 1638

猜你喜欢

转载自blog.csdn.net/weixin_43977647/article/details/104408250
今日推荐