我想使用带有 Three.js 的预先创建的画布。从我读过的教程和其他帖子来看,这应该有效:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext("2d"); // <--- This causes the error below!
const renderer = new THREE.WebGLRenderer( { canvas: canvas } );
Run Code Online (Sandbox Code Playgroud)
但是,在我的浏览器控制台(Safari v14 和 Chrome v86)中,我收到以下错误:
THREE.WebGLRenderer: Error creating WebGL context.
Run Code Online (Sandbox Code Playgroud)
我也尝试过添加
<canvas id='myCanvas'></canvas>
Run Code Online (Sandbox Code Playgroud)
并使用:
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d"); // <--- This causes the same error!
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
});
Run Code Online (Sandbox Code Playgroud)
并得到同样的问题。
我也尝试添加:
window.onload = function() {
...
};
Run Code Online (Sandbox Code Playgroud)
确保 DOM 已加载等
如果我删除这些getContext("2d")行,那么它可以工作吗?
我使用的是 Three.js 版本 0.120。
为什么这会导致问题?
Three.js 仅在一处抛出此错误,幸运的是它正在做一些非常简单的事情:从canvas. 它用于HTMLCanvasElement.getContext执行此操作,并且仅在结果为 时才抛出错误null。
HTMLCanvasElement.getContext只允许您请求一种上下文类型。webgl您可以再次请求相同的类型(或兼容的类型,在和 的情况下webgl2),但它将返回在画布上创建的原始上下文。在第一个请求建立使用中上下文后,后续对不兼容类型的请求将返回null。
let ctx_2d_1 = mycanvas.getContext( '2d' )
let ctx_2d_2 = mycanvas.getContext( '2d' )
console.log( ctx_2d_1 === ctx_2d_2 ) // true
Run Code Online (Sandbox Code Playgroud)
let ctx_2d = mycanvas.getContext( '2d' )
let ctx_webgl = mycanvas.getContext( 'webgl' )
console.log( ctx_2d ) // CanvasRenderingContext2D
console.log( ctx_webgl ) // null
Run Code Online (Sandbox Code Playgroud)
let ctx_webgl = mycanvas.getContext( 'webgl' )
let ctx_2d = mycanvas.getContext( '2d' )
console.log( ctx_webgl ) // WebGLRenderingContext
console.log( ctx_2d ) // null
Run Code Online (Sandbox Code Playgroud)
由于您在2d调用WebGLRenderer构造函数之前创建上下文,因此构造函数无法WebGLRenderingContext从画布获取有效值。相反,它得到一个null,因此它抛出错误。
如果您想在 3D 之上绘制 2D(反之亦然),则需要对不同上下文的画布进行分层,或者使用平面将 2D 信息渲染为 WebGL (third.js) 上下文中的纹理。