简体   繁体   中英

Safari incorrectly drawing shadows on SVGs via HTML5 Canvas

I'm using HTML5 canvas in a project and occasionally need to draw drop shadows on SVGs within a canvas. I've noticed that, compared to Chrome, Safari does two things incorrectly when doing this:

  1. Safari draws a shadow on each individual shape within an SVG
  2. Safari crops off parts of the shadow that go beyond the SVG's bounds

These issues can be illustrated by the following code:

 var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.shadowOffsetX = 10; context.shadowOffsetY = 10; context.shadowColor = 'red' var image = new Image(); image.src = 'https://storage.googleapis.com/card-conjurer/img/manaSymbols/0.svg'; image.onload = function() { context.drawImage(image, 10, 10, 100, 100); }
 <canvas id='canvas'></canvas>

I can't embed images yet, but here are some links to images that illustrate the problem:

(they are screenshots of the code above)

The results from Safari are... quite ugly, as you can see. Is there a way make Safari to render SVGs with shadows on HTML5 canvas like Chrome does?

Any help would be greatly appreciated. Thanks so much for your time!

That's a bug, you should report it to webkit's bug-tracker .

Though you can workaround it by first drawing the image on a second canvas just to rasterize that svg image and use that canvas as source for the shadowing:

 var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); var image = new Image(); image.src = 'https://storage.googleapis.com/card-conjurer/img/manaSymbols/0.svg'; image.onload = function() { const off = canvas.cloneNode(); off.getContext('2d').drawImage(image, 10, 10, 100, 100); context.shadowOffsetX = 10; context.shadowOffsetY = 10; context.shadowColor = 'red'; context.drawImage(off, 0, 0); }
 <canvas id='canvas'></canvas>

In order to use a single canvas, we need to use an offset trick, but it's not always easy to do since it requires knowing clearly the position of our drawing:

 var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); var image = new Image(); image.src = 'https://storage.googleapis.com/card-conjurer/img/manaSymbols/0.svg'; image.onload = function() { // first pass without shadow context.drawImage(image, 10, 10, 100, 100); // set shadow offsets to the position in page of bottom-right corner context.shadowOffsetX = 10 + 110; context.shadowOffsetY = 10 + 110; context.shadowColor = 'red'; // draw behind context.globalCompositeOperation = "destination-over"; // draw with inverse offset, so that the image is not visible // but the shadow is in-screen context.drawImage(canvas, -110, -110); }
 <canvas id='canvas'></canvas>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM