canvas实现满屏星星

413 阅读1分钟

在很多的网页上,我们可以看到移动的小星星,但是它是怎么实现的呢,今天就来实现一下,效果如下:

04.gif

直接废话不多说,开始干:

首先设置下背景色:

<style>
        #canvas {
            background-color: black;
        }
 </style>

 <canvas id="canvas"></canvas>

获取canvas画布基本操作

let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');

// 设置线为白色
ctx.strokeStyle = 'white'
// 获取宽度
let aw = document.documentElement.clientWidth;
let ah = document.documentElement.clientHeight;


canvas.width = aw;
canvas.height = ah;

创建星星方法


function Star(x, y, r) {
    this.x = x;
    this.y = y;
    this.r = r;
    // 取-2~2的随机值   数越大移动越快
    this.speedX = (Math.random() * 2) * Math.pow(-1, Math.round(Math.random()))
    this.speedY = (Math.random() * 2) * Math.pow(-1, Math.round(Math.random()))
}

将一个星星用canvas画出来

// 画星星 这里是用的小圆圈  比较简单
Star.prototype.draw = function () {
    // 需要加上beginPath closePath  不然小球移动会连成线
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
    ctx.fillStyle = 'white'
    ctx.fill()
    ctx.closePath();
}

星星移动

Star.prototype.move = function () {
    this.x = this.x - this.speedX;
    this.y = this.y - this.speedY;
    // 当碰到了边界 要反弹
    if (this.x > aw || this.x < 0) {
        this.speedX = this.speedX * -1
    }
    if (this.y > ah || this.y < 0) {
        this.speedY = this.speedY * -1
    }
}

星星之间连线

function drawLine(startX, startY, endX, endY) {
    ctx.beginPath();
    ctx.strokeStyle = 'white';
    ctx.moveTo(startX, startY);
    ctx.lineTo(endX, endY);
    ctx.stroke()
}

随机画一百个星星

let stars = [];
for (let i = 0; i < 100; i++) {
    stars.push(new Star(Math.random() * aw, Math.random() * ah, 4))
}

鼠标点击 生成3个小星星

window.onclick = function(e){
    for(let i=0;i<3;i++){
        stars.push(new Star(e.clientX,e.clientY,4))
    }
}

生成鼠标小星星,跟着鼠标移动

let mounseStar = new Star(0,0,4)
window.onmousemove = function(e){
    mounseStar.x = e.clientX
    mounseStar.y = e.clientY
}

一帧帧渲染

requestAnimationFrame() 下一帧执行 功能类似setInterval

function animate() {
    // 每一帧都需要清空画布
    ctx.clearRect(0, 0, aw, ah);
    // 鼠标星星渲染
    mounseStar.draw()

    stars.forEach((star, index) => {
        star.draw();
        star.move();
        // 当两个点相距小于50时,连线
        for (let i = index + 1; i < stars.length; i++) {
            if (Math.abs(star.x - stars[i].x) < 50 && Math.abs(star.y - stars[i].y) < 50) {
                drawLine(star.x,star.y,stars[i].x,stars[i].y)
            }
        }

        // 鼠标星星连线
        if(Math.abs(star.x-mounseStar.x) <50 && Math.abs(star.y-mounseStar.y) < 50){
            drawLine(star.x,star.y,mounseStar.x,mounseStar.y)
        }
    })

    requestAnimationFrame(animate)
}

animate()

完整代码


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <style>
        #canvas {
            background-color: black;
        }
    </style>

    <canvas id="canvas"></canvas>

    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');

        // 设置线为白色
        ctx.strokeStyle = 'white'
        // 获取宽度
        let aw = document.documentElement.clientWidth;
        let ah = document.documentElement.clientHeight;


        canvas.width = aw;
        canvas.height = ah;


        function Star(x, y, r) {
            this.x = x;
            this.y = y;
            this.r = r;
            // 取-2~2的随机值   数越大移动越快
            this.speedX = (Math.random() * 2) * Math.pow(-1, Math.round(Math.random()))
            this.speedY = (Math.random() * 2) * Math.pow(-1, Math.round(Math.random()))
        }

        // 画星星
        Star.prototype.draw = function () {
            // 需要加上beginPath closePath  不然小球移动会连成线
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
            ctx.fillStyle = 'white'
            ctx.fill()
            ctx.closePath();
        }
        // 星星移动
        Star.prototype.move = function () {
            this.x = this.x - this.speedX;
            this.y = this.y - this.speedY;
            // 当碰到了边界 要反弹
            if (this.x > aw || this.x < 0) {
                this.speedX = this.speedX * -1
            }
            if (this.y > ah || this.y < 0) {
                this.speedY = this.speedY * -1
            }
        }

        // 星星之间连线
        function drawLine(startX, startY, endX, endY) {
            ctx.beginPath();
            ctx.strokeStyle = 'white';
            ctx.moveTo(startX, startY);
            ctx.lineTo(endX, endY);
            ctx.stroke()
        }


        // 画一百个星星
        // 存放在数组中  
        let stars = [];
        for (let i = 0; i < 100; i++) {
            stars.push(new Star(Math.random() * aw, Math.random() * ah, 4))
        }

        // 鼠标点击 生成3个小星星
        window.onclick = function(e){
            for(let i=0;i<3;i++){
                stars.push(new Star(e.clientX,e.clientY,4))
            }
        }

        // 生成鼠标小星星,跟着鼠标移动
        let mounseStar = new Star(0,0,4)
        window.onmousemove = function(e){
            mounseStar.x = e.clientX
            mounseStar.y = e.clientY
        }

        function animate() {
            // 每一帧都需要清空画布
            ctx.clearRect(0, 0, aw, ah);
            // 鼠标星星渲染
            mounseStar.draw()

            stars.forEach((star, index) => {
                star.draw();
                star.move();
                // 当两个点相距小于50时,连线
                for (let i = index + 1; i < stars.length; i++) {
                    if (Math.abs(star.x - stars[i].x) < 50 && Math.abs(star.y - stars[i].y) < 50) {
                        drawLine(star.x,star.y,stars[i].x,stars[i].y)
                    }
                }

                // 鼠标星星连线
                if(Math.abs(star.x-mounseStar.x) <50 && Math.abs(star.y-mounseStar.y) < 50){
                    drawLine(star.x,star.y,mounseStar.x,mounseStar.y)
                }
            })

            requestAnimationFrame(animate)
        }

        animate()

    </script>

</body>

</html>