如何画周围的任何形状的帆布内部和外部边界?吸取内部和外部边界周围任何帆布形状
我上的HTML画布绘制好几只中风的形状,我想提醒他们周围的内部和外部边界。例如
是否有一个通用的,为什么这样做对任何形状(假设它是一个封闭的只中风型)?
如何画周围的任何形状的帆布内部和外部边界?吸取内部和外部边界周围任何帆布形状
我上的HTML画布绘制好几只中风的形状,我想提醒他们周围的内部和外部边界。例如
是否有一个通用的,为什么这样做对任何形状(假设它是一个封闭的只中风型)?
两种方法
没有内置的方式来做到这一点,有一些我使用两种编程的方式。第一个问题很复杂,涉及扩大和缩小路径,然后沿着这条路径前进。这适用于大多数情况,但在复杂情况下会失败,并且解决方案有很多变数和选项来解决这些复杂问题以及如何处理它们。
两个
,我下面介绍的是使用ctx.globalCompositeOperation
设置屏蔽掉你想绘制或不是第二个最简单的方法就更好了。当笔画沿着中心绘制并且填充填充到中心时,可以以所需宽度的两倍来绘制笔画,然后掩蔽或掩盖内部或外部部分。
当你开始创建非常复杂的图像作为掩蔽(环球综合操作)将与那些已经被吸引干扰这不会成为问题。
为了简化您可以创建第二画布的大小与原来的暂存空间相同的过程。然后,您可以在划伤画布上绘制形状,然后将划过的画布拖到工作区域上。
虽然这种方法是不一样快计算膨胀或收缩的路径,它不会从面临的路径移动点模糊度受到影响。此方法也不会为内部或外部边缘创建具有正确线条连接或斜线的线条,因为您必须使用其他方法。对于大多数目的而言,掩蔽是一个很好的解决方案。
下面是掩模方法的演示来绘制的内部或外部的路径。如果通过在填充中绘制笔画来修改蒙版,则还可以设置偏移量,以便轮廓线或内联线将偏移多个像素。我已经离开了你。 (提示添加描边并在绘制蒙版时将线宽设置为偏移距离的两倍)。
var demo = function(){
/** fullScreenCanvas.js begin **/
var canvas = (function() {
canvas = document.getElementById("canv");
if(canvas !== null){
document.body.removeChild(canvas);
}
// creates a blank image with 2d context
canvas = document.createElement("canvas");
canvas.id = "canv";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
canvas.style.zIndex = 1000;
canvas.ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
return canvas;
})();
var ctx = canvas.ctx;
/** fullScreenCanvas.js end **/
/** CreateImage.js begin **/
// creates a blank image with 2d context
var createImage = function(w,h){
var image = document.createElement("canvas");
image.width = w;
image.height =h;
image.ctx = image.getContext("2d");
return image;
}
/** CreateImage.js end **/
// define a shape for demo
var shape = [0.1,0.1,0.9,0.1,0.5,0.5,0.8,0.9,0.1,0.9];
// draws the shape as a stroke
var strokeShape = function (ctx) {
var w, h, i;
w = canvas.width;
h = canvas.height;
ctx.beginPath();
ctx.moveTo(shape[0] *w, shape[1] *h)
for (i = 2; i < shape.length; i += 2) {
ctx.lineTo(shape[i] * w, shape[i + 1] * h);
}
ctx.closePath();
ctx.stroke();
}
// draws the shape as filled
var fillShape = function (ctx) {
var w, h, i;
w = canvas.width;
h = canvas.height;
ctx.beginPath();
ctx.moveTo(shape[0] * w,shape[1] * h)
for (i = 2; i < shape.length; i += 2) {
ctx.lineTo(shape[i]*w,shape[i+1]*h);
}
ctx.closePath();
ctx.fill();
}
var drawInOutStroke = function(width,style,where){
// clear the workspace
workCtx.ctx.globalCompositeOperation ="source-over";
workCtx.ctx.clearRect(0, 0, workCtx.width, workCtx.height);
// set the width to double
workCtx.ctx.lineWidth = width*2;
workCtx.ctx.strokeStyle = style;
// fill colour does not matter here as its not seen
workCtx.ctx.fillStyle = "white";
// can use any join type
workCtx.ctx.lineJoin = "round";
// draw the shape outline at double width
strokeShape(workCtx.ctx);
// set comp to in.
// in means leave only pixel that are both in the source and destination
if (where.toLowerCase() === "in") {
workCtx.ctx.globalCompositeOperation ="destination-in";
} else {
// out means only pixels on the destination that are not part of the source
workCtx.ctx.globalCompositeOperation ="destination-out";
}
fillShape(workCtx.ctx);
ctx.drawImage(workCtx, 0, 0);
}
// clear in case of resize
ctx.globalCompositeOperation ="source-over";
ctx.clearRect(0,0,canvas.width,canvas.height);
// create the workspace canvas
var workCtx = createImage(canvas.width, canvas.height);
// draw the outer stroke
drawInOutStroke((canvas.width + canvas.height)/45, "black", "out");
// draw the inner stroke
drawInOutStroke((canvas.width + canvas.height)/45, "red", "in");
// draw the shape outline just to highlight the effect
ctx.strokeStyle = "white";
ctx.lineJoin = "round";
ctx.lineWidth = (canvas.width + canvas.height)/140;
strokeShape(ctx);
};
// run the demo
demo();
// incase fullscreen redraw it all
window.addEventListener("resize",demo)