canvas小练习之渐变粒子特效

<!DOCTYPE html>
<html lang="en">
<style>
    body {
        overflow: hidden;
        margin: 0px;
    }
    .container{
        position: relative;
        height: 900px;
        width: 900px;
        margin: auto;
        margin-top: 100px;
        background-color: aliceblue;
        z-index: 1000;
    }
    #canvas{
        z-index: 0;
        position: absolute;
        top: 0px;
        left: 0px;
    }
</style>

<body>
    <canvas id="canvas"></canvas>
    <!-- <div class="container"> -->

    </div>
    <script type="text/javascript">
        // 动画兼容函数
        window.requestAnimFrame = (function () {
            return (
                window.requestAnimationFrame ||
                window.webkitRequestAnimationFrame ||
                window.mozRequestAnimationFrame ||
                window.oRequestAnimationFrame ||
                window.msRequestAnimationFrame ||
                function (callback) {
                    window.setTimeout(callback, 1000 / 60)      //延迟一帧执行一次绘制,每秒60帧
                }
            )
        })()

        const canvas = document.getElementById('canvas')
        canvas.height = window.innerHeight      //根据屏幕显示canvas大小
        canvas.width = window.innerWidth
        const context = canvas.getContext('2d')

        var grd=context.createLinearGradient(0,0,window.innerHeight ,window.innerWidth);   
        //渐变效果函数,前两个参数是起点坐标,最后两个参数是终点坐标
        grd.addColorStop(0.2,"#FF0000");
        grd.addColorStop(0.5,"#00FF00");
        grd.addColorStop(0.8,"#0000FF");


        window.addEventListener('resize', resizeCanvas)

        function resizeCanvas() {       //实时调整canvas大小
            canvas.height = window.innerHeight
            canvas.width = window.innerWidth
        }

        // 创建粒子
        var dots = []
        for (var i = 0; i < 200; i++) {
            dots.push({
                x: Math.random() * canvas.width, // x  , y  为  粒子坐标
                y: Math.random() * canvas.height,
                xa: Math.random() * 3 - 1, // xa , ya 为  粒子 xy 轴加速度
                ya: Math.random() * 3 - 1,
                max: 100 // 连线的最大距离 px
            })
        }

        // 鼠标粒子
        let warea = {
            x: null,
            y: null,
            max: 200 // 鼠标位置 和点的连线
        }
        //获取鼠标活动时的鼠标坐标
        canvas.onmousemove = (e) => {
            warea.x = e.clientX
            warea.y = e.clientY
        }
        //鼠标移出界面时清空
        canvas.onmouseout = (e) => {
            warea.x = null
            warea.y = null
        }

        // 绘制粒子
        function drawDots() {
            // 先清空
            context.clearRect(0, 0, canvas.width, canvas.height)
            context.fillStyle = 'rgba(0,43,54,1)'
            context.fillRect(0, 0, canvas.width, canvas.height)

            // 循环加载粒子
            dots.forEach((dot) => {
                // 粒子位移
                dot.x += dot.xa     //与其说是加速度不如说是速度
                dot.y += dot.ya

                // 遇到边界将 加速度 反向
                dot.xa *= dot.x > canvas.width || dot.x < 0 ? -1 : 1
                dot.ya *= dot.y > canvas.height || dot.y < 0 ? -1 : 1

                // 绘制点
                context.fillRect(dot.x - 1, dot.y - 1, 2, 2)
                context.fillStyle = 'rgba(255,218,27,1)'

                drawLine(dot, dots)
            })
        }

        /**
         * 计算距离 并连线
         * @param dot 当前点
         * @param dots 所有点
         */
        function drawLine(dot, dots) {

            var ndots = [warea].concat(dots)    //粒子数组中加入鼠标,把鼠标也当成一种粒子

            for (var i = 0; i < ndots.length; i++) {
                var item = ndots[i]

                // 过滤错误信息
                if (dot === item || item.x === null || item.y === null) continue
                // 创建变量
                let xc = dot.x - item.x,
                    yc = dot.y - item.y,
                    dis = '',
                    ratio = ''

                // 两个粒子之间的距离
                dis = Math.sqrt(xc * xc + yc * yc)

                // 判断 粒子 之间的距离
                if (dis < item.max) {

                    // 如果是鼠标,则让其他粒子向鼠标的位置移动
                    if (item === warea && dis > item.max / 10) {
                        dot.x -= xc * 0.03
                        dot.y -= yc * 0.03
                    }


                    // 计算距离比 -- 用于线 厚度
                    ratio = (item.max - dis) / item.max
                    // 画线
                    context.beginPath()
                    context.lineWidth = ratio / 2
                    context.strokeStyle = grd
                    context.moveTo(dot.x, dot.y)
                    context.lineTo(item.x, item.y)
                    context.stroke()
                }
            }
        }




        //   drawDots()
        function animate() {        // 使用递归实现动画
            requestAnimFrame(animate)       //用递归实现定时器的功效
            drawDots()
        }
        console.log(canvas.getBoundingClientRect())
        animate()
      //
    </script>
</body>

</html>

这个和上一篇文章的区别就是这个渐变,这个渐变非常有意思,前两个参数是起点坐标,后两个参数是终点坐标,我是从左上角到右下角的渐变,虽然我本来是想试一下随机颜色的但是随机颜色的效果很差(我写的有问题。也许下一篇会讲),刚好搜渐变搜到了这个,还蛮好玩的,有点那种小时候玩的刮的那个东西。
上图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值