详解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实例教程 一款纯css3实现的环形导航菜单
Oct 20 HTML / CSS
css3实例教程 一款纯css3实现的发光屏幕旋转特效
Dec 07 HTML / CSS
使用CSS3制作一个简单的进度条(demo)
May 23 HTML / CSS
使用CSS3实现SVG路径描边动画效果入门教程
Oct 21 HTML / CSS
html5中地理位置定位api接口开发应用小结
Jan 04 HTML / CSS
详解HTML5 Canvas绘制不规则图形时的非零环绕原则
Mar 21 HTML / CSS
HTML5 canvas基本绘图之图形变换
Jun 27 HTML / CSS
使用phonegap克隆和删除联系人的实现方法
Mar 31 HTML / CSS
详解移动端Html5页面中1px边框的几种解决方法
Jul 24 HTML / CSS
CSS 实现角标效果的完整代码
Jun 28 HTML / CSS
新的CSS 伪类函数 :is() 和 :where()示例详解
Aug 05 HTML / CSS
HTML 里 img 元素的 src 和 srcset 属性的区别详解
May 21 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
shopex主机报错误请求解决方案(No such file or directory)
2011/12/27 PHP
php用正则表达式匹配中文实例详解
2013/11/06 PHP
php中引用&amp;的用法分析【变量引用,函数引用,对象引用】
2016/12/12 PHP
PHP 计算两个特别大的整数实例代码
2018/05/07 PHP
Ajax+PHP实现的删除数据功能示例
2019/02/12 PHP
javascript控制台详解
2015/06/25 Javascript
jQuery自动添加表单项的方法
2015/07/13 Javascript
js window对象属性和方法相关资料整理
2015/11/11 Javascript
JS+HTML5手机开发之滚动和惯性缓动实现方法分析
2016/06/12 Javascript
angular.js和vue.js中实现函数去抖示例(debounce)
2018/01/18 Javascript
基于vue-element组件实现音乐播放器功能
2018/05/06 Javascript
微信小程序 MinUI组件库系列之badge徽章组件示例
2018/08/20 Javascript
微信小程序中的店铺评分组件及vue中用svg实现的评分显示组件
2018/11/16 Javascript
微信小程序带动画弹窗组件使用方法详解
2018/11/27 Javascript
js防抖和节流的深入讲解
2018/12/06 Javascript
微信小程序在ios下Echarts图表不能滑动的问题解决
2019/07/10 Javascript
Python中分数的相关使用教程
2015/03/30 Python
Windows平台Python连接sqlite3数据库的方法分析
2017/07/12 Python
Python利用itchat对微信中好友数据实现简单分析的方法
2017/11/21 Python
关于python列表增加元素的三种操作方法
2018/08/22 Python
python使用Plotly绘图工具绘制水平条形图
2020/03/25 Python
python中的反斜杠问题深入讲解
2019/08/12 Python
Python爬取数据并实现可视化代码解析
2020/08/12 Python
Python实现自动装机功能案例分析
2020/10/22 Python
Python字符串对齐、删除字符串不需要的内容以及格式化打印字符
2021/01/23 Python
matplotlib部件之矩形选区(RectangleSelector)的实现
2021/02/01 Python
HTML5资源预加载(Link prefetch)详细介绍(给你的网页加速)
2014/05/07 HTML / CSS
【HTML5】Canvas绘制简单图片教程
2016/05/13 HTML / CSS
LEGO玩具英国官方商店:LEGO Shop GB
2018/03/27 全球购物
智能电子秤、手表和健康监测仪:Withings(之前为诺基亚健康)
2018/10/30 全球购物
冰淇淋开店创业计划书
2014/02/01 职场文书
爱国卫生月实施方案
2014/02/21 职场文书
《观潮》教学反思
2016/02/17 职场文书
Python 中的Sympy详细使用
2021/08/07 Python
Oracle 触发器trigger使用案例
2022/02/24 Oracle
《最终幻想14》6.01版本4月5日推出 追加新任务新道具
2022/04/03 其他游戏