首页 > 扩展 > SVG > 正文

详解FireFox下Canvas使用图像合成绘制SVG的Bug

2024-09-06 19:57:12
字体:
来源:转载
供稿:网友

本文适合适合对canvas绘制、图形学、前端可视化感兴趣的读者阅读。

楔子

所有的事情都会有一个起因。

最近产品上需要做一个这样的功能:给一些图形进行染色处理。想想这还不是顺手拈来的事情,早就研究过图形染色的技术。于是我把之前写好的两种算法发给了小伙伴,让他参照实现,第一种算法是操纵像素、第二种使用了图像合成:globalCompositeOperation。

所有的事情都可能会有意外,写程序更是如此了。

没多久,小伙伴说,第二种算法在firefox下不起作用。

探索原因

听说有bug,心中一惊。我测试过了的,FireFox下面也测试过的。于是我打开火狐浏览器,启动示例,发现是好的,没有问题。

但是小伙伴集成到产品中就有问题。 差别在哪儿呢? 通过一起排查,最终发现我的示例代码和产品中代码的一个区别是:示例代码用的是png图片,而产品中用的是svg图片。

难道是svg图片的问题,拿一个svg图片放到示例代码中,果然不对。结论已经明显:

FireFox浏览器下,用Canvas下绘制绘制SVG图的时候,globalCompositeOperation的设置将不生效。

下面是一段用于测试的代码,ctx.globalCompositeOperation = 'destination-out' 表示用源图像的形状去挖空目标图像。

在其他浏览器中,以下代码中是生效的,又挖空的效果。但是在

在FireFox 下不生效:

<html><head>    <script>        function init() {            var canvas = document.getElementById('c');            var ctx = canvas.getContext('2d');            var img = new Image();            img.onload = function () {                ctx.drawImage(img, 0, 0, img.width * 2, img.height * 2);                ctx.globalCompositeOperation = 'destination-out';            }            img.src = 'diffuse.png';            var svg = new Image;            svg.src = "./d.svg";                                function drawPoint(pointX, pointY) {                ctx.drawImage(svg, pointX - svg.width / 4, pointY - svg.height / 4, svg.width / 2, svg.height / 2);            }            canvas.addEventListener('click', function (e) {                drawPoint(e.clientX, e.clientY);            }, false);        }    </script></head><body onload="init();" style="background: red">    <div>        <canvas id="c" width="1000" height="1000"></canvas>    </div></body></html>

如何解决

找到问题的原因了,解决方法其实简单。

事情往往就是这样,很多时候,找到问题所在往往比解决问题要难。

解决方案其实很简单

代码中加入判断,判断浏浏览器是否是FireFox。

如果是,则先把svg图片绘制到临时的canvas上面。

后续绘制用临时的canvas替代svg图片。

比如上面代码可以改进如下:

function init() {            var canvas = document.getElementById('c');            var ctx = canvas.getContext('2d');            var img = new Image();            img.onload = function () {                ctx.drawImage(img, 0, 0, img.width * 2, img.height * 2);                ctx.globalCompositeOperation = 'destination-out';            }            img.src = 'diffuse.png';            var svg = new Image;            svg.src = "./d.svg";                              var tempCanvas = svg;                           if(isFirefox){                             svg.onload = function(){                                  tempCanvas = document.createElement('canvas');                                tempCanvas.width = svg.width;                                tempCanvas.height = svg.height;                                var tempCtx = tempCanvas.getContext('2d');                                tempCtx.drawImage(svg,0,0,svg.width,svg.height);                             }                                    }                                  function drawPoint(pointX, pointY) {                                            ctx.drawImage(tempCanvas, pointX - svg.width / 4, pointY - svg.height / 4, svg.width / 2, svg.height / 2);            }            canvas.addEventListener('click', function (e) {                drawPoint(e.clientX, e.clientY);            }, false);        }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表