如何知道用户绘制的内容是否涵盖了大部分画布区域?

时间:2015-04-02 10:41:07

标签: javascript jquery html5 canvas

我有一个画布,用户可以在其中写东西,并显示以前保存的图纸。但是由于某些因素,我们检测到其中一些没有使用总画布区域。所以我的问题是:

  • 我可以检测用户绘制的区域并将其缩小 粉碎了usused帆布空间?
  • 或者,我可以检测用户是否 是使用完整的帆布区域还是说超过60%?如是, 怎么样?这样我就可以向用户发出警告。

感谢。

1 个答案:

答案 0 :(得分:2)

  

我可以检测用户绘制的区域并使其变大   粉碎了美国帆布空间?

通过使用短语“撕碎未绘制的空间”,我假设您想要缩放现有图像以填充所有画布区域。

是的,你可以......

<强>步骤#1

您可以使用getImageData从画布中获取像素颜色数据。此数据是一个数组,包含画布上每个像素的红色,绿色,蓝色和Alpha值。

var pixelData=mainContext.getImageData(0,0,mainCanvas.width,mainCanvas.height).data;

画布像素[0,0]的数据:

  • pixelData [0]是画布像素[0,0]的红色组件
  • pixelData [1]是画布像素[0,0]的绿色组件
  • pixelData [2]是画布像素[0,0]的蓝色组件
  • pixelData [3]是画布像素[0,0]的 alpha 组件

画布像素[1,0]的数据:

  • pixelData [4]是画布像素[1,0]
  • 红色组件
  • pixelData [5]是画布像素[1,0]
  • 绿色组件
  • pixelData [6]是画布像素[1,0]
  • 蓝色组件
  • pixelData [7]是画布像素[1,0]
  • alpha 组件

使用像素数据确定用户不透明像素的边界框。您可以通过确定alpha> 250的最顶部,最左侧,最底部和最右侧像素来执行此操作。

var boundLeft,boundTop,boundRight,boundBottom,boundWidth,boundHeight;

function getBounds(){
    boundLeft=1000000;
    boundTop=1000000;
    boundRight=-1000000;
    boundBottom=-1000000;
    //
    var d=ctx.getImageData(0,0,cw,ch).data;
    //
    for(var i=0;i<d.length;i+=4){
        // test the alpha (d[i+3])
        if(d[i+3]>250){
            var px=parseInt(i/4);
            var pixelY=parseInt(px/cw);
            var pixelX=px-pixelY*cw;
            if(pixelX<boundLeft){boundLeft=pixelX;}
            if(pixelX>boundRight){boundRight=pixelX;}
            if(pixelY<boundTop){boundTop=pixelY;}
            if(pixelY>boundBottom){boundBottom=pixelY;}
            boundWidth=boundRight-boundLeft;
            boundHeight=boundBottom-boundTop;
        }
    }
}

<强>步骤#2

创建一个与边界框大小相同的内存中画布。

var memCanvas=document.createElement('canvas');
var memContext=memCanvas.getContext('2d');
memCanvas.width=boundWidth;
memCanvas.height=boundHeight;

<强>步骤#3

使用context.drawImage的剪辑版本将主画布的边界区域绘制到内存中的画布。

memContext.drawImage(mainCanvas,
    // grab the "used" pixels from the main canvas
    boundLeft,boundTop,boundWidth,boundHeight,
    // and draw those pixels on the in-memory canvas
    0,0,boundWidth,boundHeight
);

<强>步骤#4

(可选择将主画布调整为边界框大小)

mainCanvas.width=boundWidth;
mainCanvas.height=boundHeight;

将内存中的画布绘制到主画布上

mainContext.clearRect(0,0,mainCanvas.width,mainCanvas.height);
mainContext.drawImage(memCanvas,0,0);
  

我可以检测用户是使用完整的画布区域还是说   超过60%吗?如果有,怎么样?这样我就可以发出警告了   用户。

是的,你可以......

使用上面相同的技术计算boundWidth&amp; boundHeight

然后,您可以使用边界框大小与画布大小的比率计算“已使用”画布的百分比:

var percent = (boundWidth*boundHeight) / (mainCanvas.width*mainCanvas.height);

在用户添加到绘图时计算新的边界框

在用户绘制每个新像素之后,不是使用getImageData计算新的边界框,而是在新像素超出现有边界时扩展边界框:

if(newPixelX<leftmost){boundLeft=newPixelX;}
if(newPixelX>rightmost){boundRight=newPixelX;}
if(newPixelY<topmost){boundTop=newPixelY;}
if(newPpixelY>bottommost){boundBottom=newPixelY;}

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
  var BB=canvas.getBoundingClientRect();
  offsetX=BB.left;
  offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

var isDown=false;
var startX,startY;

var leftmost,topmost,rightmost,bottommost;

// load image
var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/car.png";
function start(){
  //
  cw=canvas.width=img.width;
  ch=canvas.height=img.height;
  //
  ctx.drawImage(img,0,0);
  //
  getBounds();

}


function getBounds(){
  leftmost=1000000;
  topmost=1000000;
  rightmost=-1000000;
  bottommost=-1000000;
  //
  var d=ctx.getImageData(0,0,cw,ch).data;
  //
  for(var i=0;i<d.length;i+=4){
    // test the alpha (d[i+3])
    if(d[i+3]>250){
      var px=parseInt(i/4);
      var pixelY=parseInt(px/cw);
      var pixelX=px-pixelY*cw;
      if(pixelX<leftmost){leftmost=pixelX;}
      if(pixelX>rightmost){rightmost=pixelX;}
      if(pixelY<topmost){topmost=pixelY;}
      if(pixelY>bottommost){bottommost=pixelY;}
    }
  }
}


function highlightBounds(){
  var previousFill=ctx.fillStyle;
  ctx.globalAlpha=0.05;
  ctx.fillStyle='red';
  ctx.fillRect(leftmost,topmost,(rightmost-leftmost),(bottommost-topmost));
  ctx.globalAlpha=1.00;
  ctx.fillStyle=previousFill;
}


function handleMouseDown(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  startX=parseInt(e.clientX-offsetX);
  startY=parseInt(e.clientY-offsetY);

  // Put your mousedown stuff here
  isDown=true;
}

function handleMouseUp(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  // Put your mouseup stuff here
  isDown=false;
}

function handleMouseOut(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  // Put your mouseOut stuff here
  isDown=false;
}

function handleMouseMove(e){
  if(!isDown){return;}
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);


  ctx.beginPath();
  ctx.arc(mouseX,mouseY,3,0,Math.PI*2);
  ctx.closePath();
  ctx.fill();

  if(mouseX<leftmost){leftmost=mouseX;}
  if(mouseX>rightmost){rightmost=mouseX;}
  if(mouseY<topmost){topmost=mouseY;}
  if(mouseY>bottommost){bottommost=mouseY;}

  var boundsArea=(rightmost-leftmost)*(bottommost-topmost);
  var canvasArea=cw*ch;
  $pct.text(parseInt(boundsArea/canvasArea*100)+'% of canvas area is used');

}

$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUp(e);});
$("#canvas").mouseout(function(e){handleMouseOut(e);});

var $pct=$('#pct');

$('#shred').click(function(){
  var width=rightmost-leftmost;
  var height=bottommost-topmost;
  var memCanvas=document.createElement('canvas');
  var memContext=memCanvas.getContext('2d');
  memCanvas.width=width;
  memCanvas.height=height;
  memContext.drawImage(canvas,
                       // grab the "used" pixels from the main canvas
                       leftmost,topmost,width,height,
                       // and draw those pixels on the in-memory canvas
                       0,0,width,height
                      );
  canvas.width=width;
  canvas.height=height;
  ctx.drawImage(memCanvas,0,0);
});
body{ background-color: white; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=shred>Eliminate outside space</button>
<h4 id=pct>Drag mouse</h4>
<canvas id="canvas" width=300 height=300></canvas>