本文适合适合对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);
}
欢迎关注公众号“ITman彪叔”。彪叔,拥有10多年开发经验,现任公司系统架构师、技术总监、技术培训师、职业规划师。熟悉Java、JavaScript、Python语言,熟悉数据库。熟悉java、nodejs应用系统架构,大数据高并发、高可用、分布式架构。在计算机图形学、WebGL、前端可视化方面有深入研究。对程序员思维能力训练和培训、程序员职业规划有浓厚兴趣。
ITman彪叔公众号
相关推荐
于是我把之前写好的两种算法发给了小伙伴,让他参照实现,第一种算法是操纵像素、第二种使用了图像合成:globalCompositeOperation。 所有的事情都可能会有意外,写程序更是如此了。 没多久,小伙伴说,第二种算法在...
使用js+canvas绘图,结合svg图形,实现标尺栏和网格效果。
html2canvas可以截图指定dom元素,但是dom元素中如果含有svg会导致截图不完整,例如使用jsPlumb流程图,其中连线无法截图,所以结合了canvg可以完整截图
该库使用JavaScript将Canvas转换为SVG。 换句话说,该库使您可以使用canvas api构建SVG文档。 为什么要使用它? 您有一个要作为SVG文件保留的画布图形。 您喜欢导出内容。 因为您不想将自定义文件格式转换为SVG...
使用Canvas类绘制android机器人
使用canvas绘制钟表 使用canvas绘制钟表 使用canvas绘制钟表
##根据wx.createSelectorQuery()获取wxml的'color','font-size','font-weight','font-family','backgroundColor','border','border-...##wx.createCanvasContext绘制海报,而不是canvas2d绘制海报,海报高度没限制
canvas 合成 文字 图片 很简单的一个入门demo
Canvas饼状图、绘制文字、绘制图像
svg转img所需 html2canvas方法,svg转canvas所需canvg方法 svg转img所需 html2canvas方法,svg转canvas所需canvg方法
Canvas详解及代码绘制安卓机器人
基于canvas的鼠标绘制矩形框的demo,多个canvas对象下支持选中,平移,删除操作,代码用VUE实现的
网页热力图绘制,绘制在canvas上的 heatmap.js,包含源码和插件示例等。
canvas绘制音频波形demo
酷炫的svg与canvas结合动画
Canvas画布图片文字拼接合成,生成图片,输入内容,填写到图片上
ECG html canvas绘制心电图
使用canvas 鼠标事件绘制多边形,鼠标按下事件,移动事件绘制,双击事件结束绘制。原生js,使用添加事件监听,移除事件监听方法来进行绘制开始和结束。简单小demo
svg转为canvas
canvas绘制动态心电图,和监护仪上的一样,可参考使用!