Custom RenderNode - Cross-fade slide transition

Instead of the default fly-to animation when going from one slide to the next, this sample implements a custom RenderNode that applies a cross-fade transition when changing to different slides.

A new FadeRenderNode is created when a slide change is initiated by the user. When render node is ready, the desired slide is applied to the view, changing the view's camera to the new viewpoint in the background without a fly-to animation.

1
2
3
4
5
6
7
8
9
10
11
slideThumbnail.onclick = async () => {
  // create a new fade render node, and set its animation speed
  const node = new FadeRenderNode({ view });
  node.duration = speed.value * 1000;

  // Wait for node to capture current view before going to next one
  await node.ready;

  // apply slide without fly-to animation
  slide.applyTo(view, { animate: false });
}

On its creation, the FadeRenderNode immediately captures the current framebuffer (input), and returns that captured framebuffer until the animation starts.

1
2
3
4
5
6
7
// hold on to the framebuffer when the render function runs the first time
if (!this._startFramebuffer) {
  this._startFramebuffer = input; //retain ensures framebuffer is kept in memory
  this._startFramebuffer.retain();
  this._resolve?.();
  return this._startFramebuffer;
}

Once animation starts, the FadeRenderNode takes the current framebuffer (input) and the initially captured framebuffer (_startFraembuffer) and blends them together in each frame, according to animation time (delta). This creates the actual cross-fade effect between the start and the target view.

1
2
3
4
5
6
7
8
9
10
11

const currentTex = input.getTexture(gl.COLOR_ATTACHMENT0);
const startTex = this._startFramebuffer.getTexture(gl.COLOR_ATTACHMENT0);


#fragment shader
void main() {
  vec4 current = texture(currentTex, uv);
  vec4 start = texture(startTex, uv);
  fragColor = mix(start, current, delta);
}

When the animation is done, FadeRenderNode has finished its job. _startFramebuffer can be released, and the render node destroys itself.

1
2
3
4
5
6
if (delta >= 1) {
  this._startFramebuffer.release();
  this._startFramebuffer = null;
  this.destroy();
  return input;
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.

The developer dashboard has moved

You can no longer sign into this site. Go to your ArcGIS portal or the ArcGIS Location Platform dashboard to perform management tasks.

Your ArcGIS portal

Create, manage, and access API keys and OAuth 2.0 developer credentials, hosted layers, and data services.

Your ArcGIS Location Platform dashboard

Manage billing, monitor service usage, and access additional resources.

Learn more about these changes in the What's new in Esri Developers June 2024 blog post.

Close