【JavaScript】particle

这是js实现的粒子动画,有两种模式,分别是zoom和line,它们对应的效果不同,但是原理都相同,具体分析如下:

部分程序如下:

        var p = this;
        p.originParams = originParams;
        p.params = params;
        p.innerWidth = window.innerWidth;//页面视图区大小
        p.innerHeight = window.innerHeight;
        p.points = [];
        p.pageXY = {pageX:p.innerWidth/2,pageY:p.innerHeight/2};
        if(container[0] === ‘#‘) {
            p.container = container.split(‘#‘)[1];
        };
        //获取canvas元素
        p.canvas = document.getElementById(p.container);
        //创建context对象
        p.ctx = p.canvas.getContext(‘2d‘);
        //初始化
        p.init = function() {
            p.canvas.width = p.innerWidth;
            p.canvas.height = p.innerHeight;
            p.drawBackground();
            p.addOverlap();
            p.initDrawPoint();
            p.animation();
            p.mouseEvent();
            p.windowResize();
        };
        p.addOverlap=function(){
            p.overlap=document.createElement(‘div‘);
            p.overlap.style.width=p.innerWidth+‘px‘;
            p.overlap.style.height=p.innerHeight+‘px‘;
            p.overlap.style.position=‘absolute‘;
            p.overlap.style.top=‘0px‘;
            p.overlap.style.left=‘0px‘;
            p.overlap.style.zIndex=‘100‘;
            if(p.canvas.nextElementSibling){//??
                p.canvas.parentNode.insertBefore(p.overlap,p.canvas.nextElementSibling);//insertBefore接收要插入的节点和作为参考的节点
            }else{
                p.canvas.parentNode.appendChild(p.overlap);
            };
        };
        //粒子颜色
        p.color = function() {
            function random() {
                return Math.round(Math.random() * 255);
            };
            this.r = random();
            this.g = random();
            this.b = random();//分别调用三次取随机值
            this.a = random(1, 0.8);
            this.rgba = ‘rgba(‘ + this.r + ‘,‘ + this.g + ‘,‘ + this.b + ‘,‘ + this.a + ‘)‘;
            return this;
        };
        //获取随机数
        p.random = function(max, min) {
            var min = arguments[1] || 0;
            return Math.floor(Math.random() * (max - min + 1) + min);
        };
        //绘制背景图
        p.drawBackground = function() {
            if(!p.canvas) return;
            p.ctx.fillStyle = ‘#000‘;
            p.ctx.fillRect(0, 0, p.innerWidth, p.innerHeight);
        };
        //粒子
        p.point = function() {//每个粒子包括颜色,坐标、半径
            this.color = new p.color();
            this.x = Math.random() * p.innerWidth;//随机坐标
            this.y = Math.random() * p.innerHeight;
            this.vx = p.random(10, -10) / 40;//步进,调用p.random
            this.vy = p.random(10, -10) / 40;
            this.r = p.random(3, 1);//半径,调用p.random,半径最大为3,最小为1,在这个范围内波动
            this.scale = 1;//放大倍数
        };
        //初始化点
        p.initDrawPoint = function() {
            for(var i = 0; i < p.params.point; i++) {//所有点
                var point = new p.point();
                p.points.push(point);
                p.ctx.beginPath();
                p.ctx.fillStyle = point.color.rgba;
                p.ctx.arc(point.x, point.y, point.r * point.scale, 0, Math.PI * 2, true);
                p.ctx.fill();
            };
            p.ctx.closePath();
        };
        //点点连线
        p.connect = function() {
            function lineColor(p1, p2) {
                var linear = p.ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);//起点终点坐标
                linear.addColorStop(0, p1.color.rgba);//开始的颜色
                linear.addColorStop(1, p2.color.rgba);//结束的颜色
                return linear;
            };
            for(var i = 0; i < p.params.point; i++) {
                for(var j = 0; j < p.params.point; j++) {
                    var p1 = p.points[i];
                    var p2 = p.points[j];
                    if(Math.abs(p2.x - p1.x) < p.params.minDis && Math.abs(p2.y - p1.y) < p.params.minDis) {//两点之间距离小于一定程度才连线

                        p.ctx.beginPath();
                        p.ctx.lineWidth = 0.2;
                        p.ctx.strokeStyle = lineColor(p1, p2);//采用渐变,描边样式
                        p.ctx.moveTo(p1.x, p1.y);
                        p.ctx.lineTo(p2.x, p2.y);
                        p.ctx.stroke();//描边,使用的是strokeStyle
                        p.ctx.closePath();
                    };
                };
            };
        };
        p.lineto = function() {//和鼠标位置有关
            function isInView(point) {
                return Math.abs(point.x - p.pageXY.pageX) < p.params.mouseDis && Math.abs(point.y - p.pageXY.pageY) < p.params.mouseDis;
            };
            (function line() {
                function lineColor(p1, p2) {
                    var linear = p.ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
                    linear.addColorStop(0, p1.color.rgba);
                    linear.addColorStop(1, p2.color.rgba);
                    return linear;
                };
                for(var i = 0; i < p.params.point; i++) {
                    for(var j = 0; j < p.params.point; j++) {
                        if(i != j) {
                            var p1 = p.points[i];
                            var p2 = p.points[j];
                            if(isInView(p1) && isInView(p2)) {
                                if(Math.abs(p2.x - p1.x) < p.params.minDis && Math.abs(p2.y - p1.y) < p.params.minDis) {
                                    p.ctx.beginPath();
                                    p.ctx.lineWidth = 0.2;
                                    p.ctx.strokeStyle = lineColor(p1, p2);
                                    p.ctx.moveTo(p1.x, p1.y);
                                    p.ctx.lineTo(p2.x, p2.y);
                                    p.ctx.stroke();
                                    p.ctx.closePath();
                                };
                            };
                        };
                    };
                };
            })();
        };
        //无限循环动画
        p.animation = function() {
            p.ctx.clearRect(0, 0, p.innerWidth, p.innerHeight);
            p.drawBackground();
            for(var i = 0; i < p.params.point; i++) {
                var point = p.points[i];
                if(point.x < 0 || point.x > p.innerWidth) {//当小圆球碰到矩形壁以后反弹
                    point.vx = -point.vx;
                };
                if(point.y < 0 || point.y > p.innerHeight) {
                    point.vy = -point.vy;
                };
                p.ctx.beginPath();
                p.ctx.fillStyle = point.color.rgba;
                point.x += point.vx;  //小圆球不断移动
                point.y += point.vy;
                p.ctx.arc(point.x, point.y, point.r * point.scale, 0, Math.PI * 2, true);
                p.ctx.fill();
            };
            if(p.params.effect == ‘zoom‘) {
                p.connect();//将小球与小球用线连接,鼠标移动事件定义在mouseEvent中
            } else if(p.params.effect == ‘line‘) {
                p.lineto();//该函数与鼠标位置有关,通过鼠标事件传入鼠标位置,在该位置附近连线
            };
            requestAnimationFrame(p.animation);
        };
        //鼠标事件
        p.mouseEvent = function() {
            p.overlap.addEventListener(‘mousemove‘, function(e) {//鼠标指针移动时触发div中的事件
                var e = e || window.event;
                var pageX = (e.clientX + document.body.scrollLeft || e.pageX) - this.offsetLeft;//offsetLeft指div到边框??
                var pageY = (e.clientY + document.body.scrollTop || e.pageY) - this.offsetTop;
                if(p.params.effect == ‘zoom‘){
                    for(var t = 0; t < p.params.point; t++) {
                        var point = p.points[t];
                        if(Math.abs(point.x - p.pageXY.pageX) < p.params.minDis && Math.abs(point.y - p.pageXY.pageY) < p.params.minDis) {//鼠标附近的点
                            point.scale = 5;
                        } else {
                            point.scale = 1;
                        };
                    };
                };
                p.pageXY.pageX = pageX;
                p.pageXY.pageY = pageY;
            });
            p.overlap.addEventListener(‘mouseout‘, function(e) {//鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发
                if(p.params.effect == ‘zoom‘){//zoom鼠标移出div都变为原来的比例
                    for(var i = 0; i < p.params.point; i++) {
                        var point = p.points[i];
                        if(point.scale != 1) {
                            point.scale = 1;
                        };
                    };
                }else{
                    p.pageXY.pageX=p.innerWidth/2;//line方式鼠标移出div自动定位到中心
                    p.pageXY.pageY=p.innerHeight/2;
                };
            });
        };
        p.windowResize = function() {
            window.addEventListener(‘resize‘, p.init);
        };
        p.init();
        return p;
    };
    //兼容requestAnimFrame
    window.requestAnimationFrame = (function() {//requestAnimationFrame??
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            function(callback) {//前面三个都不支持则采用该函数
                window.setTimeout(callback, 1000 / 60);
            };
    })();
时间: 2024-10-11 01:09:40

【JavaScript】particle的相关文章

【javascript】ajax 基础 --本文转载

[javascript]ajax 基础 什么是 ajax ajax 即"Asynchronous JavaScript and XML"(异步 JavaScript 和 XML),也就是无刷新数据读取. http 请求 首先需要了解 http 请求的方法(GET 和 POST). GET 用于获取数据.GET 是在 URL 中传递数据,它的安全性低,容量低. POST 用于上传数据.POST 安全性一般,容量几乎无限. ajax 请求 ajax 请求一般分成 4 个步骤. 1.创建 a

【JavaScript】兼容IE6可调可控的图片滑块

图片滑块其实也与图片轮播一样,无需这么多奇奇怪怪的代码就能够实现,只是布局有点复杂,而且这东西在Bootstrap里面也没有,在网页中,这个组件也越来越少见的,毕竟这个小小的组件太浪费网络资源了,实现的逻辑还比较复杂,如果不要被特别要求,能不做最好不好. 有时候,如果一个如同<[CSS]黑色幽默,兼容IE6的纯原生态的门户网站>(点击打开链接)的简单网页就能够交货,就不要卖弄你的前端技巧了. 虽然这个组件的效率很低,但是还是讲解一下实现的原理,也是完美兼容IE6,同时包你能够随心所欲地放置这个

【JavaScript】使用Bootstrap来编写 选择折叠项collapse

选择折叠项collapse在网页中并不常用,不过也并不少见. 这也算是一个比较实用的组件. 折叠项collapse在默认情况下仅能有一项是处于打开状态的. 一.基本目标 使用Bootstrap来编写如下图的选择折叠项: 其中服务条款2在打开网页的时候就是打开状态. 点击不同的折叠项,其余的项就会收起,这项就会打开. 二.制作过程 1.同之前<[JavaScript]使用Bootstrap来编写一个在当前网页弹出的对话框,可以关闭,不用跳转,非弹窗>的第一步(点击打开链接) 因为需要使用Boot

【JavaScript】你知道吗?Web的26项基本概念和技术

Web开发是比较费神的,需要掌握很多很多的东西,特别是从事前端开发的朋友,需要通十行才行.今天,本文向初学者介绍一些Web开发中的基本概念和用到的技术,从A到Z总共26项,每项对应一个概念或者技术. A — AJAX AJAX 全称为“Asynchronous JavaScript and XML”(异步JavaScript和XML),是一种创建交互式网页应用的网页开发技术.根据Ajax提出者Jesse James Garrett建议,AJAX: 使用XHTML+CSS来表示信息: 使用Java

【JavaScript】jQuery Ajax 实例 全解析

jQuery确实是一个挺好的轻量级的JS框架,能帮助我们快速的开发JS应用,并在一定程度上改变了我们写JavaScript代码的习惯. 废话少说,直接进入正题,我们先来看一些简单的方法,这些方法都是对jQuery.ajax()进行封装以方便我们使用的方法,当然,如果要处理复杂的逻辑,还是需要用到jQuery.ajax()的(这个后面会说到). 1. load( url, [data], [callback] ) :载入远程 HTML 文件代码并插入至 DOM 中. url (String) :

【JavaScript】【译】编写高性能JavaScript

英文链接:Writing Fast, Memory-Efficient JavaScript 很多JavaScript引擎,如Google的V8引擎(被Chrome和Node所用),是专门为需要快速执行的大型JavaScript应用所设计的.如果你是一个开发者,并且关心内存使用情况与页面性能,你应该了解用户浏览器中的JavaScript引擎是如何运作的.无论是V8,SpiderMonkey的(Firefox)的Carakan(Opera),Chakra(IE)或其他引擎,这样做可以帮助你更好地优

【JavaScript】计算字符串的长度

定义: functionGetChineseCount(str) { varchinieseCount=0; varbadChar="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; badChar+="abcdefghijklmnopqrstuvwxyz"; badChar+="0123456789"; badChar+=""+" ";//半角与全角空格 badChar+="`[emai

【JavaScript】父子页面之间跨域通信的方法

由于同源策略的限制,JavaScript跨域的问题,一直是一个比较棘手的问题,为了解决页面之间的跨域通信,大家煞费苦心,研究了各种跨域方案.之前也有小网同学分享过一篇“跨域,不再纠结” 开始照着尝试时还是有些不够明白的地方,深入了解之后,这里给大家补充一点更具体的做法. 先来看看哪些情况下才存在跨域的问题: 其中编号6.7两种情况同属于主域名相同的情况,可以设置domain来解决问题,今天就不讨论这种情况了. 对于其他跨域通信的问题,我想又可以分成两类: 其一(第一种情况)是a.com下面的a.

【JavaScript】HTML5/CSS3实现五彩进度条应用

今天要介绍的是一款基于HTML5和CSS3的进度条应用,这款进度条是静态的,仅提供进度条的五彩外观.当然你可以在CSS中动态设置进度值来让其变得动态,一个很好的实现方式是利用jQuery动态改变CSS中的进度值,让进度条实时动起来.具体效果大家可以看演示. 你也可以在这里查看在线演示 接下来我们来分析一下这款进度条的源代码以及实现思路,代码主要由HTML和CSS组成,如果你需要动态改变进度值,也可以自己添加Javascript代码,也是比较简单的. HTML代码: <section class=