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

屏幕尺寸变化时无法正确重写全屏滑块的位置数组问题

全屏滑块窗口 resize 后定位异常问题

我正在做一个全屏滑块,正常使用没问题,但调整屏幕尺寸后就出问题了。我试着在 resize 事件里更新定位函数,但没法正确重写 screenPosition 数组。

原实现代码

const container = document.querySelector(".grid-container");
const screens = document.querySelectorAll("#screen");
const screensList = Array.from(screens);
let screenWidth = 0;

// MAYBE ABLE TO USE INSTEAD OF getBoundingClientRect().width
// const observer = new ResizeObserver((entries) => {
//   console.log(entries[0].contentRect.width);
// });

// observer.observe(screensList[0]);

let screenPosition = [];

const setScreenPosition = (screenWidth, currentScreen) => {
  screenPosition.push(screenWidth * currentScreen);
};

const setScreenPositionOnResize = (currentScreen) => {
  screenPosition = [];
  setScreenPosition(screenWidth, currentScreen);
};

const setScreenWidth = () => {
  return (screenWidth = screensList[0].getBoundingClientRect().width);
};
setScreenWidth();

window.addEventListener("resize", () => {
  setScreenWidth();
});

screensList.forEach((scn, i) => {
  const nextBtn = scn.querySelector("#next");
  const backBtn = scn.querySelector("#back");
  const currentScreen = i + 1;
  setScreenPosition(screenWidth, currentScreen);
  window.addEventListener("resize", () => {
    setScreenPositionOnResize(currentScreen);
  });

  const moveFwd = screenPosition[i];
  const moveBk = screenPosition[i - 1] - screenWidth;

  if (nextBtn) {
    nextBtn.addEventListener("click", function () {
      container.style.transform = `translateX(-${moveFwd}px)`;
    });
  }

  if (backBtn) {
    backBtn.addEventListener("click", function () {
      container.style.transform = "translateX(-" + moveBk + "px)";
    });
  }
});

我尝试的重写数组代码

const setScreenPositionOnResize = (currentScreen) => {
  screenPosition = [];
  setScreenPosition(screenWidth, currentScreen);
};

该函数在addEventListener("resize", ...)中被调用。


问题分析与修复方案

核心问题

  1. 重复绑定 resize 事件:在 screensList.forEach 循环里,每个屏幕元素都绑定了一次 resize 事件,窗口 resize 时会触发多次 setScreenPositionOnResize,每次都会清空数组再添加单个元素,最终数组只会保留最后一个屏幕的定位值。
  2. 定位值缓存未更新:moveFwd 和 moveBk 是初始化时获取的固定值,resize 后即使更新了 screenPosition,点击事件仍使用旧值,不会同步新定位。

修复步骤

  1. 统一处理 resize 事件:将 resize 绑定移到循环外,避免重复触发,同时在宽度更新后重新计算所有屏幕的定位。
  2. 点击时动态获取定位:不在初始化时缓存定位值,而是在点击事件内根据最新的屏幕宽度和索引计算目标位置。

修复后的代码

const container = document.querySelector(".grid-container");
const screens = document.querySelectorAll("#screen");
const screensList = Array.from(screens);
let screenWidth = 0;

let screenPosition = [];

// 计算所有屏幕的定位数组
const calculateAllScreenPositions = () => {
  screenPosition = [];
  screensList.forEach((_, i) => {
    screenPosition.push(screenWidth * (i + 1));
  });
};

const setScreenWidth = () => {
  screenWidth = screensList[0].getBoundingClientRect().width;
  calculateAllScreenPositions();
};

// 初始化
setScreenWidth();

// 统一绑定resize事件
window.addEventListener("resize", setScreenWidth);

screensList.forEach((scn, i) => {
  const nextBtn = scn.querySelector("#next");
  const backBtn = scn.querySelector("#back");

  if (nextBtn) {
    nextBtn.addEventListener("click", function () {
      const moveFwd = screenPosition[i];
      container.style.transform = `translateX(-${moveFwd}px)`;
    });
  }

  if (backBtn) {
    backBtn.addEventListener("click", function () {
      // 第一个屏幕回退时定位到0位置
      const moveBk = screenPosition[i - 1] || 0;
      container.style.transform = `translateX(-${moveBk}px)`;
    });
  }
});

额外优化建议

可以用 ResizeObserver 替代 resize 事件,更精准监听容器宽度变化,避免频繁触发:

const observer = new ResizeObserver((entries) => {
  screenWidth = entries[0].contentRect.width;
  calculateAllScreenPositions();
});
observer.observe(screensList[0]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:37:36