GIF not animating over canvas element in Firefox

Encountering a strange issue on Firefox where a gif used as a background image isn't playing when there's a canvas animation, unlike in Webkit where everything works fine.

const separation = 100, amountX = 70, amountY = 50;
let container, camera, scene, renderer, particles;
let count = 0, windowHalfX = window.innerWidth / 2, windowHalfY = window.innerHeight / 2, cameraPosition = 80;

const init = () => {
  container = document.createElement('div');
  document.body.appendChild(container);
  
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.x = cameraPosition;
  camera.position.y = 1000;
  camera.position.z = -550;
  camera.zoom = 1.2;
  
  scene = new THREE.Scene();
  
  const numParticles = amountX * amountY;
  const positions = new Float32Array(numParticles * 3);
  const scales = new Float32Array(numParticles);

  let i = 0, j = 0;
  
  for(let ix = 0; ix < amountX; ix++) {
    for(let iy = 0; iy < amountY; iy++) {
      positions[i] = ix * separation - ((amountX * separation ) / 2);
      positions[i + 1] = 0;
      positions[i + 2] = iy * separation - ((amountY * separation ) / 2);

      scales[j] = 1;

      i += 3;
      j ++;
    }
  }
  
  const geometry = new THREE.BufferGeometry();
  geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
  geometry.setAttribute('scale', new THREE.BufferAttribute(scales, 1));
  
  const material = new THREE.ShaderMaterial({
    uniforms: {
      color: {value: new THREE.Color(0xeae6c3)},
    },
    vertexShader: document.getElementById('vertexshader').textContent,
    fragmentShader: document.getElementById('fragmentshader').textContent,
  });
  
  particles = new THREE.Points(geometry, material);
  scene.add(particles);
  
  renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setClearColor(0x192735, 1);
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  container.appendChild(renderer.domElement);
  container.style.touchAction = 'none';
  
  window.addEventListener( 'resize', onWindowResize );
};

const onWindowResize = () => {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize( window.innerWidth, window.innerHeight );
};

const render = () => {
  camera.lookAt(scene.position);

  const positions = particles.geometry.attributes.position.array;
  const scales = particles.geometry.attributes.scale.array;

  let i = 0, j = 0;

  for (let ix = 0; ix < amountX; ix ++) {
    for (let iy = 0; iy < amountY; iy ++) {
      positions[i + 1] = (Math.sin((ix + count) * 0.3) * 50) + (Math.sin((iy + count) * 0.5) * 50);

      scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 7 + (Math.sin((iy + count) * 0.5) + 1) * 7;

      i += 3;
      j ++;
    }
  }

  particles.geometry.attributes.position.needsUpdate = true;
  particles.geometry.attributes.scale.needsUpdate = true;

  renderer.render(scene, camera);

  count += 0.011;
};

const animate = () => {
  requestAnimationFrame(animate);

  render();
};

init();
animate();

const moveCamera = () => {
  cameraPosition = 150;
};
body::after {
  content: '';
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  background-image: url(https://res.cloudinary.com/axiol/image/upload/v1612477975/CodePen/noise.gif);
  opacity: 0.05;
  pointer-events: none;
}

canvas {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: none;
  z-index: -1;
}
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="02766a70676742322c3330372c30">[email protected]</a>/build/three.min.js"></script>
<script type="x-shader/x-vertex" id="vertexshader">
  attribute float scale;
  void main() {
    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
    gl_PointSize = scale * (300.0 / - mvPosition.z);
    gl_Position = projectionMatrix * mvPosition;
  }
</script>

<script type="x-shader/x-fragment" id="fragmentshader">
  uniform vec3 color;
  void main() {
  if (length(gl_PointCoord - vec2(0.5, 0.5)) > 0.475 ) discard;
    gl_FragColor = vec4(color, 1.0);
  }
</script>

Running into a perplexing issue with a canvas animation and gif background not syncing properly on Firefox. On another test, noticed that the gif animates only when the mouse moves, but stops once the movement halts. Any insights on this?

Curious to know if anyone has encountered similar behavior before?

Answer №1

It appears that there has been a recent regression (one week), likely triggered by this specific commit.
I have raised an issue at https://bugzilla.mozilla.org/1692736, in the hopes that it gets resolved before making its way to the stable branch.

To work around this bug, you can either disable WebRender in your Firefox browser by navigating to about:config and toggling gfx.webrender.force-disabled to false, or trigger a re-rendering of the element where the GIF is displayed, for instance, through a slight opacity change using CSS animation:

const separation = 100, amountX = 70, amountY = 50;
let container, camera, scene, renderer, particles;
let count = 0, windowHalfX = window.innerWidth / 2, windowHalfY = window.innerHeight / 2, cameraPosition = 80;

// Rest of the JavaScript code omitted for brevity 
/* 
  Applying a minimal opacity variation
  to ensure the gif image undergoes rerendering
*/
@keyframes bug1692736 { to { opacity: 0.051; } }
body::after {
  animation: bug1692736 10s infinite;
  content: '';
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  background-image: url(https://res.cloudinary.com/axiol/image/upload/v1612477975/CodePen/noise.gif);
  opacity: 0.05;
  pointer-events: none;
}

canvas {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: none;
  z-index: -1;
}
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dfabb7adbaba9feff1eeedeaf1ed">[email protected]</a>/build/three.min.js"></script>
<script type="x-shader/x-vertex" id="vertexshader">
  attribute float scale;
  void main() {
    vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
    gl_PointSize = scale * (300.0 / -mvPosition.z);
    gl_Position = projectionMatrix * mvPosition;
  }
</script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Downloading Breeze Navigation Properties for Offline Use

I am currently utilizing the most recent versions of Angular, breeze, and EF. Within the client environment, I am working on creating a sophisticated object named Quote that is associated with a job. This Quote includes a QuoteMeasure, which in turn conta ...

Switching back and forth between fluid text fields

Is there a way to navigate between dynamically generated textfields using an iterator from struts-tags? <s:iterator value="aList"> <td width="50px" align="center"> <s:textfield name="solField" size="2" maxlength="1" style="text-transform ...

Error 404: Node.js and Express encountering issues with POST request to '/webhook' endpoint

https://i.sstatic.net/CTDCv.pnghttps://i.sstatic.net/KjPeC.pngI've encountered a peculiar issue where I keep receiving a 404 error specifically when sending a post request to '/webhook'. This error is persistent even though the rest of my po ...

Establish the state as the result of a function

I need to update the state of timeToCountdown with the value stored in allTimeInSeconds. Next, I intend to pass this data as a prop to a component. class Timer extends Component { constructor(props){ super(props); this.state = { ...

Using JavaScript to make an AJAX request when a dropdown menu from

Looking to update a graph created with Google Chart API using a drop-down menu. Currently facing a few issues. The dropdown is sending a request to the wrong URL. Instead of /graph/, it's sending data to the current page, which is /services/. This ...

How to prevent sorting for a certain row in DataTables version 1.9.4

Currently utilizing DataTables version 1.9.4 Here is the table: <table border="0" cellpadding="0" cellspacing="0" class="display" id="example"> <thead> <tr><th>Date</th><th>Discription< ...

Having trouble retrieving data from the PokeAPI

Currently, I am experimenting with PokeAPI for educational purposes and attempting to run the following code: const express = require('express') const https = require('https') const app = express() const port = 3000 app.get('/&apo ...

Incorporate SWFAddress.js into your Flex project for added functionality

Is there a method to set up my Flex 4 project so that it incorporates the JavaScript aspect of the SWFAddress library? I have successfully integrated the AS, but currently, in order to test how it works, I need to open Main.html and include swfaddress.js e ...

Each element is being adorned with the Ajax success function class

Currently, I am in the process of creating an Ajax function to integrate search features into my project. The search function itself is functioning properly; however, within the success: function, I am encountering an issue. Specifically, I am attempting t ...

Is it possible to develop in React without using webpack, relying solely on Gulp instead?

Although I appreciate some aspects of Webpack, my enthusiasm for it wanes as the configuration files grow beyond 15 lines. It becomes overly cryptic, difficult to configure, and time-consuming. Therefore, I tend to reserve its use for just a couple of task ...

Is it possible for JavaScript to access and read a local file from a web page hosted locally

I am interested in using html, css, and javascript to develop a user interface for configuring a simulation. This interface will be used to generate a visualization of the simulation and an output parameters file based on multiple input files. It is impor ...

Tips for navigating through complex JSON structures with JavaScript or JQuery

I'm currently navigating the complexities of parsing a multi-level JSON array as a newcomer to JSON. I am seeking solutions using either JavaScript or jQuery. My goal is to extract the application id, application description, and Product description f ...

The error code 13:5 indicates that the "Home" component has been registered in the Vue application but is not being used, leading to the error message "vue/no-unused-components"

I encountered this issue while working with Vue for the first time. I was attempting to construct a website using Vue/CLI by reorganizing and building from the inside out. However, I am unfamiliar with Vue and unsure how to resolve this error. The changes ...

Node.js function failing to return any value

I am facing an issue with retrieving the value of a function as it is not returning anything. Below is the function I am using (Request is an async function that sends a get request): var getVolumesOKCoin = function(pair){ request('https://www.okc ...

The getter function is called before the v-if directive in the child slot component

I have developed a Vue component that needs to perform certain logic and based on that logic, I want to render the content inside the slot. <logic-component> <div>{{ data }}</div> </logic-component> The data is retrieved using a ...

What is the best way to adjust the placement of ngx-bootstrap datepicker on mobile devices?

Currently, I am facing an issue with two ngx-bootstrap datepickers in my Angular 8 project. When viewed on a mobile device, both datepickers extend beyond the viewport, creating a less than ideal layout. To address this, I need to find a way to center bo ...

AngularJS - using ng-repeat before initializing the scope variable

Currently, I have set up a md-tabs configuration, which is bound to $scope.selectedIndex for the purpose of being able to change it programmatically. The process involves using a button to trigger a function that updates data. Subsequently, I modify $scop ...

Tips for invoking the ajax pagination feature

Although I have successfully displayed the desired data based on the select box, my pagination feature seems to be malfunctioning. Why is that? The index.php display with broken pagination This snippet shows my ajax script for loading data and setting up ...

API requests seem to be failing on the server side, yet they are functioning properly when made through the browser

My current project involves utilizing an API that provides detailed information about countries. I've set up an express server to handle requests to this API, but for some reason it's not making the request. Interestingly, when I directly access ...

How can I trigger a PHP function from within an HTML onClick() event?

While I have come across a response on stackoverflow regarding form submission, my query pertains to a different implementation. I am in need of calling a function that registers a variable in $_SESSION[], and then redirects to another page (html/php). I ...