71 lines
2.1 KiB
JavaScript
71 lines
2.1 KiB
JavaScript
// Spine WebGL 运行时在小程序的适配层
|
|
// 目标:在不提供 window / document / DOM 事件 的小程序环境里安全使用 spine-webgl。
|
|
|
|
function getGlobalObject() {
|
|
if (typeof globalThis !== 'undefined') return globalThis
|
|
if (typeof global !== 'undefined') return global
|
|
if (typeof self !== 'undefined') return self
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* 保证全局存在 WebGLRenderingContext 构造器。
|
|
* spine 的 ManagedWebGLRenderingContext 构造函数里有:
|
|
* if (!(canvasOrContext instanceof WebGLRenderingContext || ...))
|
|
* 若该标识符未声明会抛 ReferenceError。这里补一个普通函数(instanceof 恒为 false),
|
|
* 从而稳定进入「把入参当作 canvas、调用 getContext」的分支。
|
|
*/
|
|
function installWebGLShim() {
|
|
const g = getGlobalObject()
|
|
if (!g) return false
|
|
if (typeof g.WebGLRenderingContext === 'undefined') {
|
|
g.WebGLRenderingContext = function WebGLRenderingContext() {}
|
|
}
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* 用「假 canvas」包装原生 gl 上下文。
|
|
* spine 会调用 canvas.getContext() 并对 canvas 注册 webglcontextlost 事件,
|
|
* 小程序 canvas 没有 addEventListener,所以这里用空实现顶掉。
|
|
*/
|
|
function wrapGLContext(spineWebgl, gl, width, height) {
|
|
const canvasLike = {
|
|
width: width,
|
|
height: height,
|
|
getContext: function () {
|
|
return gl
|
|
},
|
|
addEventListener: function () {},
|
|
removeEventListener: function () {},
|
|
}
|
|
return new spineWebgl.ManagedWebGLRenderingContext(canvasLike)
|
|
}
|
|
|
|
/**
|
|
* 正交投影 MVP(列主序,WebGL 约定)。
|
|
* 把骨骼世界坐标 (x, y) 映射到像素画布:scale 为缩放,tx/ty 为原点在画布上的像素位置。
|
|
*/
|
|
function buildMVP(scale, tx, ty, width, height) {
|
|
return [
|
|
(2 * scale) / width, 0, 0, 0,
|
|
0, (2 * scale) / height, 0, 0,
|
|
0, 0, -1, 0,
|
|
(2 * tx) / width - 1, (2 * ty) / height - 1, 0, 1,
|
|
]
|
|
}
|
|
|
|
function baseName(p) {
|
|
const s = String(p || '')
|
|
const i = Math.max(s.lastIndexOf('/'), s.lastIndexOf('\\'))
|
|
return i >= 0 ? s.slice(i + 1) : s
|
|
}
|
|
|
|
module.exports = {
|
|
getGlobalObject,
|
|
installWebGLShim,
|
|
wrapGLContext,
|
|
buildMVP,
|
|
baseName,
|
|
}
|