本文适合适合对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>>

如何解决

找到问题的原因了,解决方法其实简单。
事情往往就是这样,很多时候,找到问题所在往往比解决问题要难。
解决方案其实很简单

  1. 代码中加入判断,判断浏浏览器是否是FireFox。
  2. 如果是,则先把svg图片绘制到临时的canvas上面。
  3. 后续绘制用临时的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);
        }

欢迎关注公众号“ITman彪叔”。彪叔,拥有10多年开发经验,现任公司系统架构师、技术总监、技术培训师、职业规划师。熟悉Java、JavaScript、Python语言,熟悉数据库。熟悉java、nodejs应用系统架构,大数据高并发、高可用、分布式架构。在计算机图形学、WebGL、前端可视化方面有深入研究。对程序员思维能力训练和培训、程序员职业规划有浓厚兴趣。

ITman彪叔公众号

最新文章

  1. WPF中禁止WebBrowser控件打开新窗口
  2. beanfactory与applicationcontext的区别
  3. OpenCV2学习笔记04:图像的读取与显示
  4. Django路由
  5. 二、Linux文件系统之内存管理
  6. [转]IOS 中文排序
  7. [转]java-Three Rules for Effective Exception Handling
  8. 一、ExtJS下载使用
  9. Eclipse中代码提示框的背景色修改
  10. [论文阅读]Going deeper with convolutions(GoogLeNet)
  11. javascript知识详解之8张思维导图
  12. docker~不使用yml批量部署服务
  13. .net -笔记 简单的操作符重载
  14. How to Build a Chat Bot Using Azure Bot Service and Train It with LUIS
  15. C# Note1:深入浅出WPF-MVVM篇
  16. Git reset与checkout的区别
  17. Java重要类详解之ArrayList类
  18. MySQLCouldn&#39;t find MySQL manager
  19. JAVAEE——宜立方商城11:sso登录注册功能实现、通过token获得用户信息、Ajax跨域请求(jsonp)
  20. delphi webbrowser 常用方法示例

热门文章

  1. Command 传参的几种方式
  2. WPF - Group分组对ListBox等列表样式的约束
  3. WPF控件深拷贝:序列化/反序列化
  4. ES6/ES2015核心内容(转载)
  5. Ionic3开发环境搭建-VS Code
  6. Win10《芒果TV》商店版2016-2017春节大礼,每日前100名用户免费领取7天VIP
  7. 零元学Expression Blend 4 - Chapter 36 来玩捉迷藏吧!!!看看ScrollBar的Disabled与Hidden之差异
  8. .net EF Join 关联表分页查询
  9. 大神为你分析 Go、Java、C 等主流编程语言(Go可以替代Java,而且最小化程序员的工作量,学习比较容易)
  10. 【DRP】-Dao层常用功能代码:增删改查