【问题标题】:Best way to make png draggable ignoring transparent area使png可拖动忽略透明区域的最佳方法
【发布时间】:2015-06-12 10:33:02
【问题描述】:

我有一些不规则形状的“png”文件。我需要使它们可拖动,但只有非透明区域才能用作鼠标事件的处理程序。请让我知道实现相同的最佳方法是什么。

我已经尝试过使用“地图”,但可拖动不适用于地图。

【问题讨论】:

  • 请附上您遇到问题的代码。
  • 我非常怀疑你有“不规则形状”的 png 图像......我会打赌它们是矩形的。图像的不透明部分可能是不规则的,但您无法将它们与整体图像分开。图片没有内容。听起来你可能想要 SVG。
  • 这个 png 图像是一个 img-tag(即一个 DOM 元素)还是在画布上绘制的(drawImage();)? (我知道标签说画布,但只是想确定,因为它也说 CSS)

标签: jquery css html canvas


【解决方案1】:

如果你的 png 图像是在画布上绘制的,你可以检查你点击的像素。

假设您点击了 (x,y)

var currentCanvas = ctx.getImageData(x, y, 1, 1);
var pix = currentCanvas.data;

if (pix[3] > 0) { //0 is transparent, 255 is fully visible
    //clicked a non-transparent area and thus it is draggable
}

此解决方案假定背景也是透明的,因此您不能在其后面绘制任何其他内容。

【讨论】:

    【解决方案2】:

    以下是仅当鼠标开始拖动图像的非透明部分时才开始拖动图像的方法:

    • 使用context.getImageData 获取有关图像的像素信息。
    • 创建一个包含图像 alpha 信息的数组
    • 要启动拖动事件,请监听 mousedown 事件并检查 alpha 数组以查看鼠标是否在图像内被按下。如果是,请开始拖动。

    这是带注释的示例代码和演示:

    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(); }
    window.onresize=function(e){ reOffset(); }
    
    var isDown=false;
    var startX,startY;
    
    var hitArray
    var draggables=[];
    
    var testImg=new Image();
    testImg.crossOrigin='anonymous';
    testImg.onload=start;
    testImg.src="https://dl.dropboxusercontent.com/u/139992952/multple/pikachu.png";
    function start(){
    
      draggables.push({
        img:testImg,
        x:50,
        y:50,
        width:testImg.width,
        height:testImg.height,
        hitarray:makeHitArray(testImg),
        isDragging:false,
      });
    
      draggables.push({
        img:testImg,
        x:150,
        y:50,
        width:testImg.width,
        height:testImg.height,
        hitarray:makeHitArray(testImg),
        isDragging:false,
      });
    
      // listen for mouse events
      $("#canvas").mousedown(function(e){handleMouseDown(e);});
      $("#canvas").mousemove(function(e){handleMouseMove(e);});
      $("#canvas").mouseup(function(e){handleMouseUp(e);});
      $("#canvas").mouseout(function(e){handleMouseOut(e);});
    
      drawAll();
    
    }
    
    function drawAll(){
      ctx.clearRect(0,0,cw,ch);
      for(var i=0;i<draggables.length;i++){
        var d=draggables[i];
        ctx.drawImage(d.img,d.x,d.y);
      }
    }
    
    // Draw a target image on a canvas
    // Get the imageData of that canvas
    // Make an array containing the opacity of each pixel on the canvas
    // ( 0==pixel is not part of the object, 1==pixel is part of the object)
    function makeHitArray(img){
      var a=[];
      canvas.width=img.width;
      canvas.height=img.height;
      ctx.drawImage(img,0,0);
      var data=ctx.getImageData(0,0,canvas.width,canvas.height).data;
      for(var i=0;i<data.length;i+=4){
        // if this pixel is mostly opaque push 1 else push 0
        a.push(data[i+3]>250?1:0);
      }
      canvas.width=cw;
      canvas.height=ch;
      return(a);
    }
    
    function hitTest(mx,my,d){
      // return if the mouse is not inside the image bounds
      if(mx<d.x || mx>d.x+d.width || my<d.y || my>d.y+d.height){return;}
      // undo the effects of the image not being at [0,0]
      x=mx-d.x;
      y=my-d.y;
      // calculate which index in the hitarray to test
      index=(y*d.width)+x;
      // test the hitarray
      if(d.hitarray[index]>0){
        // the mouse is over an opaque part of the image
        return(true);
      }else{
        // the mouse is not over an opaque part of the image
        return(false);
      }
    }
    
    function handleMouseDown(e){
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
    
      // get the mouse position
      startX=parseInt(e.clientX-offsetX);
      startY=parseInt(e.clientY-offsetY);
    
      // Set the dragging flags if the mouse was down over 
      // an opaque part of the draggable image
      isDown=false;
      for(var i=0;i<draggables.length;i++){
        var d=draggables[i];
        d.isDragging=hitTest(startX,startY,d);
        if(d.isDragging){
          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();
    
      // get the mouse position
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
    
      // calculate how far the mouse has moved since the last move event
      var dx=mouseX-startX;
      var dy=mouseY-startY;
      startX=mouseX;
      startY=mouseY;
    
      // iterate draggables and move any that are being dragged
      for(var i=0;i<draggables.length;i++){
        var d=draggables[i];
        if(d.isDragging){
          d.x+=dx;
          d.y+=dy;
        }
      }
    
      drawAll();
    
    }
    body{ background-color: ivory; }
    #canvas{border:1px solid red; margin:0 auto; }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <canvas id="canvas" width=300 height=300></canvas>

    【讨论】:

      猜你喜欢
      • 2011-03-22
      • 2011-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 1970-01-01
      • 2014-09-18
      • 2016-01-05
      相关资源
      最近更新 更多