详解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制作动态进度条以及附加jQuery百分比数字显示
Dec 13 HTML / CSS
你应该知道的30个css选择器
Mar 19 HTML / CSS
无需JS和jQuery代码实现CSS3鼠标浮动放大图片
Nov 21 HTML / CSS
CSS3 transition 实现通知消息轮播条
Oct 14 HTML / CSS
基于HTML5 Canvas 实现商场监控实例详解
Nov 20 HTML / CSS
一款html5 canvas实现的图片玻璃碎片特效
Sep 11 HTML / CSS
IE9对HTML5中部分属性不支持的原因分析
Oct 15 HTML / CSS
HTML5本地存储和本地数据库实例详解
Sep 05 HTML / CSS
HTML5 manifest离线缓存的示例代码
Aug 08 HTML / CSS
html5写一个BUI折叠菜单插件的实现方法
Sep 11 HTML / CSS
解决html5中的video标签ios系统中无法播放使用的问题
Aug 10 HTML / CSS
深入理解margin塌陷和margin合并的解决方案
Jun 26 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 CURL模拟GET及POST函数代码
2010/04/25 PHP
js限制文本框输入长度两种限制方式(长度、字节数)
2012/12/19 Javascript
jquery对元素拖动排序示例
2014/01/16 Javascript
JQuery控制radio选中和不选中方法总结
2015/04/15 Javascript
jquery插件jquery.dragscale.js实现拖拽改变元素大小的方法(附demo源码下载)
2016/02/25 Javascript
浅析C/C++,Java,PHP,JavaScript,Json数组、对象赋值时最后一个元素后面是否可以带逗号
2016/03/22 Javascript
学习使用jQuery表单验证插件和日历插件
2017/02/13 Javascript
vue使用vue-cli快速创建工程
2017/07/28 Javascript
Angular项目从新建、打包到nginx部署全过程记录
2017/12/09 Javascript
不使用JavaScript实现菜单的打开和关闭效果demo
2018/05/01 Javascript
微信小程序自定义组件实现tabs选项卡功能
2018/07/14 Javascript
javascript中如何判断类型汇总
2019/05/14 Javascript
vue遍历对象中的数组取值示例
2019/11/07 Javascript
[09:13]2014DOTA2国际邀请赛 中国区预选赛coser表演
2014/05/23 DOTA
Python去掉字符串中空格的方法
2014/03/11 Python
python解析中国天气网的天气数据
2014/03/21 Python
Python可变参数函数用法实例
2015/07/07 Python
将Django框架和遗留的Web应用集成的方法
2015/07/24 Python
听歌识曲--用python实现一个音乐检索器的功能
2016/11/15 Python
python交换两个变量的值方法
2019/01/12 Python
python utc datetime转换为时间戳的方法
2019/01/15 Python
Python二叉搜索树与双向链表转换算法示例
2019/03/02 Python
Python multiprocess pool模块报错pickling error问题解决方法分析
2019/03/20 Python
Django 解决distinct无法去除重复数据的问题
2020/05/20 Python
Django项目创建及管理实现流程详解
2020/10/13 Python
HealthElement海外旗舰店:新西兰大卖场
2018/02/23 全球购物
波兰快递服务:Globkurier.pl
2019/11/08 全球购物
投资协议书范本
2014/04/21 职场文书
党日活动总结
2014/05/07 职场文书
护士长2014年终工作总结
2014/11/11 职场文书
2014年村官工作总结
2014/11/24 职场文书
建筑安全员岗位职责
2015/02/15 职场文书
信访工作个人总结
2015/03/03 职场文书
2015迎新晚会开场白
2015/05/29 职场文书
MySQL慢查询的坑
2021/04/28 MySQL
opencv检测动态物体的实现
2021/07/21 Python