mouseenter与mouseleave在Safari、Edge及IE中失效问题求助
解决
<area>元素鼠标事件在Safari/Edge/IE中失效的问题 嘿,我之前也踩过一模一样的坑!问题根源在于Safari、旧版Edge和IE对<area>元素的mouseenter/mouseleave事件支持非常差——要么完全不触发,要么触发逻辑和Chrome/Firefox完全不一致。下面给你几个靠谱的解决方案:
方案1:用mouseover/mouseout模拟mouseenter/mouseleave
mouseover和mouseout是所有浏览器都原生支持的事件,我们只需要通过判断relatedTarget过滤掉子元素冒泡的情况,就能完美模拟出mouseenter/mouseleave的行为:
var areas = document.getElementsByTagName('area'); for (var i = 0; i < areas.length; i++) { areas[i].addEventListener('mouseover', handleMouseOver); areas[i].addEventListener('mouseout', handleMouseOut); } // 模拟mouseenter逻辑 function handleMouseOver(e) { // 确认鼠标是从元素外部进入(area一般没有子元素,但保留判断更严谨) if (!e.currentTarget.contains(e.relatedTarget)) { console.log('mouseenter'); // 这里替换成你原有的inArea业务逻辑 } } // 模拟mouseleave逻辑 function handleMouseOut(e) { if (!e.currentTarget.contains(e.relatedTarget)) { console.log('mouseleave'); // 这里替换成你原有的outArea业务逻辑 } }
方案2:绑定事件到对应的<img>元素(兼容性最强)
有些极端场景下,连mouseover在<area>上都不生效,这时候可以把鼠标事件绑定到关联的<img>上,通过elementFromPoint判断鼠标位置是否落在某个<area>范围内:
// 获取关联的img元素(需确保img有usemap属性关联map) var mapImg = document.querySelector('img[usemap]'); // 记录当前hover的area,避免重复触发事件 var currentHoverArea = null; mapImg.addEventListener('mousemove', function(e) { // 获取鼠标位置对应的DOM元素 var hoveredElement = document.elementFromPoint(e.clientX, e.clientY); // 判断是否切换了hover的area if (hoveredElement.tagName === 'AREA' && hoveredElement !== currentHoverArea) { // 如果之前有hover的area,先触发leave事件 if (currentHoverArea) { outArea.call(currentHoverArea); } currentHoverArea = hoveredElement; // 触发enter事件,用call让this指向当前area inArea.call(currentHoverArea); } // 鼠标移出所有area的情况 else if (currentHoverArea && hoveredElement.tagName !== 'AREA') { outArea.call(currentHoverArea); currentHoverArea = null; } }); // 保留你原有的事件处理函数 function inArea() { console.log('mouseenter'); } function outArea() { console.log('mouseleave'); }
额外检查项
别忘了确认你的<area>标签属性是否正确:
shape和coords必须匹配(比如rect需要4个数字,circle需要3个,poly需要偶数个坐标对)coords里不能有多余符号,必须是纯数字用逗号分隔- 确保
<img>的usemap属性和<map>的name/id完全对应
为什么会出现这个问题?
早期浏览器对<area>这类特殊元素的事件模型实现不完善,mouseenter/mouseleave是后来才加入的不冒泡事件,旧浏览器根本没实现这个逻辑,而mouseover/mouseout是更早的标准事件,兼容性覆盖更广。
内容的提问来源于stack exchange,提问作者Julie
相关产品推荐
相关产品推荐

