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 相关文章推荐
Jquery Ajax学习实例7 Ajax所有过程事件分析示例
Mar 23 Javascript
Exjs 入门篇
Apr 07 Javascript
jQuery实现的立体文字渐变效果
May 17 Javascript
关于html+ashx开发中几个问题的解决方法
Jul 18 Javascript
js实现连续英文字符自动换行兼容ie6 ie7和firefox
Sep 06 Javascript
jQuery通过deferred对象管理ajax异步
May 20 Javascript
IE8利用自带的setCapture和releaseCapture解决iframe的拖拽事件方法
Oct 25 Javascript
bootstrap fileinput 上传插件的基础使用
Feb 17 Javascript
JavaScript闭包和回调详解
Aug 09 Javascript
JavaScript实现三级联动菜单效果
Aug 16 Javascript
React Native 使用Fetch发送网络请求的示例代码
Dec 02 Javascript
Layui实现带查询条件的分页
Jul 27 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
Smarty结合Ajax实现无刷新留言本实例
2007/01/02 PHP
比较全面的PHP数组的使用方法小结
2010/09/23 PHP
PHP中如何实现常用邮箱的基本判断
2014/01/07 PHP
ThinkPHP实现批量删除数据的代码实例
2014/07/02 PHP
PHP实现从PostgreSQL数据库检索数据分页显示及根据条件查找数据示例
2018/06/09 PHP
漂亮的jquery提示效果(仿腾讯弹出层)
2013/02/05 Javascript
javascript的alert box在java中如何显示多行
2014/05/18 Javascript
js老生常谈之this,constructor ,prototype全面解析
2016/04/05 Javascript
早该知道的7个JavaScript技巧
2016/06/21 Javascript
jQuery中show与hide方法用法示例
2016/09/16 Javascript
JavaScript验证知识整理
2017/03/24 Javascript
Ionic3 UI组件之autocomplete详解
2017/06/08 Javascript
vue webpack开发访问后台接口全局配置的方法
2018/09/18 Javascript
js实现通过开始结束控制的计时器
2019/02/25 Javascript
详解Vue-cli3 项目在安卓低版本系统和IE上白屏问题解决
2019/04/14 Javascript
Vue中UI组件库之Vuex与虚拟服务器初识
2019/05/07 Javascript
vue中的过滤器实例代码详解
2019/06/06 Javascript
纯异步nodejs文件夹(目录)复制功能
2019/09/03 NodeJs
[04:09]2014DOTA2国际邀请赛Ti西雅图 历届冠军相继出局 BBC综述今日比赛
2014/07/20 DOTA
[37:35]DOTA2上海特级锦标赛A组资格赛#1 Secret VS MVP.Phx第二局
2016/02/25 DOTA
Python的Django框架中的select_related函数对QuerySet 查询的优化
2015/04/01 Python
Python中字符串的处理技巧分享
2016/09/17 Python
使用pandas对两个dataframe进行join的实例
2018/06/08 Python
python PyAutoGUI 模拟鼠标键盘操作和截屏功能
2019/08/04 Python
如何查看python关键字
2021/01/17 Python
波兰数码相机及配件网上商店: Cyfrowe.pl
2017/06/19 全球购物
大学生村官事迹材料
2014/01/21 职场文书
数学国培研修感言
2014/02/13 职场文书
购房意向书范本
2014/04/01 职场文书
担保书格式及范文
2014/04/01 职场文书
创业女性典型材料
2014/05/02 职场文书
工业设计专业自荐书
2014/06/05 职场文书
赵乐秦在党的群众路线教育实践活动总结大会上的讲话稿
2014/10/25 职场文书
党员学习群众路线心得体会
2014/11/04 职场文书
学习保证书怎么写
2015/02/26 职场文书
2016春季运动会开幕词
2016/03/04 职场文书