offsetX 事件兼容及冒泡

2012/09/09 domoffsetx

近期项目中需要写一个特效,根据鼠标在当前元素中的位置,利用 mousemove 事件使鼠标在图片左右时改变样式。引出几个问题:offsetX 兼容,targetcurrentTarget,事件冒泡。

# 关于 offsetX 兼容

offsetX: 发生事件的地点在事件源元素的坐标系统中的 x 坐标. 因为 FF 不兼容这个属性,所以我们只得曲线救国了。具体实现代码如下:

// 针对火狐不支持 offsetX/Y
function getOffset (e) {
    var target = e.target, // 当前触发的目标对象
        eventCoord,
        pageCoord,
        offsetCoord;

    // 计算当前触发元素到文档的距离
    pageCoord = getPageCoord(target);

    // 计算光标到文档的距离
    eventCoord = {
        X: window.pageXOffset + e.clientX,
        Y: window.pageYOffset + e.clientY
    };

    // 相减获取光标到第一个定位的父元素的坐标
    offsetCoord = {
        X: eventCoord.X - pageCoord.X,
        Y: eventCoord.Y - pageCoord.Y
    };
    return offsetCoord;
}

function getPageCoord (element) {
    var coord = { X : 0, Y : 0 };
    // 计算从当前触发元素到根节点为止,
    // 各级 offsetParent 元素的 offsetLeft 或 offsetTop 值之和
    while (element) {
        coord.X += element.offsetLeft;
        coord.Y += element.offsetTop;
        element = element.offsetParent;
    }
    return coord;
}

# target 和 currentTarget

  • target: 返回触发事件的元素
  • currentTarget: 返回其事件监听器触发该事件的元素

所以我们可以通过比较 event.targetthis 来确定事件是不是由于冒泡而触发的。

# 关于事件冒泡

我用一个 div 包住 img, 然后在 div 上触发 mousemove 事件,当鼠标移至 img 上时 event.target 指向 img, 也就是说 div 的子元素同样触发了 mousemove 事件(PS:这和不久前碰到的 IE 下子元素触发 mouseover, mouseout 事件如出一辙。当时的解决方案是改用 mouseenter, mouseleave 或者 setTimeout, clearTimeout 控制)。回到 mousemove, 来看看我的解决方案:

$('.wrap_1').mousemove(function (evt) {
    var me = $(this),
        // 根据触发事件元素调整 width
        width = $(evt.target).width(),
        posX = (evt.offsetX == undefined) ? getOffset(evt).offsetX : evt.offsetX;

    if ( posX < width/2 ) {
        me.removeClass("imgNext");
        me.addClass("imgPrev");
    } else {
        me.removeClass("imgPrev");
        me.addClass("imgNext");
    }
});
上次更新: 2024/4/15 02:28:03