详解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制作倾斜导航条和毛玻璃效果
Sep 12 HTML / CSS
使用CSS3实现圆角,阴影,透明
Dec 23 HTML / CSS
CSS3实现菜单悬停效果
Nov 17 HTML / CSS
html5指南-2.如何操作document metadata
Jan 07 HTML / CSS
html5使用canvas画空心圆与实心圆
Dec 15 HTML / CSS
详解Html5 监听拦截Android返回键方法
Apr 18 HTML / CSS
移动端html5判断是否滚动到底部并且下拉加载
Nov 19 HTML / CSS
html5 制作地图当前定位箭头的方法示例
Jan 10 HTML / CSS
使用placeholder属性设置input文本框的提示信息
Feb 19 HTML / CSS
HTML5拖放API实现自动生成相框功能
Apr 07 HTML / CSS
video下autoplay属性无效的解决方法(添加muted属性)
May 19 HTML / CSS
在CSS中映射鼠标位置并实现通过鼠标移动控制页面元素效果(实例代码)
Apr 22 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
不用数据库的多用户文件自由上传投票系统(3)
2006/10/09 PHP
PHP+Javascript实现在线拍照功能实例
2015/07/18 PHP
[原创]php实现子字符串位置相互对调互换的方法
2016/06/02 PHP
PHP 二级子目录(后台目录)设置二级域名
2017/03/02 PHP
动态调用css文件——jquery的应用
2007/02/20 Javascript
学习面向对象之面向对象的术语
2010/11/30 Javascript
JavaScript在for循环中绑定事件解决事件参数不同的情况
2014/01/20 Javascript
详解JavaScript中shift()方法的使用
2015/06/09 Javascript
深入解读JavaScript中的Iterator和for-of循环
2015/07/28 Javascript
js+CSS实现模拟华丽的select控件下拉菜单效果
2015/09/01 Javascript
jquery判断当前浏览器的实现代码
2015/11/07 Javascript
jquery实现简单的全选和反选功能
2016/01/02 Javascript
jQuery实现每隔几条元素增加1条线的方法
2016/06/27 Javascript
浅谈jquery之on()绑定事件和off()解除绑定事件
2016/10/26 Javascript
nodejs接入阿里大鱼短信验证码的方法
2017/07/10 NodeJs
Vue2.x中利用@font-size引入字体图标报错的解决方法
2018/09/28 Javascript
JavaScript之Blob对象类型的具体使用方法
2019/11/29 Javascript
JavaScript实现拖拽和缩放效果
2020/08/24 Javascript
[55:44]完美世界DOTA2联赛决赛 FTD vs Phoenix 第二场 11.08
2020/11/11 DOTA
Flask框架配置与调试操作示例
2018/07/23 Python
[原创]Python入门教程5. 字典基本操作【定义、运算、常用函数】
2018/11/01 Python
Python流行ORM框架sqlalchemy安装与使用教程
2019/06/04 Python
Python tkinter 下拉日历控件代码
2020/03/04 Python
python如何快速生成时间戳
2020/07/21 Python
送给他或她的礼物:FUN.com
2018/08/17 全球购物
英国行业制服供应商:Alexandra
2019/09/14 全球购物
2014年学习雷锋活动总结
2014/03/01 职场文书
运动会开幕式主持词
2014/03/28 职场文书
教师三严三实心得体会
2014/10/11 职场文书
小学优秀教师事迹材料
2014/12/16 职场文书
检讨书范文
2015/01/27 职场文书
荆州古城导游词
2015/02/06 职场文书
2015年酒店服务员工作总结
2015/05/18 职场文书
http通过StreamingHttpResponse完成连续的数据传输长链接方式
2022/02/12 Python
Java实现学生管理系统(IO版)
2022/02/24 Java/Android
Android自定义scrollview实现回弹效果
2022/04/01 Java/Android