我显示带有嵌入式SVG的HTML。我想要它来检测鼠标事件,但它不适用于移动设备(Android Jellybean)。它适用于桌面浏览器。
以下是演示页:http://artsyenta.org/misc/ss/j.touchtry1.html。
如果将鼠标拖到圆圈上,则会在名为“j_xxx”的元素中看到鼠标条目的日志。这适用于Firefox和Chrome。
打开你的Android平板电脑(我也在某人的iPhone上试过这个,结果相同)。将手指拖过圆圈即可立即获得一个touchenter事件。没有别的表现。
您可以通过查看页面来源查看整个页面和代码。它不长,最长的部分是SVG定义。重要的部分是:
$(document).ready(function() {
makeSomethingHappen("hello");
});
function makeSomethingHappen(svg) {
placeATop(true);
$('[class^=j_]')
.on("mouseover", function(event) { logAction(event, this); })
.on("mouseout", function(event) { logAction(event, this); })
.on("touchstart", function(event) { logAction(event, this); })
.on("touchend", function(event) { logAction(event, this); })
.on("touchenter", function(event) { logAction(event, this); })
.on("touchleave", function(event) { logAction(event, this); })
.on("touchEnter", function(event) { logAction(event, this); })
.on("touchLeave", function(event) { logAction(event, this); });
}
var cntAct = 0;
function logAction(ev, ele) {
cntAct++;
var logSpan = $('#logTrace');
logSpan.html("" + cntAct + ": " + ev.type + " '" + $(ele).attr("class")
+ "'<br/>" + logSpan.html());
}
以下是SVG的一部分:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
id="jsvg" x="0px" y="0px" width="376.247px" height="364.318px" viewBox="140 110 130 120"
enable-background="new 0 0 376.247 364.318" xml:space="preserve">
<g id="Layer_1">
<path class="j_aa_" opacity="0.75" fill="#FFFFFF" stroke="#0071BC" stroke-width="0.9925" enable-background="new " d="M224.739,6.55l-6.414,23.957c-10.377-2.785-21.304-2.785-31.671,0L180.232,6.55C194.813,2.63,210.155,2.63,224.739,6.55z"/>
[snip]
</g>
</svg>
同样,我在桌面浏览器上检测到鼠标事件,但没有移动浏览器的触摸或鼠标事件。是否缺少技术,或手机缺少什么?它失败了iPhone浏览器,Jellybean上的谷歌浏览器和Firefox移动版。
提前致谢, 杰罗姆。
答案 0 :(得分:11)
经过对普通SVG事件和RaphaelJS事件的大量研究后,我为每个事件提供了可行的解决方案。这是一个RaphaelJS解决方案:
window.onload = function(e) {
document.getElementById("rsr").addEventListener("mousemove",
function(event) {
logAction(event, this, "m");
}, false);
document.getElementById("rsr").addEventListener("touchmove",
function(event) {
if(event.preventDefault) event.preventDefault();
// perhaps event.targetTouches[0]?
logAction(event.changedTouches[0], this, "t");
}, false);
};
代码不是密不透风的,但说明了主要观点。
首先,必须通过addEventHandler()调用注册事件。使用RaphaelJS onmousemove()等,处理程序无法在平板电脑上运行。
其次,对于触摸事件,您需要深入了解触摸列表。我的应用程序只关心单个手指,因此列表的[0]事件就足够了。有许多列表 - touches,targetTouches,changedTouches - 所以选择一个合适的列表。
第三,确定窗口是否需要冒泡事件。如果我调用preventDefault(),我会对触摸更敏感。
我在Google Nexus,iPad 3和iPad Mini上进行了测试。效果很好。
我也有普通SVG的解决方案。它基于这个网站: http://my.opera.com/MacDev_ed/blog/2010/02/01/how-to-get-all-svg-elements-intersected-by-a-given-rectangle
我使用的和他使用的Javascript的不同之处在于,触摸列表需要访问的触摸。 “root”是此示例的svg元素ID。 “logTrace”是一个接收评论的范围。
var root = document.getElementById("root");
var evtt = evt.touches[0];
var rpos = root.createSVGRect();
rpos.x = evtt.clientX;
rpos.y = evtt.clientY;
rpos.width = rpos.height = 1;
var list = root.getIntersectionList(rpos, null);
var maxItemId = list.length <= 0 ? "(no match)" : list[list.length - 1].id;
document.getElementById("logTrace").innerHTML = "screen: (" + evtt.clientX + ", " + evtt.clientY + ") ? uu(" + maxItemId + "): (" + uupos.x.toFixed(0) + "," + uupos.y.toFixed(0) + ")";
我已经在Nexus和iPad上成功测试了这个解决方案。但是,它在iPad Mini上表现不佳 - 为什么两台iPad设备的表现不同?
我还注意到“普通svg”解决方案似乎没有像RaphaelJS版本那样准确。在我的SVG元素的边缘附近,对于普通的svg检测,检测效果不是很好。我一直在使用RaphaelJS获得好成绩。
OTOH,RaphaelJS使用对SVG敏感(填充:无)。普通SVG不关心是否在元素中设置(fill:none)。选择你的毒药。
答案 1 :(得分:1)
我遇到了这个问题,事实证明iPad认为对象的不透明度是其命中测试功能,所以如果你有填充的东西:无,它就不会注册事件。
我成功测试了这种风格的路径:
.st5 {fill:none;fill-opacity:0.01;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.72}
和两个事件处理程序放在包含路径的标记上:
<g ... onclick="top.load(3201);" ontouchend="top.load(3201);" > ...path here with style .st5 </g>
load(id)
函数存储在外部JS文件中。
另一个问题是SVG必须直接放在HTML dom中,而不是作为<embed .../>
引用,后者导致安全异常