Fix clouds2d: create own canvas element
The 2D WebGL renderer now creates its own <canvas> overlay inside the target element, instead of expecting the target to already be a canvas. This fixes 'canvas.getContext is not a function' when the target is a <div>.
This commit is contained in:
1 parent
e8df75eebc
commit
c6764fd534
4 files changed
+77
-63
No files matched your search
+38
-31
@@ -927,7 +927,7 @@ else window.SunCalc = SunCalc;
|
||||
<body>
|
||||
<div id="vanta" style="background: #1c1b1f;"></div>
|
||||
<div id="debug-panel">
|
||||
<div class="debug-title expanded" onclick="toggleDebugPanel()"><span>DEBUG - Palette: <span id="dbg-palette-name">Ash</span></span><span class="debug-title-toggle" id="debug-toggle-icon">▼</span></div>
|
||||
<div class="debug-title expanded" onclick="toggleDebugPanel()">\n<span>DEBUG - Palette: <span id="dbg-palette-name">Ash</span></span><span class="debug-title-toggle" id="debug-toggle-icon">▼</span></div>
|
||||
<div id="debug-content" class="debug-content">
|
||||
<div class="debug-controls">
|
||||
<select id="dbg-theme-select" class="debug-select" onchange="setDebugTheme(this.value)">
|
||||
@@ -1094,6 +1094,7 @@ else window.SunCalc = SunCalc;
|
||||
* fragment shader to produce animated cloud-like patterns.
|
||||
*
|
||||
* Drop-in replacement for Vanta when CONFIG.renderer === 'clouds2d'.
|
||||
* Creates its own <canvas> overlay and attaches to the target element.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
@@ -1180,7 +1181,7 @@ var FRAG_SRC = [
|
||||
function init(canvas) {
|
||||
var gl = canvas.getContext('webgl', { antialias: false, alpha: false });
|
||||
if (!gl) {
|
||||
console.error('clouds2d: WebGL not available, using fallback');
|
||||
console.error('clouds2d: WebGL not available');
|
||||
return null;
|
||||
}
|
||||
var prog = makeProgram(gl, VERT_SRC, FRAG_SRC);
|
||||
@@ -1209,22 +1210,38 @@ function init(canvas) {
|
||||
|
||||
function hex(r, g, b) { return [r/255, g/255, b/255]; }
|
||||
|
||||
window.clouds2dRender = function(canvas) {
|
||||
if (!canvas) {
|
||||
console.error('clouds2d: no canvas');
|
||||
window.clouds2dRender = function(target) {
|
||||
if (!target || typeof target !== 'object') {
|
||||
console.error('clouds2d: invalid target');
|
||||
return;
|
||||
}
|
||||
if (!canvas._clouds2d) {
|
||||
canvas._clouds2d = init(canvas);
|
||||
if (!canvas._clouds2d) {
|
||||
// Fallback: render the body background color via 2D canvas
|
||||
return;
|
||||
}
|
||||
// Get or create the WebGL canvas
|
||||
var canvas = target.__clouds2dCanvas;
|
||||
if (!canvas) {
|
||||
// Replace the target's content with a WebGL canvas
|
||||
canvas = document.createElement('canvas');
|
||||
canvas.style.position = 'absolute';
|
||||
canvas.style.top = '0';
|
||||
canvas.style.left = '0';
|
||||
canvas.style.width = '100%';
|
||||
canvas.style.height = '100%';
|
||||
// Empty the target and insert the canvas as the only child
|
||||
while (target.firstChild) target.removeChild(target.firstChild);
|
||||
target.appendChild(canvas);
|
||||
target.style.position = 'relative';
|
||||
target.__clouds2dCanvas = canvas;
|
||||
}
|
||||
var s = canvas._clouds2d;
|
||||
|
||||
if (!canvas.__state) {
|
||||
canvas.__state = init(canvas);
|
||||
if (!canvas.__state) return;
|
||||
}
|
||||
|
||||
var s = canvas.__state;
|
||||
var gl = s.gl;
|
||||
var w = canvas.width, h = canvas.height;
|
||||
gl.viewport(0, 0, w, h);
|
||||
canvas.width = target.clientWidth || window.innerWidth;
|
||||
canvas.height = target.clientHeight || window.innerHeight;
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
|
||||
gl.clearColor(0, 0, 0, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
@@ -1234,14 +1251,12 @@ window.clouds2dRender = function(canvas) {
|
||||
gl.enableVertexAttribArray(s.aPos);
|
||||
gl.vertexAttribPointer(s.aPos, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.uniform2f(s.uRes, w, h);
|
||||
gl.uniform2f(s.uRes, canvas.width, canvas.height);
|
||||
gl.uniform1f(s.uTime, performance.now() / 1000);
|
||||
|
||||
// Default theme colors (used until renderWeather() sets the right ones)
|
||||
var sky = [0.39, 0.54, 0.78];
|
||||
var cloud = [0.43, 0.43, 0.43];
|
||||
var light = [0.89, 0.87, 0.82];
|
||||
// Pull from the same source as Vanta does
|
||||
var cfg = window.CONFIG || {};
|
||||
var theme = (cfg.currentWeatherTheme || (cfg.weatherThemes && cfg.weatherThemes[cfg.theme])) || null;
|
||||
if (theme) {
|
||||
@@ -1257,18 +1272,6 @@ window.clouds2dRender = function(canvas) {
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
||||
};
|
||||
|
||||
// Auto-render loop: keep the render in sync with rAF so the canvas
|
||||
// always shows the latest frame.
|
||||
window.clouds2dStart = function() {
|
||||
if (window._clouds2dRaf) return;
|
||||
function loop() {
|
||||
var c = document.getElementById('vanta');
|
||||
if (c) window.clouds2dRender(c);
|
||||
window._clouds2dRaf = requestAnimationFrame(loop);
|
||||
}
|
||||
window._clouds2dRaf = requestAnimationFrame(loop);
|
||||
};
|
||||
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
@@ -2455,7 +2458,11 @@ window.weatherThemes = {
|
||||
}
|
||||
|
||||
function tick() {
|
||||
updateClockAndEvents();
|
||||
try {
|
||||
updateClockAndEvents();
|
||||
} catch (e) {
|
||||
console.error('Tick error:', e);
|
||||
}
|
||||
setTimeout(tick, 1000);
|
||||
}
|
||||
|
||||
@@ -2721,7 +2728,7 @@ window.weatherThemes = {
|
||||
// Fetch location label from lat/lon if available
|
||||
fetchLocationLabel();
|
||||
animate();
|
||||
tick();
|
||||
try { tick(); } catch (e) { console.error('Initial tick error:', e); }
|
||||
|
||||
fetchWeather();
|
||||
setInterval(fetchWeather, 15 * 60 * 1000);
|
||||
|
||||
Reference in new issue
Block a user