问题:我想在圆圈中排列div并为半径设置动画。不幸的是,我似乎对我的变量有某种约束性问题。试着从3天开始搞清楚这一点。我能做些什么来摆脱这种困境?我是说如何以“优雅的方式”解决这个问题?
我尝试了什么:我做了一些控制台日志,一切都暗示javascript在解释我对“this”的意思时遇到了问题。
我还发现我需要在requestAnimationFrame中绑定参数,但是我无法想象绑定每个变量和函数名称所以我必须在这里做错了。
这是JSFiddle:https://jsfiddle.net/Lh23pzvb/4/
代码:
function explodeRocket(obj) {
this.elem = document.getElementsByTagName('div');
this.particle = [];
this.radius = obj.radius;
this.color = ['red', 'yellow', 'cyan', 'orchid']
this.interval = 2 * Math.PI / obj.particles;
this.init = function() {
this.create();
this.blast();
}
this.init();
this.create = function() {
for(var i = 0; i < obj.particles; i++) {
document.body.appendChild(document.createElement('div'));
this.elem[i].style.background = this.color[obj.colorIndex];
this.particle.push(new this.Properties(0, obj.x, obj.y));
this.updatePosition(i);
}
}
this.Properties = function(angle, x, y) {
this.angle = angle;
this.x = x;
this.y = y;
}
this.updatePosition = function(index) {
this.elem[index].style.left = this.particle[index].x + 'px';
this.elem[index].style.top = this.particle[index].y + 'px';
}
this.blast = function() {
for(var i = 0; i < 10 - 1; i++) {
if(this.radius < obj.radiusMax) {
this.radius += 0.2;
}
this.particle[i].x = Math.round(window.innerWidth) / 2 + obj.radius * Math.cos(this.particle[i].angle) ;
this.particle[i].y = Math.round(window.innerHeight) / 2 + obj.radius * Math.sin(this.particle[i].angle);
this.updatePosition(i);
this.particle[i].angle += this.interval;
}
requestAnimationFrame(this.blast);
}
}
new explodeRocket({
particles: 4, colorIndex: 0, radius: 0, radiusMax: 200, x: 0, y: 0
})
答案 0 :(得分:2)
错误1:
在init()
函数初始化之前调用create()
,因此您无法调用它。您可以将init()
放在explodeRocket
函数的末尾来修复它,以便在调用init()
时存在所有函数。
错误2:
.blast()
运行循环次数太多。您只有4个粒子,但循环运行9次。您可以通过仅运行particle.length
次循环来修复它:
for(var i = 0; i < this.particle.length; i++) {
错误3:
this
错误。当您拨打this
时,您的代码会丢失requestAnimationFrame
。您可以使用Function.call
,它将this
对象作为第一个参数。将this
绑定到其他变量(例如self
)以解决这些问题很常见:
var self = this;
requestAnimationFrame(function() {
self.blast.call(self);
});
错误4:
您指的是obj.radius
,始终为0.您应该使用this.radius
:
this.particle[i].x = Math.round(window.innerWidth) / 2 + this.radius * Math.cos(this.particle[i].angle);
this.particle[i].y = Math.round(window.innerHeight) / 2 + this.radius * Math.sin(this.particle[i].angle);
错误5:
你可能不想总是旋转1/4轮,所以每帧的1/40圈动画:
this.particle[i].angle += this.interval * 0.1;
错误6:
您可能希望粒子均匀分布,因此使粒子初始化为适当的半径:
this.particle.push(new this.Properties(this.interval * i, obj.x, obj.y));
完整代码:
function explodeRocket(obj) {
var self = this;
this.elem = document.getElementsByTagName('div');
this.particle = [];
this.radius = obj.radius;
this.color = ['red', 'yellow', 'cyan', 'orchid']
this.interval = 2 * Math.PI / obj.particles;
this.init = function() {
this.create();
this.blast();
}
this.create = function() {
for(var i = 0; i < obj.particles; i++) {
document.body.appendChild(document.createElement('div'));
this.elem[i].style.background = this.color[obj.colorIndex];
this.particle.push(new this.Properties(this.interval * i, obj.x, obj.y));
this.updatePosition(i);
}
}
this.Properties = function(angle, x, y) {
this.angle = angle;
this.x = x;
this.y = y;
}
this.updatePosition = function(index) {
this.elem[index].style.left = this.particle[index].x + 'px';
this.elem[index].style.top = this.particle[index].y + 'px';
}
this.blast = function() {
for(var i = 0; i < this.particle.length; i++) {
if(this.radius < obj.radiusMax) {
this.radius += 0.2;
}
this.particle[i].x = Math.round(window.innerWidth) / 2 + this.radius * Math.cos(this.particle[i].angle);
this.particle[i].y = Math.round(window.innerHeight) / 2 + this.radius * Math.sin(this.particle[i].angle);
this.updatePosition(i);
this.particle[i].angle += this.interval * 0.1;
}
requestAnimationFrame(function() {
self.blast.call(self);
});
}
this.init();
}
new explodeRocket({
particles: 4, colorIndex: 0, radius: 0, radiusMax: 200, x: 0, y: 0
})
应该这样做!
修改强>
工作jsfiddle:https://jsfiddle.net/v3nt2kd0/
答案 1 :(得分:1)
首先,尝试在构造函数的末尾移动this.init();
。
在执行此操作之后,在blast()
方法中抛出了一些其他错误,这可能与this.particles
数组只有4个元素且您正在尝试执行的事实有关迭代左右。
作为提示,您可以移动explodeRocket.prototype
上的大多数(如果不是全部)方法,以便实例共享相同的方法实例,如下所示:
function ExplodeRocket(obj) {
//yada yada
}
ExplodeRocket.prototype.blast = function blast() {
//yada yada
}