Skip to main content

makeHtmlInCanvasPresentation()v4.0.456

Allows you to pass a shader to create a HTML-in-canvas-based @remotion/transitions presentation.

For a step-by-step walkthrough, see Custom HTML-in-canvas presentations.

API Usage
const myPresentation = makeHtmlInCanvasPresentation(myShader);
Show myShader implementation
Minimal crossfade shader
import {makeHtmlInCanvasPresentation, type HtmlInCanvasShader} from '@remotion/transitions'; const VERTEX = `#version 300 es in vec2 a_pos; out vec2 v_uv; void main() { v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5); gl_Position = vec4(a_pos, 0.0, 1.0); }`; const FRAGMENT = `#version 300 es precision highp float; uniform sampler2D u_prev; uniform sampler2D u_next; uniform float u_time; in vec2 v_uv; out vec4 outColor; void main() { outColor = mix(texture(u_next, v_uv), texture(u_prev, v_uv), u_time); }`; const myShader: HtmlInCanvasShader<{}> = (canvas) => { const gl = canvas.getContext('webgl2', {premultipliedAlpha: true})!; const compile = (src: string, type: number) => { const sh = gl.createShader(type)!; gl.shaderSource(sh, src); gl.compileShader(sh); return sh; }; const program = gl.createProgram()!; gl.attachShader(program, compile(VERTEX, gl.VERTEX_SHADER)); gl.attachShader(program, compile(FRAGMENT, gl.FRAGMENT_SHADER)); gl.linkProgram(program); const buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData( gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW, ); const aPos = gl.getAttribLocation(program, 'a_pos'); gl.enableVertexAttribArray(aPos); gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0); const prevTex = gl.createTexture(); const nextTex = gl.createTexture(); return { clear: () => { gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); }, cleanup: () => { gl.deleteProgram(program); gl.deleteTexture(prevTex); gl.deleteTexture(nextTex); gl.deleteBuffer(buffer); }, draw: ({prevImage, nextImage, width, height, time}) => { gl.viewport(0, 0, width, height); gl.useProgram(program); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, prevTex); if (prevImage) { gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, prevImage, ); } gl.uniform1i(gl.getUniformLocation(program, 'u_prev'), 0); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, nextTex); if (nextImage) { gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, nextImage, ); } gl.uniform1i(gl.getUniformLocation(program, 'u_next'), 1); const t = !prevImage ? 0 : !nextImage ? 1 : time; gl.uniform1f(gl.getUniformLocation(program, 'u_time'), t); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); }, }; }; const myPresentation = makeHtmlInCanvasPresentation(myShader);
warning

HTML-in-canvas requires Google Chrome with chrome://flags/#canvas-draw-element enabled.

Arguments​

shader​

A function of type HtmlInCanvasShader<Props>.
Must return an object with three callbacks: clear, cleanup and draw.

clear()​

Called when there is nothing to draw (both scenes are unmounted).
Typically clears the WebGL color buffer.

cleanup()​

Called once when the transition unmounts.
Release any GL resources you allocated.

draw()​

Called every frame the transition is active.
Has the type HtmlInCanvasShaderDraw<Props>; the argument has the type HtmlInCanvasShaderDrawParams<Props>.

prevImage​

OffscreenCanvas | null — the rasterized exiting scene. null while it has not yet rendered (e.g. at the very start).

nextImage​

OffscreenCanvas | null — the rasterized entering scene. null after the entering scene has unmounted.

Upload these sources to WebGL textures using texImage2D().

width / height​

The pixel size of the canvas to draw into.

time​

A number between 0 and 1.

time = 0 means the shader should output the entering scene fully (i.e. transition end), and time = 1 means the shader should output the exiting scene fully (i.e. transition start).

When one image is missing, treat it as the boundary case: if !prevImage, force time = 0 so the shader falls back to nextImage only; if !nextImage, force time = 1 so the shader falls back to prevImage only.

passedProps​

Whatever you typed your Props as.

Return value​

A presentation that you can pass to a <TransitionSeries.Transition>.

Types​

HtmlInCanvasShader​

import type {
  HtmlInCanvasShader,
(alias) type HtmlInCanvasShader<Props> = (canvas: OffscreenCanvas) => { clear: () => void; cleanup: () => void; draw: HtmlInCanvasShaderDraw<Props>; } import HtmlInCanvasShader
} from '@remotion/transitions';

HtmlInCanvasShaderDraw​

import type {
  HtmlInCanvasShaderDraw,
(alias) type HtmlInCanvasShaderDraw<Props> = (params: HtmlInCanvasShaderDrawParams<Props>) => void import HtmlInCanvasShaderDraw
} from '@remotion/transitions';

HtmlInCanvasShaderDrawParams​

import type {
  HtmlInCanvasShaderDrawParams,
(alias) type HtmlInCanvasShaderDrawParams<Props> = { prevImage: OffscreenCanvas | null; nextImage: OffscreenCanvas | null; width: number; height: number; time: number; passedProps: Props; } import HtmlInCanvasShaderDrawParams
} from '@remotion/transitions';

See also​