<img src="circle.png" onclick="alert('clicked')"/>
让我们想象一下,circle.png 是一个400x400像素的透明背景图片,在中间有一个圆形。
现在,整个图像区域(400x400像素)都是可点击的。我想要的是只有圆形(非透明像素)是可点击的。
当然,我知道在这个例子中我可以使用
<img src="circle.png" onclick="alert('clicked')"/>
canvas
标签,您可以确定给定点下的像素颜色值。您可以使用事件数据来确定坐标,然后检查透明度。最后将图像加载到画布上即可。 var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function(){
ctx.drawImage(img,0,0);
};
img.src = [YOUR_URL_HERE];
首先,获取画布元素,然后创建一个Image
对象。当图像加载完成后,它将被绘制在画布上。这很简单明了!但是......如果图像与代码不在同一域中,则会遇到同一域策略安全问题。为了获取我们的图像数据,我们需要将图像本地托管。您还可以对图像进行Base64编码,但这超出了本回答的范围。(如需了解此项工具,请参见此网址。)
接下来,将点击事件附加到画布。当点击事件发生时,我们将检查透明度并仅对非透明的点击区域进行操作:
if (isTransparentUnderMouse(this, e))
return;
// do whatever you need to do
alert('will do something!');
魔法发生在函数isTransparentUnderMouse
中,它需要两个参数:目标画布元素(在点击处理程序的范围内为this
)和事件数据(例如,在此示例中为e)。现在我们来到了关键部分:
var isTransparentUnderMouse = function (target, evnt) {
var l = 0, t = 0;
if (target.offsetParent) {
var ele = target;
do {
l += ele.offsetLeft;
t += ele.offsetTop;
} while (ele = ele.offsetParent);
}
var x = evnt.page.x - l;
var y = evnt.page.y - t;
var imgdata = target.getContext('2d').getImageData(x, y, 1, 1).data;
if (
imgdata[0] == 0 &&
imgdata[1] == 0 &&
imgdata[2] == 0 &&
imgdata[3] == 0
){
return true;
}
return false;
};
getImageData
将给我们一些内容,其中包括我们指定位置的RGBA。data
对象。imgdata[3]
值。这些值为r(0)g(1)b(2)a(3),透明度由a,alpha决定。您可以使用相同的方法查找任何颜色和任何透明度,只要您知道rgba数据即可。imgdata[3]
,因为那是 alpha 通道,所以你可以使它更简单。 - Chris BakergetImageData()
返回的数组不是普通数组,因此您无法使用join
,但是Array.apply([], imgdata).join('|')
可以工作。 - aron.duby<canvas width="220" height="120" id="mainMenu_item"></canvas>
使用CSS缩放画布:
#mainMenu_item{
width:110px;
}
调整后的isTransparentUnderMouse函数如下:
var isTransparentUnderMouse = function (target, evnt) {
var l = 0, t = 0;
if (target.offsetParent) {
var ele = target;
do {
l += ele.offsetLeft;
t += ele.offsetTop;
} while (ele = ele.offsetParent);
}
var x = evnt.pageX - l;
var y = evnt.pageY - t;
var initialWidth = $(evnt.target).attr('width');
var clientWidth = evnt.target.clientWidth;
x = x * (initialWidth/clientWidth);
var initialHeight = $(evnt.target).attr('height');;
var clientHeight = evnt.target.clientHeight;
y = y * (initialHeight/clientHeight);
var imgdata = target.getContext('2d').getImageData(x, y, 1, 1).data;
if (
imgdata[0] == 0 &&
imgdata[1] == 0 &&
imgdata[2] == 0 &&
imgdata[3] == 0
){
return true;
}
return false;
};