我有以下构造函数和原型:
function drawCircles() {
$.each(circles, function() {
this.draw(context);
});
}
Circle.prototype.draw = function {
// Drawing the circle using HTML5 canvas tag
}
circles
是一个数组。渲染时,如何在每个圆圈之间以100毫秒的间隔绘制所有圆圈?
我尝试了以下但是它返回了
Uncaught TypeError: this.draw is not a function
function drawCircles() {
// context.clearRect(0, 0, screenW, screenH);
var interval;
$.each(circles, function(index) {
setTimeout(function(){
this.draw(context);
}, interval);
interval += 500;
});
}
答案 0 :(得分:0)
您必须为此使用异步方法(而不是for循环)。
你可以通过制作一个闭包来做到这一点。例如:
function drawCircles() { // main function
var i = 0, me = this; // parent scope: iterator, self
if (!circles.length) return; // no circles to draw
(function loop() { // inner loop
var circle = circles[i++]; // get circle and increment iterator
me.draw(circle, context); // draw
if (i >= circles.length) i = 0; // reset iterator
setTimeout(loop, 100); // wait 100 ms, call inner loop
})(); // self-invoked
}
您可以使用flag或取消超时来停止循环。
function CircleCascade(context) {
this.circles = [];
this.context = context;
}
CircleCascade.prototype = {
generate: function(count) {
for(var i = 0; i < count; i++) {
this.circles.push({
x: Math.random() * this.context.canvas.width,
y: Math.random() * this.context.canvas.height,
r: Math.random() * 100 + 20,
c: "hsl(" + (360 * Math.random()) + ",50%,50%)"
})
}
},
drawCircles: function() { // main function
var i = 0, me = this; // parent scope: iterator, self
if (!me.circles.length) return; // no circles to draw
(function loop() { // inner loop
var circle = me.circles[i++]; // get circle and increment iterator
me.draw(circle, me.context); // draw
if (i >= me.circles.length) i=0; // reset iterator
setTimeout(loop, 100); // wait 100 ms, call inner loop
})(); // self-invoked
},
draw: function(circle, context) {
context.beginPath();
context.fillStyle = circle.c;
context.arc(circle.x, circle.y, circle.r, 0, 6.28);
context.fill();
}
};
var ctx = c.getContext("2d");
var cc = new CircleCascade(ctx);
cc.generate(50);
cc.drawCircles();
<canvas id=c width=600 height=400></canvas>
答案 1 :(得分:0)
您可以将函数绑定到自己的引用,然后直接从setTimeout
函数调用它。
首先在Circle构造函数中绑定draw函数。
function Circle(settings){
Object.assign(this,settings);
this.draw = Circle.prototype.draw.bind(this);
}
正常构建原型
Circle.prototype = {
draw(){
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
ctx.stroke();
}
}
然后以间隔绘制圆圈,您可以将绑定绘制函数直接传递给setTimeout
函数。
const circleInterval = 100;
function drawCircles(){
circles.forEach((circle, i) => setTimeout(circle.draw, (i + 1) * circleInterval));
}
//==========================================================
// helper functions randI for random integer and setOf creates an array
const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
const setOf = (count, cb = (i)=>i) => {var a = [],i = 0; while (i < count) { a.push(cb(i ++)) } return a };
//==========================================================
// get canvas an set example constants
const w = canvas.width = innerWidth;
const h = canvas.height = innerHeight;
const ctx = canvas.getContext("2d");
const circleCount = 1500;
const circleInterval = 100;
//==========================================================
function Circle(settings) {
Object.assign(this, settings);
this.draw = Circle.prototype.draw.bind(this);
}
Circle.prototype = {
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
ctx.stroke();
}
}
//==========================================================
// create circle array
const circles = setOf(circleCount, () => new Circle({ x: randI(w), y: randI(h), r: randI(20, 100)}));
//==========================================================
// draw the circles at intervals
function drawCircles() {
circles.forEach((circle, i) => setTimeout(circle.draw, (i + 1) * circleInterval));
}
drawCircles()
&#13;
canvas {
position: absolute;
top: 0px;
left: 0px;
}
&#13;
<canvas id="canvas"></canvas>
&#13;