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


Posted in HTML / CSS onJuly 10, 2019

本文适合适合对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);
        }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
深入浅出CSS3 background-clip,background-origin和border-image教程
Jan 27 HTML / CSS
CSS3 实用技巧:实现黑白图像效果示例代码
Jul 11 HTML / CSS
CSS实现限制字数功能当对象内文本溢出时显示省略标记
Aug 20 HTML / CSS
CSS3制作缩略图的详细过程
Jul 08 HTML / CSS
CSS3打造磨砂玻璃背景效果
Sep 28 HTML / CSS
Css3新特性应用之视觉效果实例
Dec 12 HTML / CSS
HTML5本地存储之Database Storage应用介绍
Jan 06 HTML / CSS
利用HTML5 Canvas API绘制矩形的超级攻略
Mar 21 HTML / CSS
html5跳转小程序wx-open-launch-weapp踩坑
Dec 02 HTML / CSS
CSS3实现三角形不断放大效果
Apr 13 HTML / CSS
CSS实现背景图片全屏铺满自适应的3种方式
Jul 07 HTML / CSS
新的CSS 伪类函数 :is() 和 :where()示例详解
Aug 05 HTML / CSS
canvas实现有递增动画的环形进度条的实现方法
Jul 10 #HTML / CSS
Html5新增标签与样式及让元素水平垂直居中
Jul 11 #HTML / CSS
解决H5的a标签的download属性下载service上的文件出现跨域问题
Jul 16 #HTML / CSS
html通过canvas转成base64的方法
Jul 18 #HTML / CSS
基于Canvas+Vue的弹幕组件的实现
Jul 23 #HTML / CSS
HTML5 WebGL 实现民航客机飞行监控系统
Jul 25 #HTML / CSS
关于前端上传文件全面基础扫盲贴(入门)
Aug 01 #HTML / CSS
You might like
PHP5+UTF8多文件上传类
2008/10/17 PHP
PHP中的array数组类型分析说明
2010/07/27 PHP
php 判断数组是几维数组
2013/03/20 PHP
PHP图片处理之图片背景、画布操作
2014/11/19 PHP
详解php中 === 的使用
2016/10/24 PHP
Laravel中如何轻松容易的输出完整的SQL语句
2020/07/26 PHP
在每个匹配元素的外部插入新元素的方法
2013/12/20 Javascript
javascript中的undefined和not defined区别示例介绍
2014/02/26 Javascript
JS实现网页标题栏显示当前时间和日期的完整代码
2015/11/02 Javascript
jQuery插件HighCharts绘制的2D堆柱状图效果示例【附demo源码下载】
2017/03/14 Javascript
js实现适配不同的屏幕大小
2017/04/10 Javascript
MUI 上拉刷新/下拉加载功能实例代码
2017/04/13 Javascript
vue的toast弹窗组件实例详解
2018/05/14 Javascript
解决jQuery使用append添加的元素事件无效的问题
2018/08/30 jQuery
jQuery创建折叠式菜单
2019/06/15 jQuery
python单链表实现代码实例
2013/11/21 Python
python 使用get_argument获取url query参数
2017/04/28 Python
TensorFlow利用saver保存和提取参数的实例
2018/07/26 Python
Python count函数使用方法实例解析
2020/03/23 Python
Pytorch 使用 nii数据做输入数据的操作
2020/05/26 Python
Pytorch生成随机数Tensor的方法汇总
2020/09/09 Python
python报错TypeError: ‘NoneType‘ object is not subscriptable的解决方法
2020/11/05 Python
Python基于argparse与ConfigParser库进行入参解析与ini parser
2021/02/02 Python
纯css3实现鼠标经过图片显示描述的动画效果
2014/09/01 HTML / CSS
Myholidays美国:在线旅游网站
2019/08/16 全球购物
意大利奢侈品牌在线精品店:Jole.it
2020/11/23 全球购物
Nike墨西哥官网:Nike MX
2020/08/30 全球购物
采购员岗位职责
2013/11/15 职场文书
乡镇党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
民政局办理协议离婚(范本)
2014/10/25 职场文书
企业2014年度工作总结
2014/12/10 职场文书
优秀校长事迹材料
2014/12/24 职场文书
婚礼答谢礼品
2015/01/20 职场文书
可可西里观后感
2015/06/08 职场文书
反邪教观后感
2015/06/11 职场文书
Python3的进程和线程你了解吗
2022/03/16 Python