zoukankan      html  css  js  c++  java
  • 【被玩坏的博客园】之canvas装饰博客园侧边栏

    最近抽空学了学canvas,然后用canvas做了个小球运动的demo,大致的效果如下:

    虽然网上已经有很多这样的demo,但是还是想根据自己的思路来写一个,下面先跟大家讲解一下源代码,先看html代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      <style>
          html, body {
              padding: 0;
              margin: 0;
              width: 100%;
              height: 100%;
          }
          canvas {
            background-image: linear-gradient(-50deg,RGB(255, 106, 100),RGB(71, 0, 182));/*对canvas做背景颜色渐变处理,第一个参数是角度,后面2个是起始颜色,这个我就不细讲了,查查就知道*/
          }
      </style>
    </head>
    <body>
      <canvas id="canvas">
        
      </canvas>
      <script src="./index.js"></script>
    </body>
    
    </html>

    html很简单,没啥讲的,就是css那块兼容性你们注意下就好(我懒,没写兼容),再看看canvas的js处理代码,就是上面引入的index.js(讲解都写在注释里了,写的比较基础,方便没多少基础的人看):

    window.onload = function(){// 页面加载完了之后再处理
        var canvas = document.getElementById('canvas');
        var body = document.getElementsByTagName('body')[0];//getElementsByTagName是以标签名获取元素,返回是一个数组,所以用[0]
        canvas.width = body.clientWidth;// 获取body的【客户端宽度】,这个时候body已经加载完成了,页面大小已经形成。
        canvas.height = body.clientHeight;
        var bound = canvas.getBoundingClientRect();// 这个叫做获取边界客户端矩形,可以用来获取canvas的长宽
        var ctx = canvas.getContext('2d');// 获取canvas的上下文环境(可以理解为买下一个画笔)
        var width = bound.width, height = bound.height;
        var circleConfig = {// 配置信息
            ballNums: 300,// 球的数量
            fillColor: 'rgba(255, 255, 255, .5)',// 球的填充颜色
            radius: 1// 球的半径
        };
        var circle = new Circle(circleConfig);// 初始化球
        circle.init();// 初始化
        var zoom=function(e){ // 这个函数是用来缩放球的大小的,简单做了个缩放改变球的效果,目前可能就在chrome下有用
              var e = e || window.event; 
              if (!e.deltaX) {// 缩放的时候这个值是为0或-0的
                  if (e.deltaY < 0) {// 小于0好像是放大吧
                    if (circleConfig.radius) {
                        circleConfig.radius = null;
                        var circle = new Circle({
                            ballNums: 300,
                            fillColor: 'rgba(255, 255, 255, .5)',
                            // radius: 1
                        });
                        circle.init();
                    }
                    
                  }
                  else {
                    if (!circleConfig.radius) {
                        circleConfig.radius = 1;
                        var circle = new Circle({
                            ballNums: 300,
                            fillColor: 'rgba(255, 255, 255, .5)',
                            radius: 1
                        });
                        circle.init();
                    }
                  }
              }
              if(e.wheelDelta && event.ctrlKey){// 禁止网页缩放
                   event.returnValue = false
              }else if(e.detail){
                  
                   event.returnValue = false;
              } 
        }  
        if(document.addEventListener){ 
            document.addEventListener('DOMMouseScroll' , zoom , false); // 兼容火狐
        }
        window.onmousewheel = document.onmousewheel = zoom;// 除火狐之外的浏览器
        function Circle(o) {// 好了,这里才是故事真正开始的地方
            o = o || {};
            this.instance = [];// 可以理解为实例数组,用来存球的
            this.maxLineLength = o.maxLineLength || 100;// 最大线长度,就是2个球在这个距离内会在之间画根线
            function Ball() {
                this.radius = o.radius || (o.MaxRadius || 20) * Math.random();
                this.startDeg = 0;// 开始角度
                this.endDeg = Math.PI * 2;// 终结角度
                this.clockWay = false; // 顺时针还是逆时针
                this.fillColor = o.fillColor || randomColor();// 填充颜色
                this.borderColor = 'transparent';// 球的border设置为透明的不然难看
                this.dirX = 1;// 球的水平方向(控制正反)
                this.dirY = 1;// 如上
                this.speed = o.speed || 1 * Math.random() - 0.3;// 球的移动速度
                this.X = getRandom(width);// 这里是初始化球的起始位置,值是0-width
                this.Y = getRandom(height);
                this.resetDir = function() {// 控制方向
                    // X的位置如果小于半径或者大于canvas的宽度-半径就改变方向,Y同理
                    if (this.X < this.radius || this.X > width - this.radius) {
                        this.dirX = -this.dirX;
                    }
                    if (this.Y < this.radius || this.Y > height - this.radius) {
                        this.dirY = -this.dirY;
                    }  
                };
                this.init = function() {// 球的初始化
                    this.move();
                };
                this.move = function() {// 这个就是移动球,每执行一次就检查方向和改变XY的带系喔啊
                    this.resetDir();
                    this.X += this.dirX * this.speed;// 移动
                    this.Y += this.dirY * this.speed;
                };
                
            }
            this.ball = {
    
            };
            this.arc = function() {// 画圆函数
                // ctx.translate(this.X, this.Y);
                for (var i = 0; i < this.instance.length; i++) {
                    var ball = this.instance[i];// 从实例数组中取出来
                    // ctx.save();// 保存状态
                    ctx.fillStyle = ball.fillColor;// 球的填充颜色 (准备好填充颜料)
                    ctx.strokeStyle = ball.borderColor;// 球的线就是border(理解为准备好颜料)
                    ctx.beginPath();// 开始路径,可以理解为拿起画笔
                    ctx.arc(ball.X, ball.Y, ball.radius, ball.startDeg, ball.endDeg, this.clockWay);// 画圆
                    ctx.fill(); // 填充圆(就相当于给圆上色)
                    ctx.closePath();// 放下笔
                    // ctx.restore();
                    for(var j = i + 1; j < this.instance.length; j++) {
                        var s = Math.pow(ball.X - this.instance[j].X, 2) + Math.pow(ball.Y - this.instance[j].Y, 2);
                            s = Math.sqrt(s);// 获取圆与圆之间的距离,x的平方加y的平方然后开根号,初中数学知识
                        if (s < this.maxLineLength) {// 判断什么时候可以画线
                            ctx.beginPath();
                            ctx.moveTo(ball.X, ball.Y);// 把笔移动到
                            ctx.lineTo(this.instance[j].X, this.instance[j].Y);// 画线到这个位置
                            ctx.strokeStyle = 'rgba(255, 255, 255, ' + (this.maxLineLength - s) / (this.maxLineLength * 1.3)+')';
                            // 上面是调整线的颜色
                            ctx.strokeWidth = 1;// 线宽
                            ctx.stroke();//
                            ctx.closePath();
                        }
                    }
                }
            };
            this.draw = function() {
                ctx.clearRect(0,0,width,height);// 你要是把这个给注了你会发现不一样的世界
                this.arc();// 执行画圆函数
            };
            this.move = function() {
                for(var i = 0; i < this.instance.length; i++) {
                    var ball = this.instance[i];
                    ball.init();// 球的初始化函数,其实跟ball.move()是一样的,就是改变球的位置
                    
                }
                this.draw();
                requestAnimationFrame(this.move.bind(this));// 这里用bind是强行改变move函数的上下文环境,不然在requestAnimationFrame中的this会变得
                // requestAnimationFrame 请求动画帧,可以理解为控制函数执行的频率(本来这里可以用递归执行,但是递归控制不了频率,会卡死页面的,setTimeout也可以实现类似的效果)
            };
            this.init = function() {
                for(var i = 0; i < o.ballNums; i++) {
                    this.instance.push(new Ball()); // 初始化球               
                }
                this.move();
            };
            
        }
        function getRandom(s) {
            return Math.ceil(Math.random() * s);// 获取0 -(s-1)之间的值
        }
        function randomColor() {
            return 'rgba('+getRandom(255)+','+getRandom(255)+','+getRandom(255)+','+Math.random()+')';
        };
      };
      

    写完之后,还是想把他应用起来的,所以我就想用来他装饰博客园的侧边栏,所以进到:

    把上面的js改了改,插入到博客园页面:

    完整代码如下:

    <script>
    var sideBar = document.getElementById('home');
          var canvas = document.createElement('canvas');
          canvas.id = 'canvas';
          sideBar.appendChild(canvas);
    window.onload = function(){
        var canvas = document.getElementById('canvas');
        // var body = document.getElementById('home');
        var body = document.getElementsByTagName('html')[0];
        var header = document.getElementById('header');
        canvas.width = header.clientWidth;
        // canvas.height = body.clientHeight;
        canvas.height = window.screen.height;
        var bound = canvas.getBoundingClientRect();
        var ctx = canvas.getContext('2d');
        var width = bound.width, height = bound.height;
        var submit = document.getElementById('btn_comment_submit');
        submit && submit.addEventListener('click', function() {
    setTimeout(function() {
    body = document.getElementsByTagName('html')[0];
    canvas.height = window.screen.height;
    var circle = new Circle({
            ballNums: 100,
            fillColor: 'rgba(255, 255, 255, .5)',
    radius:1
        });
        circle.init();
    },1000);
    });
        var circle = new Circle({
            ballNums: 100,
            fillColor: 'rgba(255, 255, 255, .5)',
    radius: 1
        });
        circle.init();
        function Circle(o) {
            o = o || {};
            this.instance = [];
            this.maxLineLength = o.maxLineLength || 100;
            function Ball() {
                this.radius = o.radius || (o.MaxRadius || 20) * Math.random();
                this.startDeg = 0;
                this.endDeg = Math.PI * 2;
                this.clockWay = false;
                this.fillColor = o.fillColor || randomColor();
                this.borderColor = 'transparent';
                this.dirX = 1;
                this.dirY = 1;
                this.speed = o.speed || 1 * Math.random() - 0.3;
                this.X = getRandom(width);
                this.Y = getRandom(height);
                this.resetDir = function() {
                    if (this.X < this.radius || this.X > width - this.radius) {
                        this.dirX = -this.dirX;
                    }
                    if (this.Y < this.radius || this.Y > height - this.radius) {
                        this.dirY = -this.dirY;
                    }  
                };
                this.init = function() {
                    this.move();
                };
                this.move = function() {
                    this.resetDir();
                    this.X += this.dirX * this.speed;
                    this.Y += this.dirY * this.speed;
                };
                
            }
            this.ball = {
    
            };
            this.arc = function() {
                // ctx.translate(this.X, this.Y);
                for (var i = 0; i < this.instance.length; i++) {
                    var ball = this.instance[i];
                    ctx.save();
                    ctx.fillStyle = ball.fillColor;
                    ctx.strokeStyle = ball.borderColor;
                    ctx.beginPath();
                    ctx.arc(ball.X, ball.Y, ball.radius, ball.startDeg, ball.endDeg, this.clockWay);
                    ctx.fill(); 
                    ctx.closePath();
                    ctx.restore();
                    for(var j = i + 1; j < this.instance.length; j++) {
                        var s = Math.pow(ball.X - this.instance[j].X, 2) + Math.pow(ball.Y - this.instance[j].Y, 2);
                            s = Math.sqrt(s);
                        if (s < this.maxLineLength) {
                            ctx.beginPath();
                            ctx.moveTo(ball.X, ball.Y);// 把笔移动到
                            ctx.lineTo(this.instance[j].X, this.instance[j].Y);// 画线到这个位置
                            ctx.strokeStyle = 'rgba(255, 255, 255, ' + (this.maxLineLength - s) / (this.maxLineLength * 1.3)+')';
                            // 上面是调整线的颜色
                            ctx.strokeWidth = 1;// 线宽
                            ctx.stroke();//
                            ctx.closePath();
                        }
                    }
                }
            };
            this.draw = function() {
                ctx.clearRect(0,0,width,height);
                this.arc();
            };
            this.move = function() {
                for(var i = 0; i < this.instance.length; i++) {
                    var ball = this.instance[i];
                    ball.init();
                    
                }
                this.draw();
                requestAnimationFrame(this.move.bind(this));
            };
            this.init = function() {
                for(var i = 0; i < o.ballNums; i++) {
                    this.instance.push(new Ball());                
                }
                this.move();
            };
            
        }
        function getRandom(s) {
            return Math.ceil(Math.random() * s);
        }
        function randomColor() {
            return 'rgba('+getRandom(255)+','+getRandom(255)+','+getRandom(255)+','+Math.random()+')';
        };
      };
      
    </script>

    然后再调整下CSS代码,就可以达到我博客的左边侧边栏动画效果,如下:

    canvas的源代码:https://github.com/lhlybly/canvas-circle,欢迎star

    写在这里只是希望更多的人一起来学习,一起享受代码的作用,项目代码中还有很多优化的地方,欢迎大牛拍砖,也希望刚入门的人你呢个看懂,不懂可以留言问我。

    PS: 抽空我会优化刚进页面左边白屏的问题 

  • 相关阅读:
    modesim仿真
    EP3C系列FPGA的JTAG检测不了,JTAG下载失败,AS可以下载,下载完成后不执行程序
    本机修改虚拟机linux中的代码文件
    linux中的diff命令
    php中的elseif和else if
    php将数据写入另外一个文件
    IE6下的png不透明问题
    cookie的封装
    php从接口获取数据转成可以用的数组或其他(含转换编码)
    如何让后加载的元素被一开始就有的css样式渲染成功(强制提升css优先级)
  • 原文地址:https://www.cnblogs.com/hongrunhui/p/7856380.html
Copyright © 2011-2022 走看看