检测图像透明部分的水龙头

时间:2015-07-06 01:11:55

标签: javascript html css twitter-bootstrap

我目前正在开展一个项目,用户点击不规则形状的图像以放置一个点(想想飞镖或将尾巴钉在驴上)。我在画布上放置点没有问题,但是我遇到了人们在图像外部拍摄(但仍然在图像的边界框上)的问题。有谁知道如何过滤掉图像透明部分的水龙头?enter image description here 这是我的代码:

<style>

#bodyImageFront {
    display:block;
    max-height: 75vh;
    max-width: 90%;
    height:auto;
    width: auto;
    margin-bottom: 10px;
    z-index:1;
    position:absolute;
}

canvas {
    z-index:20;
}

</style>

<script>

var pointMap = [];

$(document).ready(function () {
    drawCanvas();
});

$(window).resize(function () {
    console.log("resize");
    drawCanvas();
    var tempArray = pointMap;
    pointMap = [];
    for (var i = 0; i < tempArray.length; i++) {
        addPointToMap(tempArray[i]);
    }
});

function drawCanvas() {
    if (document.getElementById("bodyMapFrontCanvas")) {
           document.getElementById("bodyMapFrontContainer").removeChild(document.getElementById("bodyMapFrontCanvas"));
    }
    var frontCanvas = document.createElement("canvas");
    frontCanvas.setAttribute("id", "bodyMapFrontCanvas");
    frontCanvas.setAttribute("width", document.getElementById("bodyImageFront").width);
    frontCanvas.setAttribute("height", document.getElementById("bodyImageFront").height);
    frontCanvas.setAttribute("style", "position:relative;");
    frontCanvas.setAttribute("onclick", "addPointToMap(event, 'bodyMapFrontCanvas');");
    document.getElementById('bodyMapFrontContainer').appendChild(frontCanvas);
}

function addPointToMap(point, canvasId) {
    x = point.offsetX ? (point.offsetX) : event.pageX - document.getElementById(canvasId).offsetLeft;
    y = point.offsetY ? (point.offsetY) : event.pageY - document.getElementById(canvasId).offsetTop;
    var context = document.getElementById(canvasId).getContext("2d");
    context.fillRect(x, y, 10, 10);
    pointMap.
}
</script>
<html>
<form id="mainForm">
    <div id="canvasContainer"></div>
    <div class="col-xs-12 col-md-6" id="bodyMapFrontContainer">
        <img src="~/Content/body.png" class="questionInputMethod" id="bodyImageFront" />
    </div>
</form>
</html>

我为糟糕的缩进道歉 提前致谢

1 个答案:

答案 0 :(得分:4)

  • 解决方案1:您的图像复杂,边框透明,不希望透明部分可点击:

    将图像绘制到画布中并使用getImageData(x,y,width,height)检查点击下的像素是否透明。

&#13;
&#13;
var pointMap = [], canvas, ctx, img;

$(document).ready(function () {
  img = $('#bodyImageFront');
  img[0].onload = init;
});


$(window).resize(function () {
    canvas.width = img[0].width;
    canvas.height = img[0].height;
    drawCanvas();
    var tempArray = pointMap;
    pointMap = [];
    for (var i = 0; i < tempArray.length; i++) {
        addPointToMap(tempArray[i]);
    }
});

function init(){
   canvas = document.createElement("canvas");
   canvas.id="bodyMapFrontCanvas";
   canvas.width = img[0].width;
   canvas.height = img[0].height;
   $(canvas).css('position:relative');
   $(canvas).click(addPointToMap);
   ctx = canvas.getContext('2d');
   img.parent().append(canvas);
   img.css('opacity:0');
   drawCanvas();
  }
function drawCanvas() {
  if(!canvas) return;
  ctx.drawImage(img[0], 0,0,canvas.width,canvas.height);
}

function addPointToMap(evt) {
    var target = evt.target,
    x = evt.offsetX ? evt.offsetX : evt.pageX - target.offsetLeft,
    y = evt.offsetY ? evt.offsetY : evt.pageY - target.offsetTop;
    // get the image data of our clicked point  
    var pointData = ctx.getImageData(x,y,1,1).data;
    // if its alpha channel is 0, don't go farther
    if(pointData[3]===0) return;

    ctx.fillRect(x-5, y-5, 10, 10);
    if(evt.type){
      pointMap.push({target: target, offsetX: x, offsetY: y});
      }
}
&#13;
#bodyImageFront {
    display:block;
    max-height: 75vh;
    max-width: 90%;
    height:auto;
    width: auto;
    margin-bottom: 10px;
    z-index:-1;
    position:absolute;
}

canvas {
    z-index:20;
    background:#AAFFAA;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<form id="mainForm">
    <div id="canvasContainer"></div>
    <div id="bodyMapFrontContainer">
        <img src="https://dl.dropboxusercontent.com/s/nqtih1j7vj850ff/c6RvK.png" id="bodyImageFront" crossorigin="Anonymous" />
    </div>
</form>
&#13;
&#13;
&#13;

  • 解决方案2:您真的只想绘制一个简单的形状,就像您给出的示例一样:

    将此形状直接绘制到画布上,并使用isPointInPath()检测是否应激活点击。

&#13;
&#13;
var canvas = document.querySelector('canvas'),
    ctx = canvas.getContext('2d');
function draw(){
  
  var w = canvas.width, h = canvas.height;
  ctx.fillStyle = "#5b9bd5";
  ctx.beginPath();
  var radius = w/3,
      x= canvas.width/2,
      y = radius, a= 11;
  for ( var i = 0; i <= 4 * Math.PI; i += ( 4 * Math.PI ) / 5 ) {
    ctx.lineTo( x + radius * Math.cos(i + a), y + radius * Math.sin(i + a));
  }
  ctx.closePath();
  ctx.fill();
  }

function clickHandler(e){
  var target = e.target,
    x = e.clientX,
    y = e.clientY;
   if(ctx.isPointInPath(e.clientX, e.clientY)){
     ctx.fillStyle="#000";
     ctx.fillRect(x-5,y-5,10,10);
     }
  }
canvas.addEventListener('click', clickHandler, false);
draw();
&#13;
canvas{background:#AAFFAA;}
*{margin:0; overflow: hidden;}
&#13;
<canvas height=500 width=500/>
&#13;
&#13;
&#13;

  • 解决方案3:您再次只想要一个简单的形状,而且您真的不需要<canvas>

    使用 svg 绘制它,并仅将事件侦听器添加到您想要侦听的svg元素。

&#13;
&#13;
document.getElementById('star').addEventListener('click', clickHandler, false);
var svg = document.querySelector('svg');

function clickHandler(e){
   var vB = svg.getBBox(),
       bB = svg.getBoundingClientRect(),
       ratio = {w:(vB.width/bB.width), h:(vB.height/bB.height)};

   var x = e.clientX*ratio.w,
       y = e.clientY*ratio.h;
  
    var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
    rect.setAttribute('x', x);
    rect.setAttribute('y', y);
    rect.setAttribute('width', 10*ratio.w);
    rect.setAttribute('height', 10*ratio.w);
    rect.setAttribute('fill', "#000");
    var parent = e.target.parentNode;
    parent.appendChild(rect);
    
  }
&#13;
*{margin: 0; overflow: hidden;}
svg{
  height: 100vh;
}
&#13;
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
	 viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<rect fill="#AAFFAA" width="100" height="100"/>
<polygon id="star" fill="#29ABE2" points="50,16.5 60.9,40.6 85.2,42.1 65.6,59.3 71.8,83.5 50,70.1 28.2,83.5 34.4,59.3 14.8,42.1 39.1,41.6 
	"/>
</svg>
&#13;
&#13;
&#13;