canvas仿屏幕保护运动线条

canvas是H5中及其重要的一个新标签,它得出现不仅让前端做图形图表功能变得异常强大,还用极强的性能丰富前端渲染页面的能力。

Life is not a problem to be solved, but a reality to be experienced.
人生不是待解决的难题,而是等着我们去体验的现实。

首先canvas标签

<canvas id="c1" width="" height=""></canvas>

canvas标签的width,height如果写在style标签中会产生模糊。

canvas的基本js操作

定义一个画笔
var oC=document.getElementById('c1');
var gd=oC.getContext('2d');

移动到坐标点:gd.moveTo(100,100);
连接线: gd.lineTo(); 注意只是做了选区,并没有实际画出线条
封闭选区: gd.closePath();
选择颜色: gd.strokeStyle='red';
选择线条宽度:gd.lineWidth=20;
画出线条: gd.stroke();
选择填充的颜色:gd.fillStyle='green';
填充: gd.fill();
画一个矩形: gd.strokeRect(起始坐标x,起始坐标y,宽,高);
画完一个操作,开始另一个的时候需要添加:
gd.beginPath();
结束一个操作的时候如果需要连回到起点,需要添加:
gd.closePath();
清除画布: clearRect(x,y,宽度,高度);

下面分享一个用canvas做的windows线条运动屏幕保护效果,这个效果只利用以上canvas的基础知识,同时例子中用到一个算法的东西,获取一个数组中最大/最小值得方法,这个方法的思路是依次讲数组中的每一个数字和数组的第一个数字做比较,如果数字大于数字的第一个数,那么讲两个数字调换位置,利用这种方法循环数组,获取数组的第一个数字便是数组中最大的数(这个在前面一篇关于算法总结的文章中已经详细说明);

这个windows运动线条的效果的思路是,动态的再canvas画布上动态的创建了5个点,并赋予这5个点移动速度,并同时规定运动范围(当前屏幕可视窗),开启定时器使这些点不停的运动改变位置,再连接这5个点创建一个不停改变样式的不规则五边形,然后在数组中记录之前小点的位置和连接出来的图形,并赋予这些图形渐变的透明色并展示出来。

下面展示代码,js代码我在写的时候都做了明显的注释

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        body,html{
             100%;
            height: 100%;
            overflow:hidden;
        }
        body{
            background:#000;
        }
        #c1{

        }
    </style>
    <script>
        function rnd(m,n){
            return parseInt(Math.random()*(n-m)+m);
        }
        window.onload=function(){
            var oC=document.getElementById('c1');
            var gd=oC.getContext('2d');
            //设置canvas的宽度和高度
            var oW=document.documentElement.clientWidth;
            var oH=document.documentElement.clientHeight;
            oC.width=oW;
            oC.height=oH;
            //创建的白色点的个数
            var N=5;
            //设置每个点的坐标的信息和移动速度的信息,并存入一个数组之中
            var point=[];
            for(var i=0;i<N;i++){
                point[i]={
                    x:rnd(0,oC.width),
                    y:rnd(0,oC.height),
                    iSpeedX:rnd(-20,20),
                    iSpeedY:rnd(-20,20)
                }
            }
            console.log(point);
            //设置小点的宽和高
            var pw=1;
            var ph=1;
            //设置重影的个数,详见下面注释
            var LEN=100;
            //准备一个空数组存放需要留下的LEN个数据
            var oldArr=[];
            //在oC创建点并让小点运动起来,运动之前先要清除画布
            setInterval(function(){
                gd.clearRect(0,0,oW,oH);
                for(var i=0;i<point.length;i++){
                    point[i].x+=point[i].iSpeedX;
                    point[i].y+=point[i].iSpeedY;
                    //设置小点的运动范围
                    if(point[i].x<0){
                        point[i].iSpeedX*=-1;
                    }
                    if(point[i].x>oW){
                        point[i].iSpeedX*=-1;
                    }
                    if(point[i].y<0){
                        point[i].iSpeedY*=-1;
                    }
                    if(point[i].y>oH){
                        point[i].iSpeedY*=-1;
                    }
                    gd.fillStyle='#fff';
                    gd.fillRect(point[i].x,point[i].y,pw,ph);
                }
                //连线
                gd.beginPath();
                gd.moveTo(point[0].x,point[0].y);
                for(var i=1;i<point.length;i++){
                    gd.lineTo(point[i].x,point[i].y);
                }
                gd.closePath();
                gd.strokeStyle='#fff';
                gd.stroke();
                //开始设置重影,重影的思路是保存当前位置往前的若干次的位置的坐标,并用线连接起来,再设置一个透明度
                //首先要先设置一个重影的个数,这个需要写到全局变量中
                //创建一个空数组来装之前所有的坐标
                var arr=[];
                for(var i=0;i<point.length;i++){
                    arr[i]={
                        x:point[i].x,
                        y:point[i].y
                    };
                }
                console.log(arr);
                //创建一个oldArr来存放我们需要留下的坐标数据,这个数据需要在每次程序开始的时候都为空,然后依次往里添加,当数组中数据的数量大于LEN时候,剔除前面多余的数据
                oldArr.push(arr);
                if(oldArr.length>LEN){
                    oldArr.shift();
                }

                //现在得到的数据是两个相互包围的数组,划线的时候注意提取数据层次性
                gd.beginPath();
                for(var i=0;i<oldArr.length;i++){
                    var opacity=i/oldArr.length;
                    gd.strokeStyle='rgba(255,255,255,'+opacity+')';
                    gd.moveTo(oldArr[i][0].x,oldArr[i][0].y);
                    for(var j=1;j<oldArr[i].length;j++){
                        gd.lineTo(oldArr[i][j].x,oldArr[i][j].y);
                    }
                    gd.closePath();
                    gd.stroke();
                }
            },16);

        };
    </script>
</head>
<body>
    <canvas id="c1"></canvas>
</body>
</html>

  

原文地址:https://www.cnblogs.com/jasonwang2y60/p/6009807.html