详解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实现的几个小loading效果
Sep 27 HTML / CSS
CSS3属性box-shadow使用详细教程
Jan 21 HTML / CSS
用纯css3实现的图片放大镜特效效果非常不错
Sep 02 HTML / CSS
CSS3只让背景图片旋转180度的实现示例
Mar 09 HTML / CSS
canvas实现飞机打怪兽射击小游戏的示例代码
Jul 09 HTML / CSS
html5适合移动应用开发的12大特性
Mar 19 HTML / CSS
html5读取本地文件示例代码
Apr 22 HTML / CSS
HTML5各种头部meta标签的功能(推荐)
Mar 13 HTML / CSS
canvas 如何绘制线段的实现方法
Jul 12 HTML / CSS
html5视频媒体标签video的使用方法及完整参数说明详解
Sep 27 HTML / CSS
html5实现点击弹出图片功能
Jul 16 HTML / CSS
POST提交数据常见的四种方式
Jan 18 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
兼容性比较好的PHP生成缩略图的代码
2011/01/12 PHP
PHP单元测试框架PHPUnit用法详解
2019/01/23 PHP
Laravel5.1 框架数据库操作DB运行原生SQL的方法分析
2020/01/07 PHP
js 方法实现返回多个数据的代码
2009/04/30 Javascript
Jquery替换已存在于element上的event的方法
2010/03/09 Javascript
JavaScript高级程序设计阅读笔记(六) ECMAScript中的运算符(二)
2012/02/27 Javascript
两个listbox实现选项的添加删除和搜索
2013/03/01 Javascript
根据当前时间在jsp页面上显示上午或下午
2014/08/18 Javascript
jQuery里filter()函数与find()函数用法分析
2015/06/24 Javascript
PageSwitch插件实现100种不同图片切换效果
2015/07/28 Javascript
JS产生随机数的用法小结
2016/12/10 Javascript
使用Javascript判断浏览器终端设备(PC、IOS(iphone)、Android)
2017/01/04 Javascript
Bootstrap Table使用整理(一)
2017/06/09 Javascript
vue+node+webpack环境搭建教程
2017/11/05 Javascript
javascript实现Emrips反质数枚举的示例代码
2017/12/06 Javascript
通过nodejs 服务器读取HTML文件渲染到页面的方法
2018/05/17 NodeJs
如何使用proxy实现一个简单完整的MVVM库的示例代码
2019/09/17 Javascript
[51:39]DOTA2-DPC中国联赛 正赛 Magma vs LBZS BO3 第二场 2月7日
2021/03/11 DOTA
linux系统使用python监测网络接口获取网络的输入输出
2014/01/15 Python
Python使用struct处理二进制的实例详解
2017/09/11 Python
Python numpy 点数组去重的实例
2018/04/18 Python
python3.X 抓取火车票信息【修正版】
2018/06/19 Python
Python使用Flask-SQLAlchemy连接数据库操作示例
2018/08/31 Python
Python多线程应用于自动化测试操作示例
2018/12/06 Python
Python3的unicode编码转换成中文的问题及解决方案
2019/12/10 Python
python 正则表达式参数替换实例详解
2020/01/17 Python
基于python计算滚动方差(标准差)talib和pd.rolling函数差异详解
2020/06/08 Python
利用canvas实现图片下载功能来实现浏览器兼容问题
2019/05/31 HTML / CSS
canvas中普通动效与粒子动效的实现代码示例
2019/01/03 HTML / CSS
芬兰汽车配件商店:Autonvaraosat24
2017/01/30 全球购物
理肤泉美国官网:La Roche-Posay
2018/01/17 全球购物
班主任工作经验材料
2014/02/02 职场文书
初中生思想道德自我评价
2015/03/09 职场文书
刑事上诉状(量刑过重)
2015/05/23 职场文书
详细聊聊vue中组件的props属性
2021/11/02 Vue.js
Python实现仓库管理系统
2022/05/30 Python