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

简介: 本文适合适合对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>>


如何解决


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

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


解决方案其实很简单

  1. 代码中加入判断,判断浏浏览器是否是FireFox。
  2. 如果是,则先把svg图片绘制到临时的canvas上面。
  3. 后续绘制用临时的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);
        }
相关文章
|
Web App开发 移动开发 HTML5
|
Web App开发 数据安全/隐私保护 安全
|
Web App开发 前端开发 测试技术
|
Web App开发 JavaScript 内存技术
flex程序Firefox下中文输入乱码的bug
flex程序Firefox下中文输入乱码的bug   低版本的firefox中无法输入中文,高版本中则出现乱码。 乱码与flash和页面编码方式都没有关系,是firefox的bug造成的。 解决方法只有使用wmode的默认值,但是这样使得flash在整个页面的最上层,div等都会被其遮挡住。
x3d
|
Linux Web App开发
Firefox关于tab的一个bug
开始没意识到这是bug,后来发现不管是linux还是win下都碰到这个问题,才发现,我也找到bug了。 就是这样的:在打开第一个tab后,如果你打开一个新的空的tab,然后再打开一个新的tab后,这些tab就无法关闭了。
x3d
665 0
|
3天前
|
Web App开发 Linux 数据安全/隐私保护
Docker本地部署Firefox火狐浏览器并远程访问
Docker本地部署Firefox火狐浏览器并远程访问
|
3天前
|
Web App开发 Linux 数据安全/隐私保护
Docker本地部署开源浏览器Firefox并远程访问进行测试
Docker本地部署开源浏览器Firefox并远程访问进行测试
165 1
|
9月前
|
数据采集 Web App开发 Python
使用Python爬虫获取Firefox浏览器的用户评价和反馈
使用Python爬虫获取Firefox浏览器的用户评价和反馈
|
9月前
|
Web App开发
应用于Firefox浏览器关于burpsuite的代理问题-详解
应用于Firefox浏览器关于burpsuite的代理问题-详解
124 1
|
10月前
|
数据采集 Web App开发 JavaScript
如何使用Selenium自动化Firefox浏览器进行Javascript内容的多线程和分布式爬取
在本文中,我们将介绍如何使用Selenium自动化Firefox浏览器进行Javascript内容的多线程和分布式爬取。我们将以一个简单的示例为例,抓取百度搜索结果页面中的标题和链接,并将结果保存到本地文件中。我们将使用Python语言编写代码,并使用爬虫代理服务器来隐藏我们的真实IP地址。
105 0
如何使用Selenium自动化Firefox浏览器进行Javascript内容的多线程和分布式爬取