{"id":10945,"library":"gif.js","title":"gif.js","description":"gif.js is a client-side JavaScript library designed for encoding GIFs directly in the browser. It leverages modern browser APIs like Web Workers and Typed Arrays to perform image processing in the background, aiming for fast performance without blocking the main thread. Despite its original aim for efficiency, the project's last stable version is 0.2.0, released over a decade ago (published in 2016, last commit 2017). This indicates it has a virtually non-existent release cadence and is no longer actively maintained. Its key differentiators at the time were its browser-centric approach with Web Worker offloading, which was a significant performance advantage for client-side GIF generation compared to synchronous methods. It accepts image elements, canvas elements, or canvas contexts as frames. However, newer alternatives often offer better performance via WebAssembly and more modern API designs.","status":"abandoned","version":"0.2.0","language":"javascript","source_language":"en","source_url":"https://github.com/jnordberg/gif.js","tags":["javascript","gif","animation","encoder"],"install":[{"cmd":"npm install gif.js","lang":"bash","label":"npm"},{"cmd":"yarn add gif.js","lang":"bash","label":"yarn"},{"cmd":"pnpm add gif.js","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"gif.js is primarily designed for inclusion via a `<script>` tag, exposing the `GIF` constructor globally. It does not natively support ES module imports.","wrong":"import { GIF } from 'gif.js';","symbol":"GIF","correct":"<!-- In your HTML: -->\n<script src=\"dist/gif.js\"></script>\n\n<script>\n  var gif = new GIF({\n    workers: 2,\n    quality: 10\n  });\n</script>"},{"note":"The library relies on a separate web worker script, `gif.worker.js`, which must be accessible at runtime. By default, it expects it in the same directory as `gif.js`.","symbol":"gif.worker.js","correct":"<!-- Ensure gif.worker.js is in the same directory as gif.js, or specify workerScript option -->\n<script src=\"dist/gif.js\"></script>\n<script>\n  var gif = new GIF({\n    workerScript: '/path/to/gif.worker.js' // If not in same directory\n  });\n</script>"}],"quickstart":{"code":"<html>\n<head>\n  <title>GIF.js Quickstart</title>\n  <script src=\"https://cdn.jsdelivr.net/npm/gif.js@0.2.0/dist/gif.js\"></script>\n</head>\n<body>\n  <canvas id=\"myCanvas\" width=\"200\" height=\"200\"></canvas>\n  <img id=\"myImage\" src=\"https://via.placeholder.com/200x200.png?text=Frame+1\" style=\"display:none;\" alt=\"Frame 1\"/>\n  <button id=\"renderGif\">Render GIF</button>\n\n  <script>\n    const canvas = document.getElementById('myCanvas');\n    const ctx = canvas.getContext('2d');\n    const image1 = document.getElementById('myImage');\n\n    const gif = new GIF({\n      workers: 2,\n      quality: 10,\n      width: 200,\n      height: 200,\n      repeat: 0 // loop forever\n    });\n\n    // Add frame from an image element\n    gif.addFrame(image1, { delay: 500 });\n\n    // Add frame from a canvas element (draw something first)\n    ctx.fillStyle = 'blue';\n    ctx.fillRect(50, 50, 100, 100);\n    gif.addFrame(canvas, { delay: 500 });\n\n    // Add another frame by clearing and drawing something else\n    ctx.clearRect(0, 0, canvas.width, canvas.height);\n    ctx.fillStyle = 'red';\n    ctx.beginPath();\n    ctx.arc(100, 100, 50, 0, Math.PI * 2);\n    ctx.fill();\n    gif.addFrame(ctx, { copy: true, delay: 500 }); // copy: true is important for context\n\n    gif.on('finished', function(blob) {\n      const img = document.createElement('img');\n      img.src = URL.createObjectURL(blob);\n      document.body.appendChild(img);\n      console.log('GIF rendered!');\n    });\n\n    document.getElementById('renderGif').addEventListener('click', () => {\n        console.log('Rendering GIF...');\n        gif.render();\n    });\n\n  </script>\n</body>\n</html>","lang":"javascript","description":"This quickstart demonstrates how to initialize GIF.js, add frames from an image element, a canvas element, and directly from a canvas rendering context. It then renders the GIF and displays it on the page."},"warnings":[{"fix":"Ensure `gif.worker.js` (from the `dist/` folder) is deployed to the same directory as `gif.js` on your web server, or specify its exact URL using the `workerScript` option in the `GIF` constructor: `new GIF({ workerScript: '/path/to/gif.worker.js' })`.","message":"The `gif.worker.js` file is essential for the library to function, as it offloads frame processing to Web Workers. If this file is not found at the expected path, GIF generation will fail silently or with worker-related errors.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"For new projects, consider modern alternatives that are actively maintained and offer better performance, broader browser support, and module compatibility. For existing projects, be aware of potential limitations and lack of security patches.","message":"The project is abandoned, with the last update over a decade ago. It lacks modern features, performance optimizations found in newer libraries (e.g., WebAssembly-based encoders), and security updates. It may not integrate well with modern JavaScript module systems (ESM) and build tools.","severity":"breaking","affected_versions":">=0.2.0"},{"fix":"Verify target browser compatibility for Web Workers, File API, and Typed Arrays. For broader support, consider using a polyfill library or a different GIF encoding solution that targets older browser versions.","message":"gif.js relies on specific browser features: Web Workers, File API, and Typed Arrays. Older browsers or environments that do not fully support these features will prevent the library from working correctly.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Always use `gif.addFrame(ctx, { copy: true, delay: 500 });` when providing a canvas context to ensure a snapshot of the pixel data is taken at the time of `addFrame` call.","message":"When adding a frame directly from a CanvasRenderingContext2D (e.g., `ctx`), the `copy: true` option is crucial. If omitted, the library might try to use a reference to the context's current state, which could lead to unexpected or blank frames if the canvas content changes before the worker processes the frame.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure you have `<script src=\"dist/gif.js\"></script>` in your HTML file, typically before your own scripts that try to use `GIF`. Verify the path to `gif.js` is correct.","cause":"The `gif.js` script was not loaded into the HTML page, or was loaded incorrectly, meaning the global `GIF` constructor is not available.","error":"ReferenceError: GIF is not defined"},{"fix":"Place `gif.worker.js` (from the `dist/` folder of the package) in the same directory as your `gif.js` file, or explicitly configure its path using the `workerScript` option when initializing `GIF`: `new GIF({ workerScript: '/path/to/gif.worker.js' })`.","cause":"The `gif.worker.js` file, which is crucial for the library's functionality, could not be found or loaded by the browser.","error":"Uncaught ReferenceError: GIFWorker is not defined at ... (gif.js:X)"},{"fix":"Ensure all image elements are fully loaded before adding them as frames. If using a canvas context, always add `copy: true` to `addFrame` options: `gif.addFrame(ctx, { copy: true })`. Also, check the `width` and `height` options; if `null`, they are determined by the first frame, which might be an issue if the first frame is invalid or not yet ready.","cause":"This can happen due to various reasons, including incorrect frame data, asynchronous image loading, or not specifying `copy: true` when adding frames from a canvas context that changes.","error":"The image is blank, or frames are incorrect/missing in the output GIF."}],"ecosystem":"npm"}