用canvas创建和使用类
Creating and using classes with canvas
我有一些麻烦,因为Javascript只是看起来可怕的类和实现是有趣的。我试图让这个块工作,所以我可以创建多个三角形:
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
var phase = 0;
var tau = 2 * Math.PI;
function animate() {
requestAnimationFrame(animate);
var sides = 3;
var size = 100;
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
phase += 0.005 * tau;
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
for (var i = 0; i <= sides; i++) {
context[i ? 'lineTo' : 'moveTo'](
centerX + size * Math.cos(phase + i / sides * tau),
centerY + size * Math.sin(phase + i / sides * tau)
);
}
context.stroke();
}
animate();
这里我试着把它变成一个类:
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
var phase = 0;
var tau = 2 * Math.PI;
function Triangle(cntx, canvs) {
this.ctx = cntx;
this.canv = canvs;
this.draw = drawTriangle;
}
function drawTriangle() {
requestAnimationFrame(drawTriangle);
var sides = 3;
var size = 100;
var centerX = this.canv.width / 2;
var centerY = this.canv.height / 2;
phase += 0.005 * tau;
this.ctx.clearRect(0, 0, this.canv.width, this.canv.height);
this.ctx.beginPath();
for (var i = 0; i <= sides; i++) {
this.ctx[i ? 'lineTo' : 'moveTo'](
centerX + size * Math.cos(phase + i / sides * tau),
centerY + size * Math.sin(phase + i / sides * tau)
);
}
this.ctx.stroke();
}
var triangle1 = new Triangle(context,canvas);
triangle1.draw();
问题是,它只是画三角形一次,所以我不确定我在这里做错了什么。
这里的问题是,您正在调用requestAnimationFrame
并传递回调到相同的函数,但this
关键字将引用window
对象,而不是您的类。
因此,您必须显式地将回调函数的上下文设置为与您相同的上下文,并且您可以通过调用.bind(this)
来实现这一点。看一下下面的例子:
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
var phase = 0;
var tau = 2 * Math.PI;
function Triangle(cntx, canvs) {
this.ctx = cntx;
this.canv = canvs;
this.draw = drawTriangle;
}
function drawTriangle() {
requestAnimationFrame(drawTriangle.bind(this));
var sides = 3;
var size = 100;
var centerX = this.canv.width / 2;
var centerY = this.canv.height / 2;
phase += 0.005 * tau;
this.ctx.clearRect(0, 0, this.canv.width, this.canv.height);
this.ctx.beginPath();
for (var i = 0; i <= sides; i++) {
this.ctx[i ? 'lineTo' : 'moveTo'](
centerX + size * Math.cos(phase + i / sides * tau),
centerY + size * Math.sin(phase + i / sides * tau)
);
}
this.ctx.stroke();
}
var triangle1 = new Triangle(context, canvas);
triangle1.draw();
<canvas></canvas>
您有两种方法可以将其作为javascript对象(不要将它们视为类)。
使用prototype定义对象方法的第一种方法。
function Triangle(cntx, canvs) { // define the triange
this.ctx = cntx;
this.canv = canvs;
this.draw = this.drawTriangle.bind(this);
}
// this creates and compiles the draw function ready to be used for any Triangle object you create.
Triangle.prototype.drawTriangle = function() { // define the draw method as part of
// triangle's prototype
requestAnimationFrame(this.draw); // all properties of Triangle.prototype can be referenced via 'this'
var sides = 3;
var size = 100;
var centerX = this.canv.width / 2;
var centerY = this.canv.height / 2;
phase += 0.005 * tau;
this.ctx.clearRect(0, 0, this.canv.width, this.canv.height);
this.ctx.beginPath();
for (var i = 0; i <= sides; i++) {
this.ctx[i ? 'lineTo' : 'moveTo'](
centerX + size * Math.cos(phase + i / sides * tau),
centerY + size * Math.sin(phase + i / sides * tau));
}
this.ctx.stroke();
}
var triangle1 = new Triangle(context, canvas);
triangle1.draw();
或者你可以用下面的代码创建一个更安全的三角形。在这种情况下,我们通过使用闭包来封装我们希望ctx
和canv
不再暴露并且只能从三角形对象调用中访问的变量来最小化this令牌的使用。使用闭包在运行时稍微快一些,但是在创建时慢一些。
function Triangle(cntx, canvs) {
var ctx = cntx; // create closure vars
var canv = canvs;
this.draw = (function() { // draw run faster because it does not have
// to search the prototype for the values
// of ctx and canv.
requestAnimationFrame(this.draw);
var sides = 3;
var size = 100;
var centerX = this.canv.width / 2;
var centerY = this.canv.height / 2;
phase += 0.005 * tau;
ctx.clearRect(0, 0, canv.width, canv.height); // dont need the this keyword
ctx.beginPath();
for (var i = 0; i <= sides; i++) {
ctx[i ? 'lineTo' : 'moveTo'](
centerX + size * Math.cos(phase + i / sides * tau),
centerY + size * Math.sin(phase + i / sides * tau));
}
ctx.stroke();
}).bind(this); // because requestAnimationFrame sets this wee need to bind the current this to the method.
}
var triangle1 = new Triangle(context, canvas); // It takes a little longer to invoke
// because it will need to create and compile
// the draw function.
triangle1.draw(); // but call this now runs a little faster.
在这种情况下,速度的差异非常小,一个比另一个的优势将取决于你创建新对象的频率和你调用它的方法的频率。如果您经常创建,请使用prototype
;如果您只创建一次,并且经常使用,请使用闭包。
相关文章:
- NodeJS canvas.createJPEGStream创建空文件
- 使用我在模拟器中创建的Canvas签名板,它运行良好,但在android设备中,两个签名板即将推出
- JS框架,用于在Canvas上创建可视化模拟
- 在 AngularJS 中使用 FontAwesome 创建 Canvas 指令
- Javascript/Canvas - 从预先存在的图像创建新图像
- HTML5 Canvas:通过 Image.prototype 创建一个 Image.onload() 函数
- Javascript和Canvas:绘制和删除线条以创建一个“呼吸”的圆圈
- 在正方形内创建n个角的多边形的算法(HTML5-Canvas)
- 使用Canvas/HTML5创建或显示N-QAM星座
- canvas js:如何动态删除数据点,但不创建“;“洞”;在图表中
- 在下面的代码中,在Fabric.js中单击鼠标时,Canvas层消失,Firefox在创建画布到图像时停止响应
- 为HTML5 Canvas游戏创建开始屏幕
- 用canvas创建和使用类
- FB.Canvas.setAutoGrow()不起作用并创建高度变化的无限循环
- 我如何在canvas的循环中创建一行星星
- 创建一个canvas链库
- 是自动创建为PNG文件的HTML Canvas标记的内容
- 用/javascript/canvas创建的形状动画
- 在JS中创建一个没有canvas实例的CanvasImageData对象
- 如何从数组中的图像源创建Canvas Image