js如何实现多张图片在页面上无覆盖的浮动,相遇后改变方向,触碰到四周也改变方向

js如何实现多张图片在页面上无覆盖的浮动,相遇后改变方向,触碰到四周也改变方向

无覆盖的浮动指的就是碰到就离开吗?
这个可以通过计算来完成。
但是比较麻烦。
单个图片碰到四周就是他的定位与监听的浏览器窗口四周做比较,相等就改变
多个图片就同时与其他以及四周做比较。
设计到的计算参数就是 每个图片的位置,大小,移动速度,四周的位置

 <script type="text/javascript" src="js/jquery.min.js"></script>

<style>
html, body{
  width: 100%;
  height: 100%;
  overflow:hidden;
  margin: 0;
  padding: 0;
  background-color: #000000;
}
.container{
  width: 100%;
  height: 100%;
  margin: 0;
}</style>
</head>
<body>

<div id="jsi-particle-container" class="container"></div>

<script>
var RENDERER = {
    init : function(){
        this.setParameters();
        this.reconstructMethods();
        this.createParticles();
        this.render();
    },
    setParameters : function(){
        this.$container = $('#jsi-particle-container');
        this.width = this.$container.width();
        this.height = this.$container.height();
        this.context = $('<canvas />').attr({width : this.width, height : this.height}).appendTo(this.$container).get(0).getContext('2d');
        this.particles = [];
    },
    reconstructMethods : function(){
        this.render = this.render.bind(this);
    },
    createParticles : function(){
        for(var i = 0, length = Math.round(this.width / 500 * this.height / 500 * 10); i < length; i++){
            this.particles.push(new PARTICLE(this.width, this.height));
        }
    },
    render : function(){
        requestAnimationFrame(this.render);
        this.context.clearRect(0, 0, this.width, this.height);

        for(var i = 0, length = this.particles.length; i < length; i++){
            this.particles[i].render(this.context);
        }
        this.checkCollision();
    },
    checkCollision : function(){
        for(var i = 0, particleCount = this.particles.length; i < particleCount; i++){
            var particle = this.particles[i];

            for(var j = i + 1; j < particleCount; j++){
                this.particles[j].checkCollision(particle);
            }
        }
    }
};
var PARTICLE = function(width, height){
    this.width = width;
    this.height = height;
    this.init();
};
PARTICLE.prototype = {
    COLOR : 'hsl(%h, 80%, %l%)',
    RADIUS : {MIN : 25, MAX : 35},
    MASS_RATE : 0.0001,
    VELOCITY : {MIN : 2, MAX : 4},
    WALL_RESTITUTION : 1.0,
    PARTICLE_RESTITUTION : 1.0,
    MAX_FACE_INDEX : 4,
    DELTA_SCALE : 0.01,
    INIT_RADIAN : 220,
    DELTA_RADIAN : {MIN : 4, MAX : 8},
    DELTA_THETA : Math.PI / 10,

    init : function(){
        this.radius = this.createRandomValue(this.RADIUS);
        this.mass = Math.round(Math.pow(this.radius, 3) * this.MASS_RATE);
        this.x = this.createRandomValue({MIN : this.radius, MAX : this.width - this.radius});
        this.y = this.createRandomValue({MIN : this.radius, MAX : this.height - this.radius});
        this.previousX = this.x;
        this.previousY = this.y;
        this.radian = this.INIT_RADIAN;
        this.deltaRadian = this.createRandomValue(this.DELTA_RADIAN) | 0;
        this.color = this.COLOR.replace('%h', this.radian);
        this.vx =  this.createRandomValue(this.VELOCITY) * ((Math.random() > 0.5) ? 1 : -1);
        this.vy =  this.createRandomValue(this.VELOCITY) * ((Math.random() > 0.5) ? 1 : -1);
        this.faceIndex = this.MAX_FACE_INDEX;
        this.scale = 0;
        this.theta = 0;
    },
    createRandomValue : function(range){
        return range.MIN + Math.round((range.MAX - range.MIN) * Math.random());
    },
    moveParticle : function(){
        this.previousX = this.x;
        this.previousY = this.y;
        this.x += this.vx;
        this.y += this.vy;

        if(this.x <= this.radius){
            this.x = this.radius;
            this.vx *= -this.WALL_RESTITUTION;
        }else if(this.x >= this.width - this.radius){
            this.x = this.width - this.radius;
            this.vx *= -this.WALL_RESTITUTION;
        }
        if(this.y <= this.radius){
            this.y = this.radius;
            this.vy *= -this.WALL_RESTITUTION;
        }else if(this.y > this.height - this.radius){
            this.y = this.height - this.radius;
            this.vy *= -this.WALL_RESTITUTION;
        }
    },
    getParticleInfo : function(){
        return {
            x : this.x,
            y : this.y,
            previousX : this.previousX,
            previousY : this.previousY,
            vx : this.vx,
            vy : this.vy,
            radius : this.radius,
            mass : this.mass,
            color : this.COLOR.replace('%h', this.radian)
        };
    },
    setParticleInfo : function(x, y, vx, vy){
        this.previousX = this.x;
        this.previousY = this.y;
        this.x = x;
        this.y = y;
        this.vx = vx;
        this.vy = vy;

        if(this.radian > 0){
            this.radian = Math.max(0, this.radian - this.deltaRadian);
        }
    },
    checkCollision : function(particle){
        if(this.radian == 0){
            return;
        }
        var particle1 = this.getParticleInfo(),
            particle2 = particle.getParticleInfo(),
            dx = particle2.x - particle1.x,
            dy = particle2.y - particle1.y,
            distance = Math.sqrt(dx * dx + dy * dy);

        if(distance > particle1.radius + particle2.radius){
            return;
        }
        var angle = Math.atan2(dy, dx),
            axis1 = {x : 0, y : 0},
            axis2 = this.rotate(dx, dy, angle),
            v1 = this.rotate(particle1.vx, particle1.vy, angle),
            v2 = this.rotate(particle2.vx, particle2.vy, angle),
            vSum = (v1.x - v2.x) * this.PARTICLE_RESTITUTION;

        v1.x = ((particle1.radius - particle2.radius * this.PARTICLE_RESTITUTION) * v1.x + particle2.radius * v2.x * (1 + this.PARTICLE_RESTITUTION)) / (particle1.radius + particle2.radius);
        v2.x = v1.x + vSum;

        var vAbs = Math.abs(v1.x) + Math.abs(v2.x),
            overlap = (particle1.radius + particle2.radius) - Math.abs(axis1.x - axis2.x);

        if(axis1.x >= axis2.x){
            axis1.x += Math.abs(overlap * v1.x / vAbs);
            axis2.x -= Math.abs(overlap * v2.x / vAbs);
        }else{
            axis1.x -= Math.abs(overlap * v1.x / vAbs);
            axis2.x += Math.abs(overlap * v2.x / vAbs);
        }
        axis1 = this.rotate(axis1.x, axis1.y, -angle);
        axis2 = this.rotate(axis2.x, axis2.y, -angle);
        v1 = this.rotate(v1.x, v1.y, -angle);
        v2 = this.rotate(v2.x, v2.y, -angle);

        this.setParticleInfo(particle1.x + axis1.x, particle1.y + axis1.y, v1.x, v1.y);
        particle.setParticleInfo(particle1.x + axis2.x, particle1.y + axis2.y, v2.x, v2.y);
    },
    rotate : function(x, y, angle){
        var sin = Math.sin(angle),
            cos = Math.cos(angle);
        return {x : x * cos + y * sin, y : y * cos - x * sin};
    },
    render : function(context){
        this.moveParticle();
        context.save();
        var axis = this.getParticleInfo();

        if(this.radian == 0){
            var scale = 1 + 4 * Math.pow((1 - this.scale), 5);
            context.translate(axis.x, axis.y);
            context.scale(scale, scale);
            context.rotate(Math.PI / 5 * Math.sin(this.theta));
            context.translate(-axis.x, -axis.y);
            context.globalAlpha = Math.max(0, this.scale);

            if(this.scale > 0){
                this.scale -= this.DELTA_SCALE;
                this.theta += this.DELTA_THETA;
                this.theta %= Math.PI * 2;
            }else{
                this.init();
            }
        }else if(this.scale < 1){
            context.translate(axis.x, axis.y);
            context.scale(this.scale, this.scale);
            context.translate(-axis.x, -axis.y);
            context.globalAlpha = this.scale;
            this.scale = Math.min(1, this.scale + this.DELTA_SCALE * 5);
        }
        context.beginPath();
        var gradient = context.createRadialGradient(axis.x, axis.y, 0, axis.x, axis.y, axis.radius);
        gradient.addColorStop(0, axis.color.replace('%l', '60'));
        gradient.addColorStop(1, axis.color.replace('%l', '30'));
        context.fillStyle = gradient;
        context.arc(axis.x, axis.y, axis.radius, 0, Math.PI * 2, true);
        context.fill();
        context.lineWidth = 2;
        context.strokeStyle = 'hsl(0, 0%, 100%)';
        context.fillStyle = 'hsl(0, 0%, 100%)';

        switch(Math.min(this.MAX_FACE_INDEX, Math.floor(this.radian / (this.INIT_RADIAN / (this.MAX_FACE_INDEX + 1))))){
        case 0:
            context.beginPath();
            context.moveTo(axis.x - 14, axis.y - 10);
            context.lineTo(axis.x - 4, axis.y - 2);
            context.moveTo(axis.x + 14, axis.y - 10);
            context.lineTo(axis.x + 4, axis.y - 2);
            context.moveTo(axis.x - 8, axis.y + 15);
            context.quadraticCurveTo(axis.x, axis.y + 5, axis.x + 8, axis.y + 15);
            context.stroke();
            break;
        case 1:
            context.beginPath();
            context.moveTo(axis.x - 15, axis.y - 8);
            context.quadraticCurveTo(axis.x - 10, axis.y, axis.x - 5, axis.y - 8);
            context.moveTo(axis.x + 15, axis.y - 8);
            context.quadraticCurveTo(axis.x + 10, axis.y, axis.x + 5, axis.y - 8);
            context.moveTo(axis.x - 8, axis.y + 15);
            context.quadraticCurveTo(axis.x, axis.y + 5, axis.x + 8, axis.y + 15);
            context.stroke();
            break;
        case 2:
            context.beginPath();
            context.moveTo(axis.x - 14, axis.y - 5);
            context.lineTo(axis.x - 4, axis.y - 5);
            context.moveTo(axis.x + 14, axis.y - 5);
            context.lineTo(axis.x + 4, axis.y - 5);
            context.moveTo(axis.x - 7, axis.y + 10);
            context.lineTo(axis.x + 7, axis.y + 10);
            context.stroke();
            break;
        case 3:
            context.beginPath();
            context.arc(axis.x - 10, axis.y - 5, 3, 0, Math.PI * 2, false);
            context.arc(axis.x + 10, axis.y - 5, 3, 0, Math.PI * 2, false);
            context.fill();
            context.beginPath();
            context.moveTo(axis.x - 7, axis.y + 5);
            context.quadraticCurveTo(axis.x, axis.y + 15, axis.x + 7, axis.y + 5);
            context.stroke();
            break;
        case 4:
            context.beginPath();
            context.moveTo(axis.x - 14, axis.y - 5);
            context.quadraticCurveTo(axis.x - 10, axis.y - 15, axis.x - 6, axis.y - 5);
            context.moveTo(axis.x + 14, axis.y - 5);
            context.quadraticCurveTo(axis.x + 10, axis.y - 15, axis.x + 6, axis.y - 5);
            context.moveTo(axis.x - 7, axis.y + 5);
            context.quadraticCurveTo(axis.x, axis.y + 15, axis.x + 7, axis.y + 5);
            context.stroke();
        }
        context.restore();
    }
};
$(function(){
    RENDERER.init();
});</script>
</body>