我有' png'文件有一些不规则的形状。我需要使它们可拖动,但只有非透明区域才能作为鼠标事件的处理程序。请告诉我实现相同的最佳方法。
我已经尝试过使用' map'但是draggable不适用于map。
答案 0 :(得分:2)
如果在画布上绘制了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
}
此解决方案假设背景也是透明的,因此您无法在其后面绘制任何其他内容。
答案 1 :(得分:1)
以下是仅当鼠标开始在图像的非透明部分中拖动时才开始拖动图像的方法:
context.getImageData
获取有关图片的像素信息。这是带注释的示例代码和演示:
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>