// ============================================================ // SpineBackendCanvas —— Canvas 2D 渲染后端 // 由 SpineMgr 在 WebGL 不可用时使用。逻辑迁自 SpineMgr.updateAndDraw,行为不变。 // // 已知性能特征:开启 triangleRendering 后,spine-canvas 对每个三角形都执行一次 // clip() 加一次整张图集的 drawImage。mesh 密集的骨架(如 qixingshisanlan 2784 // 三角形)在 iOS WKWebView 上会因 clip 叠加非轴对齐变换失去 GPU 快路径而卡顿。 // 故本后端仅作回退,主路径见 SpineBackendWebGL。 // ============================================================ (function(){ var SpineBackendCanvas = { name: "canvas", _renderer: null, _ctx: null, // 是否可用:spine 运行时须提供 Canvas 2D 的 SkeletonRenderer isAvailable: function() { return !!(window.spine && window.spine.SkeletonRenderer && !window.spine.SceneRenderer); }, createAssetManager: function(basePath) { return new spine.AssetManager(basePath); }, // Canvas 后端:骨骼位置归零,实际位置由 drawEntry 的 ctx.translate 控制。 // 由 SpineMgr 在 updateWorldTransform 之前调用 —— 之后再改 skeleton.x/y 不会重算 // 世界变换,本帧不生效。 placeEntry: function(entry) { entry.skeleton.x = 0; entry.skeleton.y = 0; }, // 每帧开始:取 gameabc 的绘制上下文 beginFrame: function() { var ctx = gameabc_face.dc; if (!ctx) return false; this._ctx = ctx; if (!this._renderer) { this._renderer = new spine.SkeletonRenderer(ctx); this._renderer.triangleRendering = true; // ★ 启用三角形渲染以支持 Mesh 网格附件 } // 确保 renderer 用的是当前 ctx (gameabc可能重建) this._renderer.ctx = ctx; return true; }, drawEntry: function(entry) { var ctx = this._ctx; ctx.save(); ctx.translate(entry.x, entry.y); ctx.scale(1, -1); // ★ Spine Y-up → Canvas Y-down(scale 已烘焙进 SkeletonJson.scale) this._renderer.draw(entry.skeleton); ctx.restore(); }, endFrame: function() { this._ctx = null; } }; if (typeof module !== "undefined" && module.exports) { module.exports = SpineBackendCanvas; } window.SpineBackendCanvas = SpineBackendCanvas; })();