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

Javascript教室元素无法随窗口尺寸自适应调整问题求助

解决教室布局响应式问题及resize事件未触发问题

一、修复resize事件未触发问题

将resize事件监听移至DOMContentLoaded回调内,确保DOM完全加载后再注册事件,避免脚本加载顺序导致的注册失败,同时添加防抖优化避免频繁触发:

document.addEventListener('DOMContentLoaded', function() {
  var buttons = document.querySelectorAll('.floor-btn');
  buttons.forEach(function(button) {
    button.addEventListener('click', function(event) {
      var floorNumber = parseInt(this.getAttribute('data-floor'));
      changeFloor(floorNumber);
    });
  });
  changeFloor(1);

  // 带防抖的resize事件监听
  let resizeTimeout;
  window.addEventListener("resize", function() {
    clearTimeout(resizeTimeout);
    resizeTimeout = setTimeout(() => {
      console.log("Resize Event");
      const activeFloor = document.querySelector('.floor-btn.active').getAttribute('data-floor');
      changeFloor(parseInt(activeFloor));
    }, 200);
  });
});

同时检查浏览器控制台是否存在变量未定义等报错,这类问题会导致脚本中断,进而无法完成事件注册。

二、实现教室位置随窗口动态调整

当前教室使用固定像素定位,窗口变化时无法自适应,需改为基于容器的相对定位方案:

1. 调整容器CSS

给#map添加相对定位,让绝对定位的教室元素以它为基准:

#map {
  position: relative;
  width: 100%;
  height: calc(100% - 80px); /* 预留楼层按钮空间,可根据布局调整 */
  overflow: hidden;
}

2. 修改绘制逻辑,使用相对比例计算位置

假设JSON中的location坐标基于基准宽高(比如1920x1080),动态计算当前容器下的位置:

async function drawCabinets(floor) {
  if (classrooms_ === undefined) {
    console.log("Loading Classroms");
    classrooms_ = await LoadCabinetsData();
  }

  let classrooms = classrooms_[floor - 1];
  const map = document.getElementById('map');
  const tooltip = document.getElementById('tooltip');
  const mapWidth = map.offsetWidth;
  const mapHeight = map.offsetHeight;
  // 替换为你的基准尺寸(JSON坐标对应的原始容器大小)
  const baseWidth = 1920;
  const baseHeight = 1080;

  map.innerHTML = ''; // 简化容器清空逻辑

  if (classrooms !== undefined) {
    classrooms.forEach(function(classroom) {
      const room = document.createElement('div');
      room.className = 'room';
      // 计算相对位置百分比
      const relativeX = (classroom.location[0] / baseWidth) * 100;
      const relativeY = (classroom.location[1] / baseHeight) * 100;
      room.style.left = `${relativeX}%`;
      room.style.top = `${relativeY}%`;
      
      room.style.backgroundColor = getColor(classroom.students, classroom.capacity);
      room.innerText = classroom.cabinet;
      if (classroom.type === 'Компьютерный') room.classList.add('computer-room');
      if (classroom.type === 'Поточный') room.classList.add('stream-room');

      room.addEventListener('mouseover', function() {
        tooltip.innerHTML = `Кабинет №${classroom.cabinet}<br>Тип: ${classroom.type}<br>Вместимость: ${classroom.capacity}<br>Сейчас в кабинете: ${classroom.students} студентов<br>Группы: ${classroom.groups.join(', ')}`;
        // 同步计算tooltip的动态位置
        const tooltipX = (classroom.location[0] / baseWidth) * mapWidth + 40;
        const tooltipY = (classroom.location[1] / baseHeight) * mapHeight - 20;
        tooltip.style.left = `${tooltipX}px`;
        tooltip.style.top = `${tooltipY}px`;
        tooltip.style.display = 'block';
      });
      room.addEventListener('mouseout', function() {
        tooltip.style.display = 'none';
      });
      map.appendChild(room);
    });
  }

  function getColor(students, capacity) {
    const percentage = (students / capacity) * 100;
    if (percentage < 25) return 'green';
    if (percentage < 50) return 'lightgreen';
    if (percentage < 75) return 'yellow';
    if (percentage < 90) return 'orange';
    return 'red';
  }
}

3. 简化changeFloor函数

function changeFloor(floorNumber) {
  const buttons = document.querySelectorAll('.floor-btn');
  buttons.forEach(btn => btn.classList.remove('active'));
  const activeBtn = document.querySelector(`.floor-btn[data-floor="${floorNumber}"]`);
  activeBtn.classList.add('active');

  const map = document.getElementById('map');
  map.innerHTML = '';
  drawCabinets(floorNumber);
}

额外说明

  • 如果JSON中的坐标本身就是百分比值,可直接省略基准尺寸计算,直接使用classroom.location[0] + '%'作为位置值。
  • 移动端测试时,确保viewport元标签正确设置(你的代码中已配置,无需修改)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:30:53