js 模拟气泡屏保效果代码


Posted in Javascript onJuly 10, 2010

核心代码:

var T$ = function(id) { return document.getElementById(id); }
var $extend = function(des, src) { for (var p in src) { des[p] = src[p]} return des; }
var Bubble = function() {
    // 小球随机样式
    var clss = ['ball_one', 'ball_two',  'ball_three', 'ball_four', 'ball_five', 'ball_six'];
    var Ball = function(radius, clsname) {
        var ball = document.createElement('div');
        ball.className = clsname;
        with(ball.style) {
            width = height = (radius || 10) + 'px';  position = 'absolute'; 
        }
        return ball;
    };
    // 屏保主类
    var Screen = function(cid, config) {
        var self = this;
        if (!(self instanceof Screen)) {
            return new Screen(cid, config);
        } 
        self.container = T$(cid);
        if (!self.container) return; 
        config = $extend(Screen.Config, config || {});
        // 配置属性
        self.ballsnum = config.ballsnum;
        self.diameter = 55;
        self.radius = self.diameter / 2;
        self.bounce = config.bounce;
        self.spring = config.spring;
        self.gravity = config.gravity;
        self.balls = [];
        self.timer = null;
        // 上下左右边界
        self.T_bound = 0;
        self.B_bound = self.container.clientHeight;
        self.L_bound = 0;
        self.R_bound = self.container.clientWidth;
    };
    // 静态属性
    Screen.Config = {
        ballsnum: 5,   // 小球数目
        spring: 0.8,   // 弹力加速度
        bounce: -0.95, // 反弹
        gravity: 0.1   // 重力
    };
    Screen.prototype = {
        initialize: function() {
            var self = this;
            // 生成小球
            self.createBalls();
            // 侦听碰撞
            self.timer = setInterval(function() {
                self.hitTest();
            }, 32);
        },
        createBalls: function() {
            var self = this, num = self.ballsnum, i = 0;
            var frag = document.createDocumentFragment();
            for (; i < num; i++) {
                var ball = new Ball(self.diameter, clss[Math.floor(Math.random() * (clss.length - 1))]);
                ball.radius = self.radius;
                ball.diameter = self.diameter;
                ball.style.left = (Math.random() * self.B_bound) + 'px';
                ball.style.top = (Math.random() * self.R_bound) + 'px';
                ball.vx = Math.random() * 6 - 3;
                ball.vy = Math.random() * 6 - 3;
                frag.appendChild(ball);
                self.balls[i] = ball;
            }
            self.container.appendChild(frag);
        },
        // 碰撞检测
        hitTest: function() {
            var self = this, num = self.ballsnum, balls = self.balls;
            for (var i = 0; i < num - 1; i++) {
                var ball0 = balls[i];
                ball0.x = ball0.offsetLeft + ball0.radius;
                ball0.y = ball0.offsetTop + ball0.radius;
                for (var j = i + 1; j < num; j++) {
                    var ball1 = balls[j];
                    ball1.x = ball1.offsetLeft + ball1.radius;
                    ball1.y = ball1.offsetTop + ball1.radius;
                    var dx = ball1.x - ball0.x;
                    var dy = ball1.y - ball0.y;
                    var dist = Math.sqrt(dx * dx + dy * dy);
                    var misDist = ball0.radius + ball1.radius;
                    if (dist < misDist) {
                        var angle = Math.atan2(dy, dx);
                        var tx = ball0.x + Math.cos(angle) * misDist;
                        var ty = ball0.y + Math.sin(angle) * misDist;
                        var ax = (tx - ball1.x) * self.spring;
                        var ay = (ty - ball1.y) * self.spring;
                        ball0.vx -= ax;
                        ball0.vy -= ay;
                        ball1.vx += ax;
                        ball1.vy += ay;
                    } 
                }
            }
            for (var i = 0; i < num; i++) {
                self.move(balls[i]);
            }
        },
        // 气泡运动
        move: function(ball) {
            var self = this;
            ball.vy += self.gravity;
            ball.style.left = (ball.offsetLeft + ball.vx) + 'px';
            ball.style.top = (ball.offsetTop + ball.vy) + 'px';
            // 边界检测
            var T = self.T_bound, B = self.B_bound, L = self.L_bound, R = self.R_bound, BC = self.bounce;
            if (ball.offsetLeft + ball.diameter > R) {
                ball.style.left = R - ball.diameter + 'px';
                ball.vx *= BC;
            } else if (ball.offsetLeft < L) {
                ball.style.left = L + 'px';
                ball.vx *= BC;
            } 
            if (ball.offsetTop + ball.diameter > B) {
                ball.style.top = B - ball.diameter + 'px';
                ball.vy *= BC;
            } else if (ball.offsetTop < T) {
                ball.style.top = T + 'px';
                ball.vy *= BC;
            } 
        }
    };
    return { Screen: Screen }
}();
window.onload = function() {
    var sc = null;
    T$('start').onclick = function() {
        document.getElementById('inner').innerHTML = '';
        sc = Bubble.Screen('inner', { ballsnum: 5, spring: 0.8, bounce: -0.95, gravity: 0.1});
        sc.initialize();
    };
    T$('stop').onclick = function() { clearInterval(sc.timer); }
    var bound = false
    T$('change').onclick = function() {
        if (!bound) {     
            T$('screen').style.backgroundImage = 'url("http://demo.3water.com/js/bubbling/o_bg1.jpg")';
            bound = true;
        } else {
            T$('screen').style.backgroundImage = 'url("http://demo.3water.com/js/bubbling/o_bg2.jpg")';
            bound = false;
        }
    }
}

【说明】
程序效率出现了很大瓶颈。需要做的优化还有很多。有时间继续完善。
另:感谢罗浮宫群友逍遥君武和豪情对图片的支持。
【源码下载】
https://3water.com/jiaoben/28295.html
Javascript 相关文章推荐
网页javascript精华代码集
Jan 24 Javascript
javascript 一个自定义长度的文本自动换行的函数
Aug 19 Javascript
JS辨别访问浏览器判断是android还是ios系统
Aug 19 Javascript
JQuery中使文本框获得焦点的方法实例分析
Feb 28 Javascript
jQuery中iframe的操作(点击按钮新增窗口)
Apr 20 Javascript
vue,angular,avalon这三种MVVM框架优缺点
Apr 27 Javascript
Jquery中attr与prop的区别详解
May 27 jQuery
vue使用axios实现文件上传进度的实时更新详解
Dec 20 Javascript
vue中的自定义分页插件组件的示例
Aug 18 Javascript
解决vue 绑定对象内点击事件失效问题
Sep 05 Javascript
解决vue 引入子组件报错的问题
Sep 06 Javascript
浅谈一个webpack构建速度优化误区
Jun 24 Javascript
浅谈javascript的数据类型检测
Jul 10 #Javascript
jquery nth-child()选择器的简单应用
Jul 10 #Javascript
SWFObject 2.1以上版本语法介绍
Jul 10 #Javascript
加载jQuery后$冲突的解决办法
Jul 09 #Javascript
在javascript将NodeList作为Array数组处理的方法
Jul 09 #Javascript
jquery multiSelect 多选下拉框
Jul 09 #Javascript
IE8 chrome中table隔行换色解决办法
Jul 09 #Javascript
You might like
PHP stream_context_create()函数的使用示例
2015/05/12 PHP
微信公众号开发客服接口实例代码
2016/10/21 PHP
PHP删除字符串中非字母数字字符方法总结
2019/01/20 PHP
javascript 学习之旅 (2)
2009/02/05 Javascript
JavaScript 继承详解(一)
2009/07/13 Javascript
JavaScript中两种链式调用实现代码
2011/01/12 Javascript
JavaScript在IE和FF下的兼容性问题
2014/05/19 Javascript
IE8中使用javascript动态加载CSS的解决方法
2014/06/17 Javascript
NodeJS Web应用监听sock文件实例
2015/02/18 NodeJs
JS实现先显示大图后自动收起显示小图的广告代码
2015/09/04 Javascript
前端性能优化及技巧
2016/05/06 Javascript
JavaScript仿淘宝页面图片滚动加载及刷新回顶部的方法解析
2016/05/24 Javascript
JavaScript必知必会(六) delete in instanceof
2016/06/08 Javascript
VUEJS实战之利用laypage插件实现分页(3)
2016/06/13 Javascript
jQuery 翻页组件yunm.pager.js实现div局部刷新的思路
2016/08/11 Javascript
AngularJS之页面跳转Route实例代码
2017/03/10 Javascript
WebGL学习教程之Three.js学习笔记(第一篇)
2019/04/25 Javascript
Vue 数组和对象更新,但是页面没有刷新的解决方式
2019/11/09 Javascript
vue移动端使用appClound拉起支付宝支付的实现方法
2019/11/21 Javascript
Angular封装表单控件及思想总结
2019/12/11 Javascript
python生成日历实例解析
2014/08/21 Python
基于Python实现定时自动给微信好友发送天气预报
2018/10/25 Python
Python3内置模块之base64编解码方法详解
2019/07/13 Python
python之拟合的实现
2019/07/19 Python
Python学习笔记之While循环用法分析
2019/08/14 Python
Django获取model中的字段名和字段的verbose_name方式
2020/05/19 Python
英国最大的女士服装零售商:Bonmarché
2017/08/17 全球购物
泰国折扣酒店预订:Hotels2Thailand
2018/03/20 全球购物
META-INF文件夹中的MANIFEST.MF的作用
2016/06/21 面试题
公司面试感谢信
2014/02/01 职场文书
公司2014年度工作总结
2014/12/10 职场文书
银行催款通知书
2015/04/17 职场文书
2015年出纳工作总结与计划
2015/05/18 职场文书
《称赞》教学反思
2016/02/17 职场文书
MongoDB数据库的安装步骤
2021/06/18 MongoDB
Nginx缓存设置案例详解
2021/09/15 Servers