详解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 中的@keyframes介绍
Sep 02 HTML / CSS
CSS3中的Media Queries学习笔记
May 23 HTML / CSS
纯CSS3实现扇形动画菜单(简化版)实例源码
Jan 17 HTML / CSS
CSS3实现王者荣耀匹配人员加载页面的方法
Apr 16 HTML / CSS
从一次项目重构说起CSS3自定义变量在项目的使用方法
Mar 01 HTML / CSS
html5音频_动力节点Java学院整理
Aug 22 HTML / CSS
HTML5实现锚点时请使用id取代name
Sep 06 HTML / CSS
浅谈Html5中视频 音频标签 进度条的问题
Jul 26 HTML / CSS
H5 meta小结(前端必看篇)
Aug 24 HTML / CSS
H5页面适配iPhoneX(就是那么简单)
Dec 02 HTML / CSS
Html5基于canvas实现电子签名并生成PDF文档
Dec 07 HTML / CSS
HTML中实现音乐或视频自动播放案例详解
May 30 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 has encountered an Access Violation at 7C94BD02解决方法
2009/08/24 PHP
简单PHP会话(session)说明介绍
2016/08/21 PHP
PHP jQuery+Ajax结合写批量删除功能
2017/05/19 PHP
让浏览器非阻塞加载javascript的几种方法小结
2011/04/25 Javascript
js获取 type=radio 值的方法
2014/05/09 Javascript
javascript中数组的多种定义方法和常用函数简介
2014/05/09 Javascript
JS 在指定数组中随机取出N个不重复的数据
2014/06/10 Javascript
jQuery获取标签文本内容和html内容的方法
2015/03/27 Javascript
原生js实现自由拖拽弹窗代码demo
2016/06/29 Javascript
Dropzone.js实现文件拖拽上传功能(附源码下载)
2016/11/22 Javascript
express默认日志组件morgan的方法
2018/04/05 Javascript
jQuery实现table表格信息的展开和缩小功能示例
2018/07/21 jQuery
elementUI中Table表格问题的解决方法
2018/12/04 Javascript
webpack-url-loader 解决项目中图片打包路径问题
2019/02/15 Javascript
VUE实现图片验证码功能
2020/11/18 Javascript
node.js通过Sequelize 连接MySQL的方法
2020/12/28 Javascript
Python 3.6 性能测试框架Locust安装及使用方法(详解)
2017/10/11 Python
hmac模块生成加入了密钥的消息摘要详解
2018/01/11 Python
浅谈python爬虫使用Selenium模拟浏览器行为
2018/02/23 Python
python3 flask实现文件上传功能
2020/03/20 Python
python如何发布自已pip项目的方法步骤
2018/10/09 Python
wxPython多个窗口的基本结构
2019/11/19 Python
10款最佳Python开发工具推荐,每一款都是神器
2020/10/15 Python
美国羽绒床上用品第一品牌:Pacific Coast
2018/08/25 全球购物
亚马逊巴西站:Amazon.com.br
2019/09/22 全球购物
如何用Java实现列出某个目录下的所有子目录
2015/07/20 面试题
会计岗位描述
2014/02/22 职场文书
2014基层党员干部学习全国两会心得体会
2014/03/17 职场文书
表彰大会主持词
2014/03/26 职场文书
大学生简短的自我评价
2014/09/12 职场文书
2014年作风建设剖析材料
2014/10/23 职场文书
单身证明范本
2015/06/15 职场文书
欧元符号 €
2022/02/17 杂记
python turtle绘图
2022/05/04 Python
Go gorilla/sessions库安装使用
2022/08/14 Golang
SQL中去除重复数据的几种方法汇总(窗口函数对数据去重)
2023/05/08 MySQL