【被玩坏的博客园】之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.getElementById(‘home‘);
    var header = document.getElementById(‘header‘);
    canvas.width = header.clientWidth;
    // canvas.height = body.clientHeight;
    canvas.height = body.clientHeight;
    var bound = canvas.getBoundingClientRect();
    var ctx = canvas.getContext(‘2d‘);
    var width = bound.width, height = bound.height;
    var submit = document.getElementById(‘btn_comment_submit‘);
    submit.addEventListener(‘click‘, function() {
setTimeout(function() {
body = document.getElementById(‘home‘);
canvas.height = body.clientHeight;
var circle = new Circle({
        ballNums: 200,
        fillColor: ‘rgba(255, 255, 255, .5)‘
    });
    circle.init();
},1000);
});
    var circle = new Circle({
        ballNums: 200,
        fillColor: ‘rgba(255, 255, 255, .5)‘
    });
    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: 抽空我会优化刚进页面左边白屏的问题

时间: 2024-10-01 07:31:45

【被玩坏的博客园】之canvas装饰博客园侧边栏的相关文章

玩坏的博客园】之canvas装饰博客园侧边栏

最近抽空学了学canvas,然后用canvas做了个小球运动的demo,大致的效果如下: 虽然网上已经有很多这样的demo,但是还是想根据自己的思路来写一个,下面先跟大家讲解一下源代码,先看html代码: html很简单,没啥讲的,就是css那块 http://p.baidu.com/itopic/main/qlog?qid=88496162633461303933633700&type=questionloghttp://p.baidu.com/itopic/main/qlog?qid=894

我的版权何在?博客园就不维护博友文章的版权?

说到版权心里就很不爽,大家很多时候自己的利益都有被侵犯的时候,很多人感觉不再乎,以前自己也是. 自己以前在51cto技术博客也写博客,不能说每天都写吧,但是每周都会出新笔记,当时自己也有很多粉丝,当时朋友就给我说,记得写笔记啊,我们都等着看呢,晚上10点前发出来,我必看.当时自己把自己知道的,结合所学到的一块做成world文档,加图片,标注,一心一意的写,偶尔也会录个小视频.想着自己会有越来越多的粉丝,后来博客就被封了,就中午下去吃顿饭的功夫,后来申诉去了,说我博客内容雷同,想想可能版权的问题,

【原】博客园第三方客户端-i博客园App开源

[原]博客园第三方客户端-i博客园App开源 本文转载请注明出处 —— polobymulberry-博客园 1.前言 目前i博客园App已经更新到2.0.0版本了,使用了最新的博客园Web API.相比于第一个版本,添加了很多新的功能,也修改了很多功能.整体来说改动比较大,代码也比较混乱.所以趁着清明假期,把代码好好整理了一番.目前基本的架构已成型(当然,后期还需要不断优化),但App基本功能方面还有很多需要添加的,后面会集中把App功能完善. 上面简单介绍了下目前App的情况,回到开源的话题

Windows Live Writer离线博客工具使用教程(适用于博客园、CSDN、51CTO等等博客)

文章背景 写博客不单是一种记录方式,更是一种工作习惯,与朋友一起分享是一件很快乐的事情,以前写博客,我们都会面临博客自带编辑器上各种头疼问题,比如排版.样式.功能局限性等等.但这些阻止不了我写下去的决心.一天突然奇想搜索下是否有那种离线博客发布的工具,没想到一谷歌,结果是,我竟然Out了好多年!泪奔啊- 文章主题 在网上查找离线博客之类的工具,发现各式各样都有!参差不齐!这里我就不一一举例了.最后决定使用微软一款开源日志发布工具Windows Live Writer.之所以用它,主要是原因有三:

博客园第三方客户端-i博客园正式发布App Store

博客园第三方客户端-i博客园正式发布App Store 1. 前言 算来从15年8月到现在自学iOS已经快7个月了,虽然中间也是断断续续的,不过竟然坚持下来了.年后要找实习啦,于是萌生了一个想法 —— 写一个app练练手.这次我没弄后台了,直接使用了博客园的open api(嘿嘿).之前也做过一个app,叫做魔界-魔术,前后端都是我弄的,不过后端使用的是Bmob后端云(一个Baas服务),但是作为第一个app,代码上感觉很混乱,而且基本上都是用的第三方控件.这次的i博客园是我完全独立开发的(包括

【转】Windows Live Writer离线博客工具使用教程(适用于博客园、CSDN、51CTO等等博客)

文章背景 写博客不单是一种记录方式,更是一种工作习惯,与朋友一起分享是一件很快乐的事情,以前写博客,我们都会面临博客自带编辑器上各种头疼问题,比如排版.样式.功能局限性等等.但这些阻止不了我写下去的决心.一天突然奇想搜索下是否有那种离线博客发布的工具,没想到一谷歌,结果是,我竟然Out了好多年!泪奔啊- 文章主题 在网上查找离线博客之类的工具,发现各式各样都有!参差不齐!这里我就不一一举例了.最后决定使用微软一款开源日志发布工具Windows Live Writer.之所以用它,主要是原因有三:

本人博客迁移说明 使用CSDN发布博客,不在更新博客园

很感谢博客园,我在博客园写的第一篇博客,由于很忙偶尔更新.后面开通了CSDN的账号,将博客园的博客文章转发到CSDN,CSDN平台大一些,用户也多,很方便,但是两个账号间文章转来转去很麻烦,我时间不多,所以最后决定放弃博客园,只是用CSDN更新.感谢博客园这一年多的陪伴,关注我的朋友可以点击下面的链接到我的CSDN博客下: https://blog.csdn.net/weixin_40377195 原文地址:https://www.cnblogs.com/hqz68/p/11805930.htm

那些年被我玩坏的点子和创意-下篇

时光如白驹过隙,继那些年被我玩坏的点子和创意-上篇已过一个月,平常忙活着和队友一起做产品了,挤得时间总结了下篇,分四个故事来说 自动发微博软件为啥做这个呢,淘宝客接口还没有限制以前好多玩淘宝客的.其中我发现有个淘宝客玩的挺特别的,他是在新浪微博和腾讯微博(当时还没有关闭),上通过时光机等一些定时发微博的平台给粉丝推送淘客商品信息,我还记得他的微博马甲叫"型男服装搭配",他推送的微博都是从淘宝男装男鞋等类目下的按销量等某些筛选条件后的top N条商品,我不知道这样效果怎么样,但我知道可以

为知笔记 | [插件]发布笔记到博客,更好的博客离线撰写工具

23 二 1 --> [插件]发布笔记到博客,更好的博客离线撰写工具 2011-02-23 功能特性 为知笔记支持绝大部分的博客离线撰写,可以方便地把笔记直接发布为博客. 使用 打开您已经在Wiz的撰写好的文章,然后点击“分享”按钮-发布到博客,如下图: 选择“发布到博客”,出现如下对话框: API地址:就是博客离线撰写发布的API地址,通常每一个博客的API地址都不相同,您可以从博客的帮助里面获得.下面是常用的一些博客API地址:  常用博客 API地址 新浪博客 http://upload.