详解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 11 HTML / CSS
CSS3——齿轮转动关键代码
May 02 HTML / CSS
css3弹性盒模型(Flexbox)详细介绍
Oct 08 HTML / CSS
详解CSS3中强大的filter(滤镜)属性
Jun 29 HTML / CSS
Html5页面在微信端的分享的实现方法
Aug 30 HTML / CSS
关于前端上传文件全面基础扫盲贴(入门)
Aug 01 HTML / CSS
用HTML5制作烟火效果的教程
May 12 HTML / CSS
带你认识HTML5中的WebSocket
May 22 HTML / CSS
详解HTML5如何使用可选样式表为网站或应用添加黑暗模式
Apr 07 HTML / CSS
简单介绍 http请求响应参数、无连接无状态、MIME、状态码、端口、telnet、curl
Mar 31 HTML / CSS
在CSS中使用when/else的方法
Jan 18 HTML / CSS
bootstrapv4轮播图去除两侧阴影及线框的方法
Feb 15 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给文字内容中的关键字进行套红处理
2016/04/12 PHP
laravel5.1框架基础之Blade模板继承简单使用方法分析
2019/09/05 PHP
js对数字的格式化使用说明
2011/01/12 Javascript
jQuery.clean使用方法及思路分析
2013/01/07 Javascript
IE6-8中Date不支持toISOString的修复方法
2014/05/04 Javascript
纯js和css实现渐变色包括静态渐变和动态渐变
2014/05/29 Javascript
如何在MVC应用程序中使用Jquery
2014/11/17 Javascript
3种Jquery限制文本框只能输入数字字母的方法
2014/12/03 Javascript
JS中完美兼容各大浏览器的scrolltop方法
2015/04/17 Javascript
JavaScript面对国际化编程时的一些建议
2015/06/24 Javascript
jQuery实现在最后一个元素之前插入新元素的方法
2015/07/18 Javascript
jQuery+正则+文本框只能输入数字的实现方法
2016/10/07 Javascript
全面解析vue中的数据双向绑定
2017/05/10 Javascript
Bootstrap标签页(Tab)插件切换echarts不显示问题的解决
2018/07/13 Javascript
详解ESLint在Vue中的使用小结
2018/10/15 Javascript
Nodejs实现多文件夹文件同步
2018/10/17 NodeJs
[03:52]DOTA2英雄基础教程 酒仙
2013/12/23 DOTA
Python 实现毫秒级淘宝抢购脚本的示例代码
2019/09/16 Python
python将print输出的信息保留到日志文件中
2019/09/27 Python
Python SSL证书验证问题解决方案
2020/01/13 Python
Pycharm中安装wordcloud等库失败问题及终端通过pip安装的Python库如何添加到Pycharm解释器中(推荐)
2020/05/10 Python
python 服务器运行代码报错ModuleNotFoundError的解决办法
2020/09/16 Python
python 实现客户端与服务端的通信
2020/12/23 Python
web字体加载方案优化小结
2019/11/29 HTML / CSS
Stutterheim瑞典:瑞典高级外套时装品牌
2019/06/24 全球购物
WatchShop法国:英国排名第一的独立手表零售商
2020/02/17 全球购物
应届毕业生求职信
2013/11/30 职场文书
可口可乐广告词
2014/03/20 职场文书
三月学雷锋月活动总结
2014/04/28 职场文书
音乐教育专业自荐信
2014/09/18 职场文书
喝酒驾驶检讨书
2014/10/01 职场文书
学前班幼儿评语大全
2014/12/29 职场文书
保研导师推荐信
2015/03/25 职场文书
催款函范本大全
2015/06/24 职场文书
2015年中秋寄语
2015/07/31 职场文书
老干部局2015年度工作总结
2015/10/22 职场文书