我有一个快照svg动画,动画一堆圆圈,如果它们在彼此的某个接近范围内,则在它们之间画一条线。但是,我意识到我可以做很多优化,但我不确定如何做到这一点。我觉得
会有用这是动画的一个工作示例:
http://jsfiddle.net/heaversm/sbj4W/1/
以下是我认为可以优化的内容:
每个圆圈都调用自己的动画功能 - 圆圈已全部添加到一个组中,我猜测有一种方法可以将随机运动应用于组的所有成员,而不是为每个成员调用一个函数以及小组中的每个元素。
for (var i=0; i<this.drawingConfig.circles.amount;i++){
...
this.animateSingle(circleShape);
}
接近函数很难 - 对于每个圆,对于每个更新周期,我必须遍历所有其他圆的数组,并找出X和Y坐标是否足够接近以绘制线。另外,这意味着您将获得重复的行,因为每个圆圈都会向其邻居绘制一条线,而不是在两者之间只有一条共享线。
for (var i=0;i<circles.length;i++){
var nextCircle = circles[i].node;
var nextCircleX = nextCircle.cx.baseVal.value;
var distance = Math.abs(nextCircleX-thisCircleX);
var proximity = mainModule.drawingConfig.circles.proximity;
if (distance < proximity){
var nextCircleY = nextCircle.cy.baseVal.value;
var thisCircleY = shape.node.cy.baseVal.value;
var distanceY = Math.abs(nextCircleY - thisCircleY);
if (distanceY < proximity){
var line = mainModule.s.line(thisCircleX, thisCircleY, nextCircleX, nextCircleY).attr({stroke: '#a6a8ab', strokeWidth: '1px'});
mainModule.drawingConfig.circles.circleGroup.add(line);
}
}
}
相应地,我每个圆圈的动画功能都会清除屏幕上的所有线条。理想情况下,所有圆圈都将共享一个更新功能,在该功能中,您将清除这些线条。
Snap.animate(startX, animX, function (val) {
var lines = Snap.selectAll('line');
lines.remove();
...
}, mainModule.drawingConfig.circles.animTime);
现在,我可以告诉渲染器无法跟上所有各种动画/循环。任何帮助优化上述内容的任何帮助(或者你能看到的其他任何我都很奇怪的东西,都会非常感激。
答案 0 :(得分:0)
我通过每隔10毫秒只在一个计时器上运行一个动画循环来清理它,并通过给它们一个斜率来动画圆圈的位置,并且每次更新,沿着该斜率继续它们。你可以在这里看到一个更新的小提琴:
http://jsfiddle.net/heaversm/fJ6fj/
var mainModule = {
s: Snap("#svg"),
drawingConfig: {
circles: {
amount: 20,
sizeMin: 10,
sizeMax: 20,
proximity: 100,
circleGroup: null,
circleArray: [],
animTime: 2000
},
canvas: {
width: 800,
height: 600
}
},
init: function(){
//this.sizeCanvas();
this.makeCircles();
},
sizeCanvas: function(){
$('#svg').width(800).height(600);
},
makeCircles: function(){
this.drawingConfig.circles.circleGroup = this.s.g();
for (var i=0; i<this.drawingConfig.circles.amount;i++){
var circleX = this.randomNumber(0, this.drawingConfig.canvas.width);
var circleY = this.randomNumber(0, this.drawingConfig.canvas.height);
var circleRadius = this.randomNumber(this.drawingConfig.circles.sizeMin,this.drawingConfig.circles.sizeMax);
var circleFill = '#'+Math.floor(Math.random()*16777215).toString(16);
var circleShape = this.s.circle(circleX, circleY, circleRadius);
circleShape.attr({
fill: circleFill
});
this.drawingConfig.circles.circleGroup.add(circleShape);
var circleIncline = this.setIncline();
var circleObj = { incline: circleIncline, shape: circleShape };
this.drawingConfig.circles.circleArray.push(circleObj);
}
this.update();
},
setIncline: function(){
return { incX: this.randomNumber(-5,5), incY: this.randomNumber(-5,5) }
},
update: function(){
var lines = Snap.selectAll('line');
lines.remove();
for (var i=0; i<this.drawingConfig.circles.amount; i++){
var circle = this.drawingConfig.circles.circleArray[i];
var circleX = circle.shape.node.cx.animVal.value;
var circleY = circle.shape.node.cy.animVal.value;
this.move(circle,circleX,circleY);
for (var j=0;j<i;j++){
if (i != j){
var circle2 = this.drawingConfig.circles.circleArray[j];
var circle2X = circle2.shape.node.cx.animVal.value;
var circle2Y = circle2.shape.node.cy.animVal.value;
var dist = mainModule.distance(circleX,circleY,circle2X,circle2Y);
if (dist <= mainModule.drawingConfig.circles.proximity){ //
var lineWeight = 10/dist;
var line = mainModule.s.line(circleX, circleY, circle2X, circle2Y).attr({stroke: '#a6a8ab', strokeWidth: '1px'});
}
if (dist <= 10) { //collision
circle.incline = mainModule.setIncline();
circle2.incline = mainModule.setIncline();
}
}
}
}
setTimeout(function(){ mainModule.update(); },10);
},
distance: function(circleX,circleY,circle2X,circle2Y){
var distX = circle2X - circleX;
var distY = circle2Y - circleY;
distX = distX*distX;
distY = distY*distY;
return Math.sqrt(distX + distY);
},
move: function(circle,curX,curY){
if (curX > this.drawingConfig.canvas.width || curX < 0) {
circle.incline.incX = -circle.incline.incX;
}
if (curY > this.drawingConfig.canvas.height || curY < 0) {
circle.incline.incY = -circle.incline.incY;
}
curX = curX + circle.incline.incX;
curY = curY + circle.incline.incY;
if (curX > this.drawingConfig.canvas.width) {
curX = this.drawingConfig.canvas.width;
circle.incline = this.setIncline();
} else if (curX < 0) {
curX = 0;
circle.incline = this.setIncline();
}
if (curY > this.drawingConfig.canvas.height) {
curY = this.drawingConfig.canvas.height;
circle.incline = this.setIncline();
} else if (curY < 0) {
curY = 0;
circle.incline = this.setIncline();
}
circle.shape.attr({ cx: curX, cy: curY });
},
randomNumber: function(min,max){
return Math.floor(Math.random()*(max-min+1)+min);
},
getBounds: function(shape){
shapeBox = shape.node.getBoundingClientRect();
}
}
mainModule.init();