Tilda站点Canvas故障动画在Safari显示黑屏问题求助
Safari中Canvas Glitch动画黑屏问题排查与修复
核心问题分析与修复步骤
1. 变量引用顺序错误(初始化直接报错)
你的代码中resize()函数在mesh创建前就被调用,此时mesh未定义,会抛出ReferenceError直接终止WebGL渲染流程,这是黑屏的核心原因。
修复方案:
将resize事件监听和resize()调用,移到mesh创建完成之后:
// ... 创建program、mesh之后 const mesh = new ogl.Mesh(gl, { geometry, program }); // 移到此处执行 window.addEventListener("resize", resize, false); resize();
2. 图片加载与纹理初始化时机不匹配
当前代码在图片未加载完成时就创建了渲染程序和网格,Safari对未初始化的纹理处理更严格,直接导致渲染黑屏。
修复方案:
把所有依赖纹理的初始化逻辑(program、mesh、事件监听、渲染启动等)放到图片onload回调中,确保纹理加载完成后再启动渲染:
const img = new Image(); img.crossOrigin = "Anonymous"; img.onload = () => { texture.image = img; // 计算纹理适配参数 let a1, a2; const imageAspect = imgSize[1] / imgSize[0]; if (window.innerHeight / window.innerWidth < imageAspect) { a1 = 1; a2 = window.innerHeight / window.innerWidth / imageAspect; } else { a1 = (window.innerWidth / window.innerHeight) * imageAspect; a2 = 1; } // 创建渲染程序与网格 const program = new ogl.Program(gl, { vertex, fragment, uniforms: { uTime: { value: 0 }, tWater: { value: texture }, res: { value: new ogl.Vec4(window.innerWidth, window.innerHeight, a1, a2) }, img: { value: new ogl.Vec2(imgSize[0], imgSize[1]) }, tFlow: flowmap.uniform } }); const mesh = new ogl.Mesh(gl, { geometry, program }); // 绑定resize事件 window.addEventListener("resize", resize, false); resize(); // 绑定鼠标/触摸事件 const isTouchCapable = "ontouchstart" in window; if (isTouchCapable) { window.addEventListener("touchstart", updateMouse, false); window.addEventListener("touchmove", updateMouse, { passive: false }); } else { window.addEventListener("mousemove", updateMouse, false); } // 启动渲染循环 requestAnimationFrame(update); }; img.src = "https://dl.dropboxusercontent.com/s/064wgjmnq6m49ca/глитч%20фон.jpg?dl=1";
3. 非2幂纹理的Wrap模式兼容问题
你的图片尺寸为1650x1000(非2的幂次方),OGL默认纹理Wrap模式为REPEAT,Safari不支持非2幂纹理使用该模式,会导致纹理失效。
修复方案:
创建Texture时显式设置Wrap模式为CLAMP_TO_EDGE:
const texture = new ogl.Texture(gl, { minFilter: gl.LINEAR, magFilter: gl.LINEAR, wrapS: gl.CLAMP_TO_EDGE, wrapT: gl.CLAMP_TO_EDGE });
4. 片段着色器精度兼容性优化(可选)
部分旧版Safari对highp精度支持有限,可添加降级声明:
// 片段着色器开头修改为 precision highp float; precision highp int; #ifdef GL_ES precision mediump float; #endif
内容的提问来源于stack exchange,提问作者Rodion Roddion
相关产品推荐
相关产品推荐

