Canvas JavaScript HTML - 从一个父级创建多个实例



我正在初始化这样的类(字符是我程序中的一个类):

character = new Character();

我想要这个类/对象的两个实例,所以我尝试了这个:

character2 = new Character();

然而,字符2只是简单地取代了字符;因此,只有一个对象。是否可以创建另一个实例,或者我需要创建另一个 Character 类(大量代码重复!

我尝试为第二个对象添加第二个绘制函数(名为 draw2),但这没有帮助。

您需要将Character.prototype.draw方法的定义移出构造函数。否则,每次创建new Character()时,也会重写Character.prototype.draw方法。

您还需要将Character.prototype.draw方法中对局部构造函数变量(如xysize)的引用替换为对象属性(如this.Xthis.Ythis.Size)。

此外,您需要使img成为Character的(可能是静态的)属性。

现代 JS 中的对象创建

现代 JS 在定义对象时包含一些快捷方式。除非您要创建对象的许多实例,否则实际上不需要使用原型。使用对象时,访问原型会增加一些开销

您可以在创建函数中创建对象,该函数允许您通过闭包定义私有属性。

关闭创建私有属性

function Character() {
var x = 0;
var y = 0;
var size = 25;
var vx = 4;
var vy = 4;
var width = 45;
var height = 45;
var img = new Image();
img.src = 'character.jpg';
var pattern;
// using API = {rather than return {  allows you to access the instance of the
// inside this scope without having to use the `this` token
const API = {
get x() { return x },
get y() { return y },
get vx() { return vx },
get vy() { return vy },
get size() { return size },
get width() { return width },
get height() { return height },
set x(v) { x = v },
set y(v) { y = v },
set vx(v) { vx = v },
set vy(v) { vy = v },
set size(v) { size = v },
set width(v) { width = v },
set height(v) { height = v },
draw(ctx) {
ctx.save();
ctx.translate(x, y);
ctx.lineWidth = 2;
ctx.fillStyle = pattern ? pattern = ctx.createPattern(img, "no-repeat") : pattern;
ctx.beginPath();
ctx.moveTo(-size, -size);
ctx.lineTo(-size, size);
ctx.lineTo(size, size);
ctx.lineTo(size, -size);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
},
}
return API;
}

用法

var char = Character();
var char1 = Character();
// or 
var char = new Character();
var char1 = new Character();

性能注意事项

如果性能代码中需要该对象,则可能需要创建性能更高的资源库和 getter,或者避免 getter setter 开销并将属性包含在对象本身中。

function Character() {
var img = new Image();
img.src = 'character.jpg';
var pattern;
// using API = {rather than return {  allows you to access the instance of the
// inside this scope without having to use the `this` token
const API = {
x : 0, 
y : 0,
size : 25,
vx : 4,
vy : 4,
width : 45,
height : 45,
draw(ctx) {
const size = API.size;
ctx.save();
ctx.translate(API.x, API.y); // Note that I use API.x rather than this.x
ctx.lineWidth = 2;
ctx.fillStyle = pattern ? pattern = ctx.createPattern(img, "no-repeat") : pattern;
ctx.beginPath();
ctx.moveTo(-size, -size);
ctx.lineTo(-size, size);
ctx.lineTo(size, size);
ctx.lineTo(size, -size);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
},
}
return API;
}

笔记。

我注意到你的评论太多了。

例如

//public property for VX
Object.defineProperty(this, 'width',

//function public draw method
Character.prototype.draw = function (ctx) {
//save the ctx
ctx.save();
//set x and y
ctx.translate(x, y);
//set the line width
ctx.lineWidth = 2;

你在评论中陈述了显而易见的事情,没有机器会阅读它,没有人需要阅读它,那么为什么它在那里。注释会增加噪音,源代码噪音很危险,请避免代码中所有不必要的噪音。


每次调用 draw 函数时都会创建模式,这是不必要的开销。仅创建一次。


有时调用绘制函数可能不起作用,因为图像尚未加载。也许您应该管理对象之外的图像,在那里您可以确保媒体对象已加载并准备好使用,因为您尝试使用它们。


Character的每个实例将加载映像,创建 100 个映像,并且同一映像将有 100 个副本。这将对性能和内存产生负面影响。

最新更新