canvas旋转跟随鼠标线条 html+css+js

举报
北极光之夜。 发表于 2021/04/12 10:50:21 2021/04/12
【摘要】 先看效果(完整代码在底部):视频演示:https://www.bilibili.com/video/BV1iK4y1m7ur 实现过程(可一步一步实现):1.定义标签与基本css样式:<canvas id="canvas"></canvas>canvas{ display: block; }2. 开始正式js部分,先获取画布: var canvas = docu...

先看效果(完整代码在底部):



视频演示:https://www.bilibili.com/video/BV1iK4y1m7ur

实现过程(可一步一步实现):

1.定义标签与基本css样式:

<canvas id="canvas"></canvas>
canvas{
          display: block;
      }

2. 开始正式js部分,先获取画布:

 var canvas = document.querySelector("#canvas");
 var ctx = canvas.getContext("2d");

3.定义基本变量:

       // 画布宽与高
        var kuan=0,gao=0;
       // 线条数量    
        var num=25;
        //数组,存储每条线的基本信息
        var arr=[];
        // 存几个喜欢的颜色后面给线条
        var colors = ["#2196F3","#1976D2","#00BCD4","#4CAF50","#FF5252","#E040FB"];

4. 使得画布动态与窗口一样大小,直接copy该方法就行,顺便定义初始鼠标位置变量为画布的中间位置:

    window.onresize=resizeCanvas;
        function resizeCanvas(){
            kuan=canvas.width=window.innerWidth;
            gao=canvas.height=window.innerHeight;
        }
        resizeCanvas(); 

  var mouseX = kuan/2,mouseY = gao/2;

5. 初始化数组,初始化每条线条的基本信息:

注:Math.random()*(max-min) + min 为随机获取min到max间的一个数。

for(let i=0;i<num;i++){
            arr.push({
              // 线条的宽度
                r: Math.random()*(5-3) + 3,
              // 线条的颜色  
                color: colors[parseInt(Math.random()*6)],
                 /* 线条最初始小点所在旋转圆上的位置,就是在旋转开始的角度 */
                rot: Math.random()*2*Math.PI,
                /* 线条与旋转圆中心的距离 */
                distance: Math.random() * (75 - 40) + 40,
                /* 记录初始位置,后面鼠标拖拽时做缓动动画用 */
                lastMouse:{
                    x:kuan/2,
                    y:gao/2
                }
            })
        }

6.绑定鼠标移动事件:

 window.addEventListener('mousemove',function(event){
               mouseX = event.clientX;
               mouseY = event.clientY;               
         })   

7.执行更新操作,在更新里调用绘制:

注意:在一个圆上,坐标 x=cos(…)× r,y = sin(…)× r 。
cos(.)与sin(.)取值范围为【-1,1】。细品。

 function update (){
            for(let i=0;i<num;i++){
                //先保存上一帧的位置与i值
               let last ={x:arr[i].x,y:arr[i].y,i:i};             
            // 移动后位置 = 当前位置 + (移动后位置-当前位置)*0.05 缓动动画原理 
                arr[i].lastMouse.x+=(mouseX-arr[i].lastMouse.x)*0.05;
                arr[i].lastMouse.y+=(mouseY-arr[i].lastMouse.y)*0.05;
             // 角度改变,就是进行旋转
               arr[i].rot+=0.1;
               // 坐标X改变
                arr[i].x = arr[i].lastMouse.x + Math.cos(arr[i].rot)*arr[i].distance;
                // 坐标y改变
                arr[i].y = arr[i].lastMouse.y + Math.sin(arr[i].rot)*arr[i].distance;
                 /* 位置改变了,把last传给draw,得到不同两点后绘制画线 */
                draw(last);
            }
         }

8. 绘制:

 function draw(last) {
            var yuan = arr[last.i]; 
            // 开始绘制
            ctx.beginPath();
            //颜色
            ctx.strokeStyle = yuan.color;
            // 宽度
            ctx.lineWidth = yuan.r;
            ctx.moveTo(last.x,last.y);
            ctx.lineTo(yuan.x,yuan.y);
            ctx.stroke();
            ctx.closePath();
        }

9. 设置定时器,同时实现线条尾部慢慢消失效果:

setInterval(function(){
             /*  ctx.clearRect(0,0,kuan,gao); */
             /* 不直接用clearRect让上一帧内容全部变透明,而是逐渐给上一帧
             蒙上一层有点透明的当前背景色,这样一帧一帧的叠加,最开始的线段
             会逐渐与背景融合变得相当与消失 */
             ctx.fillStyle = "rgba(0,0,0,0.1)"; 
             ctx.fillRect(0,0,kuan,gao); 
             update(); 
          /*  draw(); */ 
        },20)

完整代码:

<!DOCTYPE html>
<html lang="zh-CN">
<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>
    <style>
        *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
      body{
          background-color: rgb(0, 0, 0);
        
      }
      canvas{
          display: block;
      }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script>
         var canvas = document.querySelector("#canvas");
         var ctx = canvas.getContext("2d");
       // 画布宽与高
        var kuan=0,gao=0;    
        var num=25;
        var arr=[];
        var colors = ["#2196F3","#1976D2","#00BCD4","#4CAF50","#FF5252","#E040FB"];
        window.onresize=resizeCanvas;
        function resizeCanvas(){
            kuan=canvas.width=window.innerWidth;
            gao=canvas.height=window.innerHeight;
        }
        resizeCanvas(); 
        var mouseX = kuan/2,mouseY = gao/2;
        for(let i=0;i<num;i++){
            arr.push({
               /*  x: kuan/2,
                y: gao/2, */
                r: Math.random()*(5-3) + 3,
                color: colors[parseInt(Math.random()*6)],
                 /* 旋转开始角度 */
                rot: Math.random()*2*Math.PI,
                /* 旋转小球距离中心距离 */
                distance: Math.random() * (75 - 40) + 40,
                /* 记录初始位置,鼠标拖拽时做缓动动画用 */
                lastMouse:{
                    x:kuan/2,
                    y:gao/2
                }
            })
        }
        function draw(last) {
           /*  for(let i=0;i<num;i++){ */ 
            var yuan = arr[last.i]; 
            ctx.beginPath();
            /* ctx.fillStyle = yuan.color; 
            ctx.arc(yuan.x,yuan.y,yuan.r, 0,Math.PI* 2, false);
            ctx.fill(); */
            ctx.strokeStyle = yuan.color;
            ctx.lineWidth = yuan.r;
            ctx.moveTo(last.x,last.y);
            ctx.lineTo(yuan.x,yuan.y);
            ctx.stroke();
            ctx.closePath();
           /*  } */ 
        }
          
         window.addEventListener('mousemove',function(event){
               mouseX = event.clientX;
               mouseY = event.clientY;               
         })       
        /*  var moveX=kuan/2,moveY=gao/2; */
         function update (){
            for(let i=0;i<num;i++){
                /* 传当前绘制的第i个的线的绘制前一帧的位置和当前i保存 */
               let last ={x:arr[i].x,y:arr[i].y,i:i};             
            /* 移动后位置 = 当前位置 + (移动后位置-当前位置)*0.05 缓动动画原理 */
                arr[i].lastMouse.x+=(mouseX-arr[i].lastMouse.x)*0.05;
                arr[i].lastMouse.y+=(mouseY-arr[i].lastMouse.y)*0.05;
               arr[i].rot+=0.1;
                arr[i].x = arr[i].lastMouse.x + Math.cos(arr[i].rot)*arr[i].distance;
                arr[i].y = arr[i].lastMouse.y + Math.sin(arr[i].rot)*arr[i].distance;
                 /* 位置改变,把last传给draw,画线 */
                draw(last);
            }
         }
        setInterval(function(){
             /*  ctx.clearRect(0,0,kuan,gao); */
             /* 不直接用clearRect让上一帧内容全部变透明,而是逐渐给上一帧
             蒙上一层有点透明的当前背景色,这样一帧一帧的叠加,最开始的小球
             会逐渐与背景融合变得相当与消失 */
             ctx.fillStyle = "rgba(0,0,0,0.1)"; 
             ctx.fillRect(0,0,kuan,gao); 
             update(); 
          /*  draw(); */ 
        },20)
    </script>
</body>
</html>

总结:

这是我的B站账号~https://space.bilibili.com/176586698
敲锣打鼓~
关注一波~
会有更多有意思的东西~
大概~
在这里插入图片描述

其它文章:
炫彩流光文字 html+css
气泡浮动背景特效 html+css
简约时钟特效 html+css+js
赛博朋克风格按钮 html+css
仿网易云官网轮播图 html+css+js
水波加载动画 html+css
导航栏滚动渐变效果 html+css+js
书本翻页 html+css
3D立体相册 html+css
霓虹灯绘画板效果 html+css+js
记一些css属性总结(一)
Sass总结笔记
…等

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。