前端canvas实现粒子效果(一): 初始化粒子并移动起来

先看实现的效果吧:
在这里插入图片描述

<!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>粒子效果</title>
    <link rel="stylesheet" href="./index.css">
	<style>
		body{
		    padding: 0;
		    margin: 0;
		    height: 100vh;
		    box-sizing: border-box;
		}
		#bg{
		    height: 100%;
		    background-color: rgb(50,64,87);
		    background-size: cover;
		    position: fixed;
		    top: 0;
		    left: 0;
		    bottom: 0;
		    right: 0;
		    z-index: 0;
		}
	</style>
</head>

<body>
    <div id="bg">
        <canvas id="canvas"></canvas>
    </div>
    <script type="text/javascript">
        let canvas = document.getElementById('canvas')
        let width = window.innerWidth    //画布宽度初始值
        let height = window.innerHeight   // 画布高度初始值
        let animationFrame = null
        const PIX_NUM = 140    // 粒子个数
        const LINE_WIDTH = 1   // 粒子连线线宽
        const RADIUS = 1  // 定义粒子圆的半径 
        let ctx = canvas.getContext('2d')   //获取canvas画布上下文
        let fillStyle = `rgba(255,255,255,.7)`  // 像素点填充色
        const CONNECTION = 80 //连线的最大距离
        const FOLLOW_LENGTH = 80 // 鼠标跟随距离
        let dots = []   //所有粒子集合
        let mouseX = null // 鼠标x坐标
        let mouseY = null   // 鼠标y坐标

        // 初始化画布的尺寸,并且当窗口大小变化时,也需要重新定义画布尺寸
        function initCanvasSize(){
            width = window.innerWidth
            height = window.innerHeight
            canvas.width = window.innerWidth
            canvas.height = window.innerHeight
            ctx.clearRect(0,0,width,height)
            console.log('initCancasSize.......')
            dots = []
            // 每次初始化画布大小时,都需要清除上一次的动画,否则多个动画并存,会导致动画越来越快,这点和多个定时器道理一样
            if(animationFrame)window.cancelAnimationFrame(animationFrame) 
            // // 测试10秒钟后终止动画
            // setTimeout(()=>{
            //     window.cancelAnimationFrame(animationFrame)
            // },10000)
            // 调用初始化粒子的方法
            initDots()
            // 移动粒子
            moveDots()
        }
        
        function mouseMove(e){
            mouseX = e.clientX // 根据鼠标移动实时记录x坐标
            mouseY = e.clientY // 根据鼠标移动实时记录y坐标
        }
        // 定义dot粒子类,用于生成80个像素点
        class Dot{
            // 构造函数,通过传入x和y的坐标来确定每一个粒子点的位置
            constructor(x,y){
                this.x = x
                this.y = y
                //随机生成 -1~1之间的数,意思就是每次重绘像素点时所移动的距离
                // requestAnimationFrame()会根据每次移动的距离自动判定动画的速度
                this.speedX = Math.random()*2-1 
                this.speedY = Math.random()*2-1 
            }
            // 绘制每一个粒子的方法
            draw(){
                // console.log('开始绘制......')
                ctx.beginPath() //开始绘制
                ctx.arc(this.x,this.y,RADIUS,0,2*Math.PI) //根据x,y坐标绘制圆
                ctx.fillStyle = 'rgba(255,255,255,1)'   //设置圆填充色,即每一个粒子
                ctx.fill()  //填充圆
                ctx.closePath() //结束绘制
            }
            move(){
                // 判断边界,防止粒子点超出屏幕外
                if(this.x >= width || this.x <= 0)this.speedX = -this.speedX
                if(this.y >= height || this.y <= 0)this.speedY = -this.speedY
                // 每次实例调用此方法都会使x坐标移动 speedX的距离
                this.x += this.speedX
                this.y += this.speedY
                // 触发重绘元素点
                this.draw()
            }
        }
        // 根据上面定义的粒子数,即 PIX_NUM 常量
        function initDots(){
            for(let i = 0;i < PIX_NUM;i++){
                // 为每个粒子点初始化x坐标,坐标范围在  0~画布宽度之间
                let x = Math.floor(Math.random() * (width-0)+1)
                // 同上,  0~画布高度之间
                let y = Math.floor(Math.random()*(height-0)+1)
                let dot = new Dot(x,y)
                dot.draw()
                dots.push(dot)//将每一个dot粒子实例存储到dots数组中
            }
        }
        // 让粒子移动起来
        function moveDots(){   
        	// 清空画布:
        	// 即每次移动粒子时,都需要将上一次绘制的粒子从画布上清空掉之后在绘制粒子,
        	// 从而达到移动的视觉效果
            ctx.clearRect(0,0,width,height)
            for(const dot of dots){
                dot.move()
            }
            // 启用帧动画,也是最重要的一步,否则每次重置并重绘粒子都是瞬间完成的
            animationFrame =  window.requestAnimationFrame(moveDots)   
        }
        initCanvasSize()
        // 监听窗口尺寸变化事件,一旦窗口大小变化,触发initCanvasSize事件
        window.onresize = initCanvasSize
    </script>
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值