You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法为容器所有子元素实现3D旋转hover效果,for循环实现异常

问题根源

这是典型的循环内闭包变量共享问题,具体原因如下:

  • 你用var声明的循环变量i属于函数作用域,整个循环全程只会创建一个i变量,所有绑定的事件回调都共享这同一个i的引用。等循环跑完的时候,i的值已经变成了rotate.length,超出了数组的下标范围,事件触发时读取rotate[i]会返回undefined,自然不会有任何效果。
  • 另外你把事件处理函数定义在循环内部,每次迭代都会重复创建新的函数,属于不必要的性能开销。

修复方案

方案1:替换变量声明(改动最小)

把循环的var i改为let i即可,let是块级作用域声明,每次循环迭代都会生成独立的i绑定到当前块,每个回调拿到的都是对应迭代的独立i值。另外建议直接用this代替rotate[i],事件回调中的this默认指向当前绑定事件的DOM元素,逻辑更稳妥,完全不需要依赖循环变量。
修复后代码:

let rotate = document.getElementsByClassName("group")[0].getElementsByTagName("a");
// 仅把var替换为let即可解决变量共享问题
for (let i=0; i<rotate.length; i++) {
    const height = rotate[i].clientHeight;
    const width = rotate[i].clientWidth;

    rotate[i].addEventListener('mousemove', handleMove)
    function handleMove(e) {
        const xVal = e.layerX;
        const yVal = e.layerY;
        const yRotation = 20 * ((xVal - width / 2) / width);
        const xRotation = -20 * ((yVal - height / 2) / height);
        const string = 'perspective(500px) scale(1.1) rotateX(' + xRotation + 'deg) rotateY(' + yRotation + 'deg)';
        this.style.transform = string;
    }

    rotate[i].addEventListener('mouseout', function() {
        this.style.transform = 'perspective(500px) scale(1) rotateX(0) rotateY(0)'
    })
    rotate[i].addEventListener('mousedown', function() {
        this.style.transform = 'perspective(500px) scale(0.9) rotateX(0) rotateY(0)'
    })
    rotate[i].addEventListener('mouseup', function() {
        this.style.transform = 'perspective(500px) scale(1.1) rotateX(0) rotateY(0)'
    })
}

方案2:用forEach遍历(更易维护)

把DOM集合转成数组后用forEach遍历,天然避免循环变量共享问题,代码可读性更高:

const rotate = Array.from(document.querySelector(".group").getElementsByTagName("a"));
rotate.forEach(el => {
    const height = el.clientHeight;
    const width = el.clientWidth;

    el.addEventListener('mousemove', e => {
        const xVal = e.layerX;
        const yVal = e.layerY;
        const yRotation = 20 * ((xVal - width / 2) / width);
        const xRotation = -20 * ((yVal - height / 2) / height);
        const string = `perspective(500px) scale(1.1) rotateX(${xRotation}deg) rotateY(${yRotation}deg)`;
        el.style.transform = string;
    })

    el.addEventListener('mouseout', () => {
        el.style.transform = 'perspective(500px) scale(1) rotateX(0) rotateY(0)'
    })
    el.addEventListener('mousedown', () => {
        el.style.transform = 'perspective(500px) scale(0.9) rotateX(0) rotateY(0)'
    })
    el.addEventListener('mouseup', () => {
        el.style.transform = 'perspective(500px) scale(1.1) rotateX(0) rotateY(0)'
    })
})

内容的提问来源于stack exchange,提问作者tez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 02:06:03