2016-09-19 65 views
0

我一直在制作一个看似简单的图形。我希望创建一个圈子,用一条连接圆圈的线条,并用一些背景填充圆圈。我几乎已经知道了,但是这一块让我沮丧。在HTML画布上分层和概述

我可以定义画布,创建圆和线连接它们就好:

var canvas = document.getElementById('canvas'); 
var ctx = canvas.getContext('2d'); 
canvas.width = $(window).width(); 
canvas.height = $(window).height(); 

ctx.beginPath(); 
ctx.strokeStyle = "black"; 
ctx.lineWidth = 10; 

//Create two nodes 
ctx.arc(100, 100, 25, 0, 2*Math.PI); 
ctx.moveTo(200+25, 200) 
ctx.arc(200, 200, 25, 0, 2*Math.PI); 

//line connecting two nodes 
ctx.moveTo(100, 100); 
ctx.lineTo(200, 200); 

ctx.stroke(); 

这应该是这样的:

enter image description here

什么话,我要做的就是补(这是为什么我使用clip()),但使用白色填充作为示例还演示了此问题以及:

//simulate filling in nodes with image, in this case solid color 
ctx.clip(); 
ctx.fillStyle = "white"; 
ctx.fill(); 

enter image description here

现在我几乎没有,但也有一些锯齿边缘那里,我已阅读只是在Chrome中的小“错误”的,也是我喜欢的圈子里厚厚的黑色轮廓。所以,我想回到只是两个圈子并概述它们。看来不管我做什么,上下文会永远记住这条线连接两个,我打电话stroke()后结束与连接线在图像的顶部:

//would like to just re-outline circles, not connecting line 
ctx.stokeStyle = "black"; 
ctx.arc(100, 100, 25, 0, 2*Math.PI); 
ctx.moveTo(200+25, 200) 
ctx.arc(200, 200, 25, 0, 2*Math.PI); 
ctx.stroke(); 

enter image description here

我无法弄清楚如何在填充白色背景(加载图像)后再次勾勒出2个圆圈?

我觉得像绘图层一样。首先,我画了一些线,然后我把图像放入,然后再在上面画。不知道HTML画布是否应该这样使用。谢谢。

JSFiddle Example Here

回答

1

你忘了,开始一个新的路径。

每当你开始一个新的形状,你必须使用ctx.beginPath或上下文将重绘所有以前的路径。

顺便说一句,锯齿圆是因为你重新渲染它们,这会导致边缘锯齿。

var canvas = document.createElement("canvas"); 
 
var ctx = canvas.getContext('2d'); 
 
canvas.width = 500; 
 
canvas.height = 500; 
 
document.body.appendChild(canvas); 
 
ctx.setTransform(1,0,0,1,0,-50); // just moving everything up to be seen in snippet. 
 

 
ctx.beginPath(); 
 
ctx.strokeStyle = "black"; 
 
ctx.fillStyle = "#FAFAFF"; 
 
ctx.lineWidth = 10; 
 

 
//Create two nodes 
 
/* dont draw the two circle the first time as you are 
 
    doubling the render causing the edges to get to sharp 
 
    making them appear jaggy. 
 
ctx.arc(100, 100, 25, 0, 2*Math.PI); 
 
ctx.moveTo(200+25, 200) 
 
ctx.arc(200, 200, 25, 0, 2*Math.PI); 
 
*/ 
 
//line connecting two nodes 
 
ctx.moveTo(100, 100); 
 
ctx.lineTo(200, 200); 
 

 
ctx.stroke(); 
 

 
ctx.beginPath(); // start a new path and removes all the previous paths 
 

 
//Create two nodes 
 
ctx.arc(100, 100, 25, 0, 2*Math.PI); 
 
ctx.moveTo(200+25, 200) 
 
ctx.arc(200, 200, 25, 0, 2*Math.PI); 
 
ctx.fill(); 
 

 
ctx.beginPath(); // start a new path and removes all the previous paths 
 

 
//Create two nodes 
 
ctx.arc(100, 100, 25, 0, 2*Math.PI); 
 
ctx.moveTo(200+25, 200) 
 
ctx.arc(200, 200, 25, 0, 2*Math.PI); 
 
ctx.stroke();

+0

就是这样,非常有帮助的感谢!只是一个问题,你是什么意思“重新渲染”。有没有不同的方式来渲染它们,以帮助解决锯齿边缘问题?你的解决方案在这里肯定有效,但我的生产代码异步加载图像,所以做这样的事情由于某种原因不能很好地工作。同样在你的代码中,你并没有使用我需要使用的'clip'来使图像尺寸合适。但无论如何。 –

+1

@jeffery_the_wind重新渲染,我的意思是你正在重绘自己的圈子。 AntiAliasing通过在边缘绘制带有alpha的像素进行工作,当您再次绘制一个形状时,边缘的像素会变得较暗(或者颜色较浅),从而使它们看上去很光滑。您仍然可以使用剪辑,但它具有相同的规则,请使用beginPath来定义剪辑(每次定义唯一路径时使用beginPath)。对于图像,只需等到您在渲染前加载图像即可。 – Blindman67