这其实可以是一个高级话题,或者说不定可以用简单的方法解决。
问题:
假设有 5 或 25 张小图片,用户可以将鼠标移到(鼠标悬停)查看图片的稍微放大版本(或者在某些情况下,图片实际上会变成一个小视频并播放)几秒钟作为预览)。
目前,用户无法单击该图像或视频来跳转到链接。下面有一个单独的按钮,上面写着“Go”以跳转到链接。
程序管理员希望点击图片能让用户跳转到链接。
因此,为了解决这个问题,我可以使用
<a href="... ">. </a>
来包裹这个元素来实现这一点。
然而,在iPad或iPhone,或任何“触摸屏”PC上,用户可能点击它,立即跳转到该链接,而没有机会看到放大的图片或正在播放的小视频
所以 PM(程序经理)不喜欢这种行为,并说:“好吧,只有在桌面情况下才跳转到该链接。”所以PM的意思是,当是iPad或iPhone或触摸屏时,当用户点击那个小图片时,不要跳转到链接。
PM只是希望在PC上“点击”图片可以让用户跳转到链接,但在iPad或iPhone或触摸屏上却会产生不良效果,如上面(5)所述:点击也会跳跃,没有悬停效果看放大的图片或微小的视频预览。
那么问题来了,如何才能让点击跳转只在桌面上起作用,而在iPad、iPhone或触摸屏上不起作用呢?
经过一番思考,我最初的尝试是:当有
mouseenter
事件时,向元素添加一个类,称为 mouse-entered
(并在 mouseleave
事件上,删除该类)。那么,如果元素没有这个 mouse-entered
类,则调用 ev.preventDefault()
来防止跳转到链接。
代码是:
elContent.addEventListener("mouseenter", (ev) => {
console.log("MOUSE_ENTER", ev, new Date());
elContent.classList.add("mouse-entered");
});
elContent.addEventListener("mouseleave", (ev) => {
console.log("MOUSE_LEAVE", ev, new Date());
elContent.classList.remove("mouse-entered");
});
elContent.addEventListener("click", (ev) => {
console.log("CLICK", ev, new Date(), performance.now(), Date.now());
if (!elContent.classList.contains("mouse-entered")) {
ev.preventDefault();
}
});
你可以在codesandbox上尝试一下:
代码已开启: https://codesandbox.io/p/devbox/blissful-hugle-xszzzh
页面位于: https://xszzzh-5000.csb.app/
因此,如果你将其视为网页,或者如果你使用 Google Chrome 的开发工具来模拟 iPhone 或 iPad,如果你点击该块,你仍然会跳转到该链接(我将其设置为跳转到 google.com)。
原因是:在点击时触发
click
事件(在 iPhone 上)之前,也会触发 mousenenter
事件。 因此实际上添加了 mouse-entered
类(并且没有触发 mouseleave
事件来删除该类),因此它不起作用。
我的第二个想法是:如果我加一个类呢,比如
tapped
,有ev.preventDefault()
类的时候用tapped
,这样我就知道是iPhone还是iPad,那就不用跳到了链接。 但是,有些计算机带有触摸屏,所以如果用户点击它,然后使用触控板将鼠标移到上面并单击它,它仍然应该跳转到该链接,所以它也不起作用。
事件的顺序是:
touchstart
touchend
mouseneter
click
所以我不能说,“如果有
touchend
,让它返回到非触摸屏外壳”,因为在 iPhone 或 iPad 上,它也会触发 touchend
事件,就像触摸一样屏幕电脑。
所以我的第三次尝试非常hacky。我只是用
dataset
设置 touchend
时间,这样如果 click
事件在 touchend 时间后小于 0.3 秒或 0.5 秒,那么就不会跳转到链接。目标是说:如果这次点击实际上是点击,那么就不要跳转到链接。 它有效,但确实很hacky。
(
dataset
就像,它会添加一个data-some-name
作为元素的属性)
代码如下:
const elContent = document.querySelector("#content");
console.log("elContent", elContent);
elContent.addEventListener("click", (ev) => {
console.log("CLICK", ev, new Date(), performance.now(), Date.now());
if (
elContent.dataset.touchEndedAt &&
Date.now() - +elContent.dataset.touchEndedAt < 500
) {
ev.preventDefault();
}
});
elContent.addEventListener("touchend", (ev) => {
console.log("TOUCH_END", ev, new Date(), performance.now(), Date.now());
elContent.dataset.touchEndedAt = Date.now();
});
你可以尝试一下。代码是https://codesandbox.io/p/sandbox/jovial-dirac-rm8h7w 该应用程序是https://rm8h7w.csb.app/
因此,如果您使用 Google Chrome 像在 PC 或 Mac 上一样查看页面,则单击该块,它将跳转到链接 (google.com),但如果您使用开发工具模拟 iPhone 并点击它,那么它就不会跳了。
但它非常hacky。 有更好的办法吗?
你把事情搞得太复杂了。只需检测用户是否使用触摸设备并据此调整行为即可。
这是我的建议:
检测设备类型:使用JavaScript判断用户是否是 在触摸设备上。
条件行为:如果是触摸设备,则阻止第一次点击时的默认链接行为,并允许用户看到放大的图像或视频。如果是桌面,让点击立即触发链接。
const elContent = document.querySelector("#content");
let isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
elContent.addEventListener("click", (ev) => {
if (isTouchDevice) {
ev.preventDefault();
// Handle showing the enlarged image or video on touch devices here.
} else {
// Allow the link to work normally on non-touch devices.
window.location.href = ev.currentTarget.dataset.link;
}
});