详解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实现质感细腻丝滑按钮
Mar 09 HTML / CSS
CSS3网格的三个新特性详解
Apr 04 HTML / CSS
一款基于css3的列表toggle特效实例教程
Jan 04 HTML / CSS
使用CSS3和Checkbox实现JQuery的一些效果
Aug 03 HTML / CSS
轻松掌握CSS3中的字体大小单位rem的使用方法
May 24 HTML / CSS
谈谈对css属性box-sizing的了解
Jan 04 HTML / CSS
利用CSS3动画实现圆圈由小变大向外扩散的效果实例
Sep 10 HTML / CSS
html Table 表头固定的实现
Jan 22 HTML / CSS
canvas绘制文本内容自动换行的实现代码
Jan 14 HTML / CSS
HTML5样式控制示例代码
Nov 27 HTML / CSS
通过HTML5规范搞定i、em、b、strong元素的区别
Mar 04 HTML / CSS
简单实现一个手持弹幕功能+文字抖动特效
Mar 31 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/03/23 PHP
PHP入门教程之表单与验证实例详解
2016/09/11 PHP
PHP使用gearman进行异步的邮件或短信发送操作详解
2020/02/27 PHP
使用JavaScript获取电池状态的方法
2014/05/03 Javascript
jQuery中:visible选择器用法实例
2014/12/30 Javascript
JavaScript forEach()遍历函数使用及介绍
2015/07/08 Javascript
javascript每日必学之循环
2016/02/19 Javascript
AngularJs bootstrap搭载前台框架——基础页面
2016/09/01 Javascript
etmvc+jQuery EasyUI+combobox多值操作实现角色授权实例
2016/11/09 Javascript
EsLint入门学习教程
2017/02/17 Javascript
Angular4 中常用的指令入门总结
2017/06/12 Javascript
jQuery实现鼠标响应式淘宝动画效果示例
2018/02/13 jQuery
JavaScript实现仿Clock ISO时钟
2018/06/29 Javascript
利用d3.js实现蜂巢图表带动画效果
2019/09/03 Javascript
9种方法优化jQuery代码详解
2020/02/04 jQuery
vue prop传值类型检验方式
2020/07/30 Javascript
Python编程使用*解包和itertools.product()求笛卡尔积的方法
2017/12/18 Python
完美解决在oj中Python的循环输入问题
2018/06/25 Python
对pandas中Series的map函数详解
2018/07/25 Python
对python打乱数据集中X,y标签对的方法详解
2018/12/14 Python
python实现数据分析与建模
2019/07/11 Python
Python HTTP下载文件并显示下载进度条功能的实现
2020/04/02 Python
自定义Django_rest_framework_jwt登陆错误返回的解决
2020/10/18 Python
Luxplus丹麦:香水和个人护理折扣
2018/04/23 全球购物
英国受欢迎的运动鞋和街头服装商店:Footasylum
2018/06/12 全球购物
Janie and Jack美国官网:GAP旗下的高档童装品牌
2019/09/09 全球购物
军训考核自我鉴定
2014/02/13 职场文书
各营销点岗位职责范本
2014/03/05 职场文书
学习决心书
2014/03/11 职场文书
经贸专业毕业生求职信
2014/03/23 职场文书
建设工地安全标语
2014/06/07 职场文书
国博复兴之路观后感
2015/06/02 职场文书
Go 语言结构实例分析
2021/07/04 Golang
Redis高可用集群redis-cluster详解
2022/03/20 Redis
MySQL脏读,幻读和不可重复读
2022/05/11 MySQL
Python如何加载模型并查看网络
2022/07/15 Python