class MySprite { x = 0; y = 0; radius = 0; margin = 0; ctx; _width = 0; _height = 0; _anchorX = 0; _anchorY = 0; _offX = 0; _offY = 0; scaleX = 1; scaleY = 1; _alpha = 1; rotation = 0; visible = true; skewX = 0; skewY = 0; _shadowFlag = false; _shadowColor; _shadowOffsetX = 0; _shadowOffsetY = 0; _shadowBlur = 5; _radius = 0; children = [this]; childDepandVisible = true; childDepandAlpha = false; img; _z = 0; constructor(ctx = null) { if (!ctx) { this.ctx = window['curCtx']; } else { this.ctx = ctx; } } init(imgObj = null, anchorX = 0.5, anchorY = 0.5) { if (imgObj) { this.img = imgObj; this.width = this.img.width; this.height = this.img.height; } this.anchorX = anchorX; this.anchorY = anchorY; } setShadow(offX, offY, blur, color = 'rgba(0, 0, 0, 0.3)') { this._shadowFlag = true; this._shadowColor = color; this._shadowOffsetX = offX; this._shadowOffsetY = offY; this._shadowBlur = blur; } setRadius(r) { this._radius = r; } update($event = null) { if (!this.visible && this.childDepandVisible) { return; } this.draw(); } draw() { this.ctx.save(); this.drawInit(); this.updateChildren(); this.ctx.restore(); } drawInit() { this.ctx.translate(this.x, this.y); this.ctx.rotate(this.rotation * Math.PI / 180); this.ctx.scale(this.scaleX, this.scaleY); this.ctx.globalAlpha = this.alpha; this.ctx.transform(1, this.skewX, this.skewY, 1, 0, 0); if (this._radius) { const r = this._radius; const w = this.width; const h = this.height; this.ctx.lineTo(-w / 2, h / 2); // 创建水平线 this.ctx.arcTo(-w / 2, -h / 2, -w / 2 + r, -h / 2, r); this.ctx.arcTo(w / 2, -h / 2, w / 2, -h / 2 + r, r); this.ctx.arcTo(w / 2, h / 2, w / 2 - r, h / 2, r); this.ctx.arcTo(-w / 2, h / 2, -w / 2, h / 2 - r, r); this.ctx.clip(); } } drawSelf() { if (this._shadowFlag) { this.ctx.shadowOffsetX = this._shadowOffsetX; this.ctx.shadowOffsetY = this._shadowOffsetY; this.ctx.shadowBlur = this._shadowBlur; this.ctx.shadowColor = this._shadowColor; } else { this.ctx.shadowOffsetX = 0; this.ctx.shadowOffsetY = 0; this.ctx.shadowBlur = null; this.ctx.shadowColor = null; } if (this.img) { this.ctx.drawImage(this.img, this._offX, this._offY); } } updateChildren() { if (this.children.length <= 0) { return; } for (let i = 0; i < this.children.length; i++) { if (this.children[i] === this) { if (this.visible) { this.drawSelf(); } } else { this.children[i].update(); } } } load(url, anchorX = 0.5, anchorY = 0.5) { return new Promise((resolve, reject) => { const img = new Image(); img.onload = () => resolve(img); img.onerror = reject; img.src = url; }).then(img => { this.init(img, anchorX, anchorY); return img; }); } addChild(child, z = 1) { if (this.children.indexOf(child) === -1) { this.children.push(child); child._z = z; child.parent = this; } this.children.sort((a, b) => { return a._z - b._z; }); if (this.childDepandAlpha) { child.alpha = this.alpha; } } removeChild(child) { const index = this.children.indexOf(child); if (index !== -1) { this.children.splice(index, 1); } } removeChildren() { for (let i = 0; i < this.children.length; i++) { if (this.children[i]) { if (this.children[i] != this) { this.children.splice(i, 1); i --; } } } } _changeChildAlpha(alpha) { for (let i = 0; i < this.children.length; i++) { if (this.children[i] != this) { this.children[i].alpha = alpha; } } } set alpha(v) { this._alpha = v; if (this.childDepandAlpha) { this._changeChildAlpha(v); } } get alpha() { return this._alpha; } set width(v) { this._width = v; this.refreshAnchorOff(); } get width() { return this._width; } set height(v) { this._height = v; this.refreshAnchorOff(); } get height() { return this._height; } set anchorX(value) { this._anchorX = value; this.refreshAnchorOff(); } get anchorX() { return this._anchorX; } set anchorY(value) { this._anchorY = value; this.refreshAnchorOff(); } get anchorY() { return this._anchorY; } refreshAnchorOff() { this._offX = -this._width * this.anchorX; this._offY = -this._height * this.anchorY; } setScaleXY(value) { this.scaleX = this.scaleY = value; } getBoundingBox() { const getParentData = (item) => { let px = item.x; let py = item.y; let sx = item.scaleX; let sy = item.scaleY; const parent = item.parent; if (parent) { const obj = getParentData(parent); const _x = obj.px; const _y = obj.py; const _sx = obj.sx; const _sy = obj.sy; px = _x + item.x * _sx; py = _y + item.y * _sy; sx *= _sx; sy *= _sy; } return {px, py, sx, sy}; }; const data = getParentData(this); const x = data.px + this._offX * Math.abs(data.sx); const y = data.py + this._offY * Math.abs(data.sy); const width = this.width * Math.abs(data.sx); const height = this.height * Math.abs(data.sy); // const x = this.x + this._offX * Math.abs(this.scaleX); // const y = this.y + this._offY * Math.abs(this.scaleY); // const width = this.width * Math.abs(this.scaleX); // const height = this.height * Math.abs(this.scaleY); return {x, y, width, height}; } }