<img src="circle.png" onclick="alert('clicked')"/>
让我们假设circle.png是一个400x400像素的透明背景图像,中间有一个圆圈。
我现在得到的是整个图像区域(400x400px)是可点击的。我想要的是只有圆圈(非透明像素)可以点击。
当然我知道在这个例子中我可以使用<map>
标签和圆形区域,但我正在寻找一种通用的解决方案,它将考虑实际的图像透明度并适用于任何类型的图像(即非规则形状)。
我能看到的最复杂的方法是根据每个像素alpha跟踪图像的轮廓,转换为路径(可能是简化)并应用为地图。
有更有效/直接的方法吗?
答案 0 :(得分:17)
使用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];
第一个位抓取canvas元素,然后创建一个Image
对象。加载图像时,它将在画布上绘制。很简单!除了......如果图像与代码不在同一个域中,您就会遇到相同的域策略安全性。为了获取图像的数据,我们需要将图像本地托管。您还可以对图像进行base64编码,这超出了本答案的范围。 (有关可以使用的工具,请参阅this url。)
接下来,将您的点击事件附加到画布上。当点击进入时,我们将检查透明度并仅针对非透明点击区域:
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;
};
首先,我们做一些跳舞来获得所讨论元素的精确位置。我们将使用该信息传递给canvas元素。 getImageData
除其他外,还会为我们提供一个data
对象,其中包含我们指定位置的RGBA。
如果所有这些值都是0,那么我们正在考虑透明度。如果没有,会出现一些颜色。 -edit-如评论中所述,我们真正需要关注的唯一值是上一个示例中的最后一个imgdata[3]
。值为r(0)g(1)b(2)a(3),透明度由a,α确定。您可以使用相同的方法在任何您知道rgba数据的不透明度中查找任何颜色。
在此处试试:http://jsfiddle.net/pJ3MD/1/
(注意:在我的示例中,由于我提到的域安全性,我使用了base64编码的图像。您可以忽略该部分代码,除非您还打算使用base64编码)< / p>
同样的例子,对鼠标光标进行了更改以获得乐趣:http://jsfiddle.net/pJ3MD/2/
<强>文档强>
Image
对象 - https://developer.mozilla.org/en/DOM/Image canvas
图片的教程 - https://developer.mozilla.org/en/Canvas_tutorial/Using_images canvas
元素(getContext
) - https://developer.mozilla.org/en/DOM/HTMLCanvasElement/ CanvasRenderingContext2D
(getImageData
) - https://developer.mozilla.org/en/DOM/CanvasRenderingContext2D 答案 1 :(得分:4)
您可以使用HTML5画布执行此操作。将图像绘制到画布中,将单击处理程序附加到画布,然后在处理程序中检查单击的像素是否透明。
答案 2 :(得分:1)
谢谢克里斯这个伟大的答案
我在代码中添加了几行来处理缩放画布
所以我现在所做的就是创建一个画布,其中包含图像所具有的精确像素大小。喜欢(对于Image 220px * 120px):
<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;
};