繁体   English   中英

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

[英]Determine bounds of shape / graphics drawn into a Canvas

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

我意识到我可以在绘制形状以找出边界时进行数学计算,但我想看看是否有更简单/内置的方法。

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

显示此内容的快速示例

 var ctx = document.getElementById("canvas").getContext("2d"); var xMin, xMax, yMin, yMax; // These are set to where the path starts, i start them at 10,10 xMin = xMax = 10; yMin = yMax = 10; ctx.beginPath(); ctx.moveTo(10,10); for(var i = 0; i <10; i++){ var x = Math.floor(Math.random()*150), y = Math.floor(Math.random()*150); ctx.lineTo(x,y); if(x < xMin){ xMin = x; } if(x > xMax){ xMax = x; } if(y < yMin){ yMin = y; } if(y > yMax){ yMax = y; } } ctx.strokeStyle = "rgb(0,0,0)"; ctx.stroke(); ctx.closePath(); ctx.strokeStyle = "rgb(255,0,0)"; ctx.strokeRect(xMin,yMin,xMax - xMin,yMax - yMin);
 #canvas{ width: 300px; height: 300px; }
 <canvas id="canvas"></canvas>

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

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

尽管您必须自己跟踪它,但我建议将其包含在可重用的功能中。 这是一个最小的示例,仅针对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);  

灵感来自@Phrogz 的回答,来自计算任意基于像素的绘图的边界框的答案,以及他的两个略有不同的演示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};
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM