No estoy seguro de si este CanvasRenderingContext2D.globalCompositeOperation realmente no funciona o funciona en Safari, pero lo he probado.
Estoy trabajando en una función de conversión de imagen a imagen de boceto usando Javascript, y esta implementación involucra la CANVAS API o CanvasRenderingContext2D.globalCompositeOperation para ser exactos.
Para explicar el flujo, estoy generando dos imágenes usando la imagen seleccionada, 1 imagen en blanco y negro y 1 en blanco y negro con una imagen borrosa, y luego estoy usando esta función de merge para combinarlas para tener Sketch-draw-image. Verifique esto https://codepen.io/ohyeahhu/pen/RwMVjym , si está usando Chrome, por supuesto, funcionará, pero si está usando el navegador Safari, Sketch Image no funcionará.
La siguiente función de filter de script es cómo convierto/genero una imagen en blanco y negro y borrosa usando CanvasRenderingContext2D.filter en CANVAS API.
Ahora sé que CanvasRenderingContext2D.filter no es compatible con el navegador Safari, pero resolví esa parte usando https://github.com/davidenke/context-filter-polyfill gracias a esta hermosa sugerencia 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; } El siguiente script es el que estoy usando para crear una imagen similar a un boceto. Ahora el ctx.globalCompositeOperation = 'color-dodge'; Se supone que la línea de código hace que la imagen sea como una imagen dibujada con Sketch, pero de alguna manera en los navegadores Safari, dispositivos móviles o Mac, no funciona.
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; } He leído la documentación de MDN de CanvasRenderingContext2D.globalCompositeOperation y dice que los navegadores Safari lo admiten por completo.
Si ese es el caso, entonces no sé dónde me equivoqué en esta implementación. ¿Cometí un error en la implementación? Realmente estoy atascado en esto por un día, ¿hay alguna alternativa o solución a este problema?
Sí, Safari es compatible globalCompositeOperation (gCO), incluso tienen la lista más grande de modos que admiten entre los tres navegadores principales (aunque encontré un error de renderizado) .
El problema radica en su filtro polyfill. Probablemente se arruinó en alguna parte cuando monopatinó los diversos métodos del contexto y rompió el gCO ( también rompió clearRect ).
Al ver que no hay actividad en el proyecto, no estoy seguro de que pueda solucionarlo, pero una solución simple es dejar que el polyfill sepa que no debe llamarse en ese lienzo configurando la propiedad __skipFilterPatch en verdadero en tu lienzo:
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>