详解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 相关文章推荐
CSS中简写属性要注意TRouBLe的顺序问题(避免踩坑)
Mar 09 HTML / CSS
纯CSS3实现图片无间断轮播效果
Aug 25 HTML / CSS
CSS3颜色值RGBA与渐变色使用介绍
Mar 06 HTML / CSS
animation和transition的区别
Oct 12 HTML / CSS
HTML5中使用postMessage实现Ajax跨域请求的方法
Apr 19 HTML / CSS
HTML5实现分享到微信好友朋友圈QQ好友QQ空间微博二维码功能
Jan 03 HTML / CSS
HTML5 Canvas+JS控制电脑或手机上的摄像头实例
May 03 HTML / CSS
html5 冒号分隔符对齐的实现
Jul 31 HTML / CSS
关于iframe跨域使用postMessage的实现
Oct 29 HTML / CSS
CSS 实现多彩、智能的阴影效果
May 12 HTML / CSS
css filter和getUserMedia的联合使用
Feb 24 HTML / CSS
CSS SandBox应用场景及常见问题
Jun 25 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新手上路(四)
2006/10/09 PHP
PHP实现读取一个1G的文件大小
2013/08/24 PHP
Zend Framework教程之Loader以及PluginLoader用法详解
2016/03/09 PHP
利用php输出不同的心形图案
2016/04/22 PHP
ThinkPHP3.2框架自定义配置和加载用法示例
2018/06/14 PHP
PHP pthreads v3下worker和pool的使用方法示例
2020/02/21 PHP
JavaScript设置FieldSet展开与收缩
2009/05/15 Javascript
JS获得图片alt信息的方法
2015/04/01 Javascript
每天一篇javascript学习小结(Array数组)
2015/11/11 Javascript
javascript拖拽应用实例(二)
2016/03/25 Javascript
AngularJS 2.0入门权威指南
2016/10/08 Javascript
微信公众号-获取用户信息(网页授权获取)实现步骤
2016/10/21 Javascript
AngularJS 在同一个界面启动多个ng-app应用模块详解
2016/12/20 Javascript
JavaScript和jQuery制作光棒效果
2017/02/24 Javascript
JavaScript框架Angular和React深度对比
2017/11/20 Javascript
vue this.reload 方法 配置
2018/09/12 Javascript
Vue CLI3搭建的项目中路径相关问题的解决
2018/09/17 Javascript
详解使用element-ui table组件的筛选功能的一个小坑
2018/11/02 Javascript
微信小程序实现的一键连接wifi功能示例
2019/04/24 Javascript
如何测量vue应用运行时的性能
2019/06/21 Javascript
jQuery模仿ToDoList实现简单的待办事项列表
2019/12/30 jQuery
Vue是怎么渲染template内的标签内容的
2020/06/05 Javascript
Pytorch自己加载单通道图片用作数据集训练的实例
2020/01/18 Python
Python多线程threading join和守护线程setDeamon原理详解
2020/03/18 Python
python框架flask入门之环境搭建及开启调试
2020/06/07 Python
解决margin 外边距合并问题
2019/07/03 HTML / CSS
使用Canvas操作像素的方法
2018/06/14 HTML / CSS
JAVA中的关键字有什么特点
2014/03/07 面试题
Delphi笔试题
2016/11/14 面试题
清华大学自主招生自荐信
2014/01/29 职场文书
心理健康课教学反思
2014/02/13 职场文书
开工典礼策划方案
2014/05/23 职场文书
政府班子四风问题整改措施思想汇报
2014/10/08 职场文书
个人工作作风整改措施思想汇报
2014/10/13 职场文书
python中的sys模块和os模块
2022/03/20 Python
MySQL中dd::columns表结构转table过程及应用详解
2022/09/23 MySQL