确定绘制到Canvas中的形状/图形的边界

时间:2011-01-07 19:19:38

标签: javascript html5 canvas drawing

我有一个简单的HTML5 Canvas示例,可让用户在画布上绘制路径。有没有办法确定绘制的路径/形状的矩形边界? (即,围绕路径的矩形区域的宽度,高度是多少)。

我意识到我可以在绘制形状的同时进行数学计算,但我想知道是否有更简单/内置的方式。

3 个答案:

答案 0 :(得分:6)

我假设您正在使用LineTo,我能想​​到的唯一方法是在用户绘制路径时保持高度和宽度的最小值/最大值。除此之外,从画布中回退信息​​的唯一方法是使用getImageData,它只会为您提供原始像素信息。

显示此

的快速示例

http://jsfiddle.net/dEnAF/

注意我只是创建了一堆随机点。要记住的主要事情是将最小/最大值设置为用户创建的第一条路径的坐标。

我猜你知道这一点,所以真正的答案是不,不幸的是目前没有内置的方法来做这件事。

答案 1 :(得分:3)

虽然您必须自己跟踪,但我建议将其包装在可重用的功能中。这是一个最小的示例,仅针对moveTolineTo进行跟踪。请参阅此处的实时示例:http://phrogz.net/tmp/canvas_bounding_box.html

function trackBBox( ctx ){
  var begin = ctx.beginPath;
  ctx.beginPath = function(){
    this.minX = this.minY = 99999999999;
    this.maxX = this.maxY = -99999999999;
    return begin.call(this);
  };
  ctx.updateMinMax = function(x,y){
    if (x<this.minX) this.minX = x;
    if (x>this.maxX) this.maxX = x;
    if (y<this.minY) this.minY = y;
    if (y>this.maxY) this.maxY = y;
  };
  var m2 = ctx.moveTo;
  ctx.moveTo = function(x,y){
    this.updateMinMax(x,y);
    return m2.call(this,x,y);
  };
  var l2 = ctx.lineTo
  ctx.lineTo = function(x,y){
    this.updateMinMax(x,y);
    return l2.call(this,x,y);
  };
  ctx.getBBox = function(){
    return {
      minX:this.minX,
      maxX:this.maxX,
      minY:this.minY,
      maxY:this.maxY,
      width:this.maxX-this.minX,
      height:this.maxY-this.minY
    };
  };
}

...

var ctx = myCanvas.getContext("2d");

// Cause the canvas to track its own bounding box for each path
trackBBox(ctx);
ctx.beginPath();
ctx.moveTo(40,40);
for(var i=0; i<10; i++) ctx.lineTo(Math.random()*600,Math.random()*400);

// Find the bounding box of the current path
var bbox = ctx.getBBox();
ctx.strokeRect(bbox.minX,bbox.minY,bbox.width,bbox.height);  

答案 2 :(得分:0)

受到@Phrogz的回答,Calculate bounding box of arbitrary pixel-based drawing的回答以及他的两个演示http://phrogz.net/tmp/canvas_bounding_box.htmlhttp://phrogz.net/tmp/canvas_bounding_box2.html的启发,这是一个不使用Alpha通道的版本(它不起作用以我为例),但只是与白色比较。

function contextBoundingBox(ctx){
    var w=ctx.canvas.width,h=ctx.canvas.height;
    var data = ctx.getImageData(0,0,w,h).data;
    var x,y,minX,minY,maxY,maxY;
    o1: for (y=h;y--;)        for (x=w;x--;)           if ((data[(w*y+x)*4] != 255) && (data[(w*y+x)*4+1] != 255) && (data[(w*y+x)*4+2] != 255)) { maxY=y; break o1 }
    o2: for (x=w;x--;)        for (y=maxY+1;y--;)      if ((data[(w*y+x)*4] != 255) && (data[(w*y+x)*4+1] != 255) && (data[(w*y+x)*4+2] != 255)) { maxX=x; break o2 }
    o3: for (x=0;x<=maxX;++x) for (y=maxY+1;y--;)      if ((data[(w*y+x)*4] != 255) && (data[(w*y+x)*4+1] != 255) && (data[(w*y+x)*4+2] != 255)) { minX=x; break o3 }
    o4: for (y=0;y<=maxY;++y) for (x=minX;x<=maxX;++x) if ((data[(w*y+x)*4] != 255) && (data[(w*y+x)*4+1] != 255) && (data[(w*y+x)*4+2] != 255)) { minY=y; break o4 }
    return {x:minX,y:minY,maxX:maxX,maxY:maxY,w:maxX-minX,h:maxY-minY};
}