MediaWiki:PauseWebpExample.js: Difference between revisions

From Heroes 3 wiki
Jump to navigation Jump to search
Created page with "$(function () { const canvas = $('<canvas>', { id: 'pikemanCanvas', width: 64, height: 64, css: { border: '1px solid #ccc', display: 'block', margin: '10px 0' } }).appendTo('#bodyContent')[0]; const ctx = canvas.getContext('2d'); const imageURL = 'https://heroes.thelazy.net/images/f/f1/Pikeman.webp'; // animated WebP const frames = []; let currentFrame = 0; let isPlaying = true; let frameDuration = 100; let lastUpdate = 0; window.tog..."
 
No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 8: Line 8:
   const ctx = canvas.getContext('2d');
   const ctx = canvas.getContext('2d');


   const imageURL = 'https://heroes.thelazy.net/images/f/f1/Pikeman.webp'; // animated WebP
   const imageURL = 'https://heroes.thelazy.net/images/f/f1/Pikeman.webp';
   const frames = [];
   const frames = [];
   let currentFrame = 0;
   let currentFrame = 0;
   let isPlaying = true;
   let lastUpdate = 0;
   let frameDuration = 100;
   let frameDuration = 100;
  let lastUpdate = 0;


   window.togglePikemanAnimation = function () {
   fetch(imageURL)
    isPlaying = !isPlaying;
    .then(response => response.arrayBuffer())
  };
    .then(buffer => {
      const decoder = new VideoDecoder({
        output: function (videoFrame) {
          createImageBitmap(videoFrame).then(bitmap => {
            frames.push(bitmap);
            videoFrame.close();
          });
        },
        error: function (e) {
          console.error('Decoder error:', e);
        }
      });


  $('<button>', {
      decoder.configure({ codec: 'vp8' });
    text: 'Pause/Play',
    click: window.togglePikemanAnimation
  }).appendTo('#bodyContent');


  (async function () {
      const chunk = new EncodedVideoChunk({
    const response = await fetch(imageURL);
        type: 'key',
    const buffer = await response.arrayBuffer();
        timestamp: 0,
        data: new Uint8Array(buffer)
      });


    const decoder = new VideoDecoder({
      decoder.decode(chunk);
      output: handleFrame,
      error: e => console.error('Decoder error:', e)
    });


    decoder.configure({ codec: 'vp8' });
      // Wait until at least one frame is decoded before starting animation
 
      const waitForFrames = function () {
    // Feed the entire buffer as a single chunk
        if (frames.length > 0) {
    const chunk = new EncodedVideoChunk({
          drawFrame(0);
      type: 'key',
          requestAnimationFrame(animate);
      timestamp: 0,
        } else {
      data: new Uint8Array(buffer)
          setTimeout(waitForFrames, 50);
    });
         }
 
       };
    decoder.decode(chunk);
 
    function handleFrame(videoFrame) {
      createImageBitmap(videoFrame).then(bitmap => {
        frames.push(bitmap);
         videoFrame.close();
       });
    }


    // Wait for decoding to finish
      waitForFrames();
    const waitForFrames = () => new Promise(resolve => {
      const check = () => {
        if (frames.length > 0) resolve();
        else setTimeout(check, 50);
      };
      check();
     });
     });
    await waitForFrames();
    drawFrame(0);
    requestAnimationFrame(animate);
  })();


   function drawFrame(index) {
   function drawFrame(index) {
Line 74: Line 61:
     const delta = timestamp - lastUpdate;
     const delta = timestamp - lastUpdate;


     if (isPlaying && delta > frameDuration && frames.length > 0) {
     if (frames.length > 0) {
       currentFrame = (currentFrame + 1) % frames.length;
       const isLastFrame = currentFrame === frames.length - 1;
      drawFrame(currentFrame);
      const delay = isLastFrame ? 1000 : frameDuration;
      lastUpdate = timestamp;
 
      if (delta > delay) {
        currentFrame = (currentFrame + 1) % frames.length;
        drawFrame(currentFrame);
        lastUpdate = timestamp;
      }
     }
     }



Latest revision as of 17:52, 18 October 2025

$(function () {
  const canvas = $('<canvas>', {
    id: 'pikemanCanvas',
    width: 64,
    height: 64,
    css: { border: '1px solid #ccc', display: 'block', margin: '10px 0' }
  }).appendTo('#bodyContent')[0];
  const ctx = canvas.getContext('2d');

  const imageURL = 'https://heroes.thelazy.net/images/f/f1/Pikeman.webp';
  const frames = [];
  let currentFrame = 0;
  let lastUpdate = 0;
  let frameDuration = 100;

  fetch(imageURL)
    .then(response => response.arrayBuffer())
    .then(buffer => {
      const decoder = new VideoDecoder({
        output: function (videoFrame) {
          createImageBitmap(videoFrame).then(bitmap => {
            frames.push(bitmap);
            videoFrame.close();
          });
        },
        error: function (e) {
          console.error('Decoder error:', e);
        }
      });

      decoder.configure({ codec: 'vp8' });

      const chunk = new EncodedVideoChunk({
        type: 'key',
        timestamp: 0,
        data: new Uint8Array(buffer)
      });

      decoder.decode(chunk);

      // Wait until at least one frame is decoded before starting animation
      const waitForFrames = function () {
        if (frames.length > 0) {
          drawFrame(0);
          requestAnimationFrame(animate);
        } else {
          setTimeout(waitForFrames, 50);
        }
      };

      waitForFrames();
    });

  function drawFrame(index) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(frames[index], 0, 0, canvas.width, canvas.height);
  }

  function animate(timestamp) {
    if (!lastUpdate) lastUpdate = timestamp;
    const delta = timestamp - lastUpdate;

    if (frames.length > 0) {
      const isLastFrame = currentFrame === frames.length - 1;
      const delay = isLastFrame ? 1000 : frameDuration;

      if (delta > delay) {
        currentFrame = (currentFrame + 1) % frames.length;
        drawFrame(currentFrame);
        lastUpdate = timestamp;
      }
    }

    requestAnimationFrame(animate);
  }
});