切换JavaScript模块后全局gl变量在工具函数中未定义的解决方法
解决模块模式下WebGL工具函数无法访问上下文的问题
模块模式下,JS文件的顶级作用域不再是全局window,这就导致webgl_test.js里定义的gl变量无法被普通脚本glutils.js访问到。以下是几种不用传递gl参数的优雅解决方法:
方法一:将工具文件改为模块,通过共享上下文绑定
把glutils.js改成ES模块,新增一个设置上下文的函数,在初始化WebGL后将上下文传入工具模块,后续工具函数直接使用这个共享的上下文:
修改glutils.js为模块:
let glContext = null; // 提供设置上下文的接口 export function setGLContext(gl) { glContext = gl; } export function updateGLTexture(texture, format, genMipmaps, data) { const gl = glContext; gl.bindTexture(gl.TEXTURE_2D, texture); // 原有业务代码 gl.bindTexture(gl.TEXTURE_2D, 0); } // 其他工具函数同理...
修改webgl_test.js导入并设置上下文:
import { setGLContext, updateGLTexture } from './glutils.js'; let gl, canvas = null; function init() { canvas = document.createElement('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); gl = canvas.getContext('webgl2', { antialias: false }); // 将初始化好的上下文传入工具模块 setGLContext(gl); // 正常调用工具函数 updateGLTexture(/* 传入对应参数 */); } init();
方法二:封装WebGL工具类,实例化时绑定上下文
采用面向对象的方式,将工具函数封装为类的方法,实例化时传入WebGL上下文,每个工具实例绑定对应的上下文,更适合多画布场景:
修改glutils.js为模块:
export class GLUtils { constructor(gl) { this.gl = gl; } updateGLTexture(texture, format, genMipmaps, data) { const gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, texture); // 原有业务代码 gl.bindTexture(gl.TEXTURE_2D, 0); } // 其他工具方法... }
修改webgl_test.js实例化工具类:
import { GLUtils } from './glutils.js'; let gl, canvas = null; let glUtils; function init() { canvas = document.createElement('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); gl = canvas.getContext('webgl2', { antialias: false }); // 实例化工具类并传入上下文 glUtils = new GLUtils(gl); // 通过实例调用工具方法 glUtils.updateGLTexture(/* 传入对应参数 */); } init();
方法三:临时过渡方案——将上下文挂载到全局(不推荐)
如果不想大幅修改现有代码,可以将gl挂载到window对象上,让普通脚本glutils.js能访问到全局的上下文:
修改webgl_test.js:
let gl, canvas = null; function init() { canvas = document.createElement('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; document.body.appendChild(canvas); gl = canvas.getContext('webgl2', { antialias: false }); // 将上下文挂载到全局window window.gl = gl; // 正常调用工具函数 updateGLTexture(/* 传入对应参数 */); } init();
该方法简单但会污染全局作用域,不符合模块化设计理念,仅适合临时过渡使用。
内容的提问来源于stack exchange,提问作者Michael IV
相关产品推荐
相关产品推荐

