女朋友都喜欢的Canvas:十二星座

1,688 阅读4分钟

在正文的第一句加入“我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

大家好,我是小杜杜,最近团了两张星空馆的门票,想和女神小姐姐一起去看看,说不定就能脱单了,于是我鼓足了勇气询问小姐姐:

6e6a2355cb444acc53ab4e93689d5314.jpg

看来女神小姐姐对星座比较迷恋,也不知道星空馆有没有,🤔,那我就自己写一个,顺便搞点土味情话,说不定能得到小姐姐的芳心(...花里胡哨)~

最终效果

满天繁星

背景

先来做一个背景,把背景设为黑色,然后考虑下怎么制作繁星,所以我们先简单的设置下

  * {
    margin: 0;
    padding: 0;
  }
  #canvas {
    background: #000;
    display: block;
  }

  <canvas id="canvas">您的浏览器版本过低,请更换浏览器!</canvas>

  let canvas = document.getElementById("canvas");
  let ctx = canvas.getContext("2d");
  let w = (canvas.width = window.innerWidth);
  let h = (canvas.height = window.innerHeight)

画星星

在这里有两种方式可以画星星,一种是利用圆,一种是利用图片,在这里我选择使用圆去画星星(因为比较方便~)

所以我们需要使用arc() 方法来画,先看看arc拥有那些参数:

image.png

通过x,y控制圆的位置,r控制圆的大小,就ok了,我们为了星星比较小,可以将r设置的小一点,然后蒋x,y设置成随机值,就ok了~

class Stars {
  constructor(ctx, width, height, r = 1) {
    this.ctx = ctx;
    this.width = width;
    this.height = height;
    this.stars = this.getStars(r);
  }
  getStars(r) {
    let stars = [];
    stars.push({
      x: this.width,
      y: this.height,
      r: Math.random() + r,
    });
    return stars;
  }
  draw() {
    let ctx = this.ctx;
    ctx.save();
    ctx.fillStyle = "white";

    this.stars.forEach((star) => {
      ctx.beginPath();
      ctx.arc(star.x, star.y, star.r, 0, 2 * Math.PI);
      ctx.fill();
    });
    ctx.restore();
  }

使用:

    let arr = []
    for(let i = 0; i < 200; i++){
            arr= [...arr, {
                    w: Math.random() * w, 
                    h: Math.random() * h, 
            }]
    }
    
    const constellation = (ctx, ary, w, h) => {
        arr.map(item => {
            new Stars(ctx, item.w, item.h, 1).draw()
        })
    })
     
   constellation(ctx, str, 600, 600)

这样就OK了~,来看看效果:

image.png

星星眨眼

我们发现现在有点美中不足的地方就是星星闪烁,我们可以利用定时器通过清空画布,在重新绘制,就能简单的实现闪动效果

如:

    setInterval(function () {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            constellation(ctx, str, 600, 600)
    }, 1000);

效果:

img1.gif

巨蟹座♋️

十二星座一共有:白羊座♈️、天秤座♎️、摩羯座♑️、水瓶座♒、双鱼座♓️、金牛座♉️、双子座♊️、巨蟹座♋️、狮子座♌️、处女座♍️、天蝎座♏️和射手座♐️

这里演示下巨蟹,原因是巨蟹相对于其他星座更加简单些~

画一条简单的线段

画一条简单的线段,我们需要一下方法:

  • ctx.beginPath():开始一条路径,或重置当前的路径
  • ctx.moveTo(x, y):将路径移入指定点的位置,此时并不会绘制线条,x:横坐标,y:纵坐标
  • ctx.lineTo(x, y):添加一个新点的坐标,此时也不会绘制线条
  • ctx.stroke():通过 moveTo() 和 lineTo() 方法定义的路径,就是绘制线条,默认颜色为黑色

先来一个简单的例子:

    ctx.beginPath();
    ctx.strokeStyle="#FFF"; //设置线段的颜色
    ctx.moveTo(50,20);
    ctx.lineTo(150,130); 
    ctx.lineTo(60,210); 
    ctx.stroke();  // 画

效果:

image.png

轮廓

所以我们只需要将对应的星座的点按照顺序绘制出来就可以了,像这样:

image.png

当然,我们可以将对应节点单独标记出来,方便星座看的更加清楚,同理我们直接使用上述的星星就可以了,同时我们可以将星星的半径r放大一点这样会更加清楚

img2.gif

文字

为了防止女神不认识这些星座,我们顺便加个文字,只需要通过font来设置下字体,再通过strokeText描绘下,就可以了,同时为了讨得欢心,我们加些土味情话,也是可以的~

    ctx.font = "30px Courier New";
    ctx.strokeText('巨蟹座:苦酒折柳今相离,无风无月也无你', 420, 100);

如:

image.png

十二星座

做好了巨蟹,我们再把其他的星座,按照同样的方法进行制作,在给个定时器,让3s一换,这样效果就好了

img5.gif

圆月

毕竟是中秋,怎么可能没有圆圆的月亮呢?为了效果更加真实,简单的使用下渐变,这样会更加的真实

//月亮
class Moon {
    constructor(ctx, width, height) {
        this.ctx = ctx
        this.width = width
        this.height = height
    }

    draw() {
        let ctx = this.ctx
        let gradient = ctx.createRadialGradient(200, 200, 80, 200, 200, 800)
        gradient.addColorStop(0, 'rgb(255,255,255)')
        gradient.addColorStop(0.01, 'rgb(70,70,80)')
        gradient.addColorStop(0.2, 'rgb(40,40,50)')
        gradient.addColorStop(0.4, 'rgb(20,20,30)')
        gradient.addColorStop(1, 'rgb(0,0,10)')
        ctx.save()
        ctx.fillStyle = gradient
        ctx.fillRect(0, 0, this.width, this.height)
        ctx.restore()
    }
}

//使用
new Moon(ctx, w, h).draw()

效果:

image.png

最终效果

img7.gif

在线地址:与女神一起去看星空吧~

最后

到时候我把这个发给女神小姐姐,不知道她喜不喜欢,🤔🤔

觉得有趣的小伙伴,或者有该如何追女神的兄弟,有什么好的建议可以在评论区讨论讨论,喜欢的点个赞支持一下吧~

祝有情人终成眷属,遇到其他情人各自飞!加油XDM!!!

另外,对React感兴趣的小伙伴,可以关注下作者的专栏:深入React,彻底搞懂React,相信一定能帮助到你~