经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 软件/图像 » SVG » 查看文章
详解FireFox下Canvas使用图像合成绘制SVG的Bug
来源:jb51  时间:2019/7/11 8:37:17  对本文有异议

本文适合适合对canvas绘制、图形学、前端可视化感兴趣的读者阅读。

楔子

所有的事情都会有一个起因。

最近产品上需要做一个这样的功能:给一些图形进行染色处理。想想这还不是顺手拈来的事情,早就研究过图形染色的技术。于是我把之前写好的两种算法发给了小伙伴,让他参照实现,第一种算法是操纵像素、第二种使用了图像合成:globalCompositeOperation。

所有的事情都可能会有意外,写程序更是如此了。

没多久,小伙伴说,第二种算法在firefox下不起作用。

探索原因

听说有bug,心中一惊。我测试过了的,FireFox下面也测试过的。于是我打开火狐浏览器,启动示例,发现是好的,没有问题。

但是小伙伴集成到产品中就有问题。 差别在哪儿呢? 通过一起排查,最终发现我的示例代码和产品中代码的一个区别是:示例代码用的是png图片,而产品中用的是svg图片。

难道是svg图片的问题,拿一个svg图片放到示例代码中,果然不对。结论已经明显:

FireFox浏览器下,用Canvas下绘制绘制SVG图的时候,globalCompositeOperation的设置将不生效。

下面是一段用于测试的代码,ctx.globalCompositeOperation = 'destination-out' 表示用源图像的形状去挖空目标图像。

在其他浏览器中,以下代码中是生效的,又挖空的效果。但是在

在FireFox 下不生效:

  1. <html>
  2. <head>
  3. <script>
  4. function init() {
  5. var canvas = document.getElementById('c');
  6. var ctx = canvas.getContext('2d');
  7. var img = new Image();
  8. img.onload = function () {
  9. ctx.drawImage(img, 0, 0, img.width * 2, img.height * 2);
  10. ctx.globalCompositeOperation = 'destination-out';
  11. }
  12. img.src = 'diffuse.png';
  13. var svg = new Image;
  14. svg.src = "./d.svg";
  15. function drawPoint(pointX, pointY) {
  16. ctx.drawImage(svg, pointX - svg.width / 4, pointY - svg.height / 4, svg.width / 2, svg.height / 2);
  17. }
  18. canvas.addEventListener('click', function (e) {
  19. drawPoint(e.clientX, e.clientY);
  20. }, false);
  21. }
  22. </script>
  23. </head>
  24. <body onload="init();" style="background: red">
  25. <div>
  26. <canvas id="c" width="1000" height="1000"></canvas>
  27. </div>
  28. </body>
  29. </html>

如何解决

找到问题的原因了,解决方法其实简单。

事情往往就是这样,很多时候,找到问题所在往往比解决问题要难。

解决方案其实很简单

代码中加入判断,判断浏浏览器是否是FireFox。

如果是,则先把svg图片绘制到临时的canvas上面。

后续绘制用临时的canvas替代svg图片。

比如上面代码可以改进如下:

  1. function init() {
  2. var canvas = document.getElementById('c');
  3. var ctx = canvas.getContext('2d');
  4. var img = new Image();
  5. img.onload = function () {
  6. ctx.drawImage(img, 0, 0, img.width * 2, img.height * 2);
  7. ctx.globalCompositeOperation = 'destination-out';
  8. }
  9. img.src = 'diffuse.png';
  10. var svg = new Image;
  11. svg.src = "./d.svg";
  12. var tempCanvas = svg;
  13. if(isFirefox){
  14. svg.onload = function(){
  15. tempCanvas = document.createElement('canvas');
  16. tempCanvas.width = svg.width;
  17. tempCanvas.height = svg.height;
  18. var tempCtx = tempCanvas.getContext('2d');
  19. tempCtx.drawImage(svg,0,0,svg.width,svg.height);
  20. }
  21. }
  22. function drawPoint(pointX, pointY) {
  23. ctx.drawImage(tempCanvas, pointX - svg.width / 4, pointY - svg.height / 4, svg.width / 2, svg.height / 2);
  24. }
  25. canvas.addEventListener('click', function (e) {
  26. drawPoint(e.clientX, e.clientY);
  27. }, false);
  28. }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号