Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

235
Vistas
CanvasRenderingContext2D.globalCompositeOperation is not working on safari

I'm not sure if this CanvasRenderingContext2D.globalCompositeOperation is not really working or working in safari, but I've tested it.

I'm working on a Convert Image to Sketch Image feature using Javascript, and this implementation involves CANVAS API or CanvasRenderingContext2D.globalCompositeOperation to be exact.

To explain the flow, I'm generating two images using the image selected, 1 black and white image, and 1 black and white a with blurred image, and then after, that I'm using this merge function to merge/combine them to have Sketch-drew-image. Check this https://codepen.io/ohyeahhu/pen/RwMVjym, if you are using Chrome of course it will work, but if you are using safari browser the Sketch Image will not work.

The script filter function below is how I convert/generate an Image to a black and white and blurred using CanvasRenderingContext2D.filter in CANVAS API.

Now I know that the CanvasRenderingContext2D.filter doesn't have any support from the safari browser but I've solved that part by using https://github.com/davidenke/context-filter-polyfill thanks to this beautiful suggestion https://stackoverflow.com/a/65843002/17678769

const filter = function(img, filter) {
   let canvas = document.createElement('canvas');
   canvas.width = img.width;
   canvas.height = img.height;
   let ctx = canvas.getContext('2d');
   ctx.filter = filter;
   ctx.drawImage(img, 0, 0, img.width, img.height);
   return canvas;
}

The script below is the one I'm using to create a sketch-like-image. Now the ctx.globalCompositeOperation = 'color-dodge'; line of code supposed to make the image like a Sketch-drew-image but somehow in Safari browsers mobile devices or mac, it is not working.

const merge = function(front, overlay) {
   let canvas = document.createElement('canvas');
   canvas.width = front.width;
   canvas.height = front.height;
   let ctx = canvas.getContext('2d');
   ctx.globalCompositeOperation = 'color-dodge';
   ctx.drawImage(front, 0, 0, canvas.width, canvas.height);
   ctx.drawImage(overlay, 0, 0, canvas.width, canvas.height);
   let img = document.createElement('img');
   img.src = canvas.toDataURL();
   return img;
}

I've read the MDN documentation of CanvasRenderingContext2D.globalCompositeOperation and it says that safari browsers fully supports it.

If that's the case, then I do not know where did I go wrong on this implementation, Did I made a mistake in the implementation? I'm really stuck in this for a day, is there any alternative or solution to this issue/problem?

about 4 years ago · Santiago Gelvez
1 Respuestas
Responde la pregunta

0

Yes Safari does support globalCompositeOperation (gCO), they even do have the biggest list of modes they support among all three main browsers (though I found a rendering bug).

The problem lies in your filter polyfill. It probably messed up somewhere when monkeypatching the various methods of the context and broke the gCO (it also broke clearRect).
Seeing how there is no activity on the project I'm not sure you'll be able to have it fixed, but a simple workaround is to let the polyfill know it shouldn't be called on that canvas by setting the __skipFilterPatch property to true on your canvas:

function createCanvas({width, height}) {
  return Object.assign(document.createElement("canvas"), { width, height });
}
function filter(source, filters) {  
  const canvas = createCanvas(source);
  const ctx = canvas.getContext("2d");
  ctx.filter = filters;
  ctx.drawImage(source, 0, 0);
  return canvas;
}
(async() => {
  const blob = await fetch("https://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/20141025_Shockwave_Truck_Alliance_Air_Show_2014-3.jpg/640px-20141025_Shockwave_Truck_Alliance_Air_Show_2014-3.jpg").then(resp => resp.blob());
  const bmp = await createImageBitmap(blob);
  const gray = filter(bmp, "grayscale(1)");
  const blur = filter(bmp, "grayscale(1) invert(1) blur(5px)");
  const canvas = createCanvas(bmp);
  canvas.__skipFilterPatch = true; // the magic
  const ctx = canvas.getContext("2d");
  ctx.drawImage(gray, 0, 0);
  ctx.globalCompositeOperation = "color-dodge";
  ctx.drawImage(blur, 0, 0);
  document.body.append(canvas);
 })().catch(console.error);
  
<script src="https://cdn.jsdelivr.net/npm/context-filter-polyfill@0.2.4/dist/index.js"></script>

about 4 years ago · Santiago Gelvez Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda