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

随机定位文本悬停时显示随机排列缩略图的实现需求

实现悬停文本时淡入随机排列的缩略图(满足可扩展/随机位置要求)

需求:当用户悬停不同文本时,淡入显示一组随机排列的缩略图
需满足以下要求:

  • 缩略图需保持在对应文本附近
  • 缩略图可重叠但不能完全覆盖
  • 文本和缩略图的位置在每次页面刷新时均为随机
  • 文本和缩略图不能超出屏幕范围
  • 具备可扩展性(最多支持10个文本,每个文本对应最多10个缩略图,必要时可呈同心圆分布)

原代码存在固定位置、扩展性差、无随机逻辑等问题,以下是重构后的完整实现:

实现思路

  1. 动态生成文本节点及对应缩略图容器,通过配置参数控制数量,满足扩展性要求
  2. 页面加载时随机计算每个文本的屏幕位置,确保不超出视口范围
  3. 悬停文本时,基于文本位置生成缩略图坐标:数量较少时随机分布,数量较多时自动切换为同心圆布局,避免完全覆盖
  4. 使用fadeIn()/fadeOut()实现平滑的淡入淡出效果

完整代码

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="hover-container"></div>

CSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  overflow: hidden;
}

.hover-text {
  position: absolute;
  padding: 8px 12px;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 4px;
  cursor: pointer;
  user-select: none;
  font-size: 14px;
}

.thumb-group {
  position: absolute;
  pointer-events: none;
}

.thumb {
  position: absolute;
  width: 100px;
  height: 100px;
  border-radius: 4px;
  overflow: hidden;
  display: none;
  transition: all 0.3s ease;
}

.thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

JavaScript

$(document).ready(function() {
  // 可配置参数,按需调整
  const CONFIG = {
    maxTexts: 5,
    maxThumbsPerText: 6,
    thumbSize: 100,
    textOffset: 150,
    minOverlap: 20
  };

  const container = $('.hover-container');
  const windowWidth = $(window).width();
  const windowHeight = $(window).height();

  // 生成指定范围的随机整数
  function getRandom(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  // 计算文本的随机位置(确保不超出屏幕)
  function getTextPosition(textWidth, textHeight) {
    return {
      left: getRandom(0, windowWidth - textWidth),
      top: getRandom(0, windowHeight - textHeight)
    };
  }

  // 计算缩略图位置:随机分布/同心圆分布
  function getThumbPositions(textCenterX, textCenterY, count) {
    const positions = [];
    // 缩略图数量超过6时用同心圆布局
    if (count > 6) {
      const radiusStep = CONFIG.textOffset / Math.ceil(count / 6);
      let currentRadius = radiusStep;
      const angleStep = 360 / 6;
      let angle = 0;
      for (let i = 0; i < count; i++) {
        if (i % 6 === 0 && i !== 0) currentRadius += radiusStep;
        const radian = (angle * Math.PI) / 180;
        let x = textCenterX + currentRadius * Math.cos(radian) - CONFIG.thumbSize/2;
        let y = textCenterY + currentRadius * Math.sin(radian) - CONFIG.thumbSize/2;
        // 边界校验
        x = Math.max(0, Math.min(x, windowWidth - CONFIG.thumbSize));
        y = Math.max(0, Math.min(y, windowHeight - CONFIG.thumbSize));
        positions.push({x, y});
        angle += angleStep;
      }
    } else {
      // 随机分布,确保最小间距
      for (let i = 0; i < count; i++) {
        let x, y;
        do {
          x = getRandom(textCenterX - CONFIG.textOffset, textCenterX + CONFIG.textOffset) - CONFIG.thumbSize/2;
          y = getRandom(textCenterY - CONFIG.textOffset, textCenterY + CONFIG.textOffset) - CONFIG.thumbSize/2;
          x = Math.max(0, Math.min(x, windowWidth - CONFIG.thumbSize));
          y = Math.max(0, Math.min(y, windowHeight - CONFIG.thumbSize));
          // 检查是否与已有位置过度重叠
          const hasOverlap = positions.some(pos => 
            Math.abs(pos.x - x) < CONFIG.minOverlap && Math.abs(pos.y - y) < CONFIG.minOverlap
          );
          if (!hasOverlap) break;
        } while (true);
        positions.push({x, y});
      }
    }
    return positions;
  }

  // 动态生成文本和缩略图
  for (let i = 0; i < CONFIG.maxTexts; i++) {
    // 创建文本节点并设置随机位置
    const textEl = $(`<div class="hover-text">文本${i+1}</div>`);
    container.append(textEl);
    const textWidth = textEl.width();
    const textHeight = textEl.height();
    const textPos = getTextPosition(textWidth, textHeight);
    textEl.css({
      left: `${textPos.left}px`,
      top: `${textPos.top}px`
    });

    // 创建缩略图组容器
    const thumbGroup = $(`<div class="thumb-group"></div>`);
    container.append(thumbGroup);
    // 生成随机数量的缩略图并设置位置
    const thumbCount = getRandom(3, CONFIG.maxThumbsPerText);
    const thumbPositions = getThumbPositions(textPos.left + textWidth/2, textPos.top + textHeight/2, thumbCount);
    for (let j = 0; j < thumbCount; j++) {
      const thumbEl = $(`
        <div class="thumb">
          <img src="https://placeimg.com/100/100/${['animals','people','tech','nature','arch'][getRandom(0,4)]}" alt="缩略图${j+1}">
        </div>
      `);
      thumbEl.css({
        left: `${thumbPositions[j].x}px`,
        top: `${thumbPositions[j].y}px`
      });
      thumbGroup.append(thumbEl);
    }

    // 绑定悬停事件
    textEl.hover(
      () => thumbGroup.find('.thumb').fadeIn(300),
      () => thumbGroup.find('.thumb').fadeOut(300)
    );
  }
});

关键特性说明

  • 扩展性:通过CONFIG参数可快速调整文本和缩略图的最大数量,无需修改核心逻辑
  • 随机位置:页面加载时自动计算文本的随机坐标,悬停时生成缩略图的随机/同心圆位置
  • 边界控制:所有元素位置计算时都会校验是否超出屏幕范围,确保显示完整
  • 避免完全覆盖:随机分布时检查最小间距,数量多时自动切换为同心圆布局,保证缩略图可见
  • 平滑效果:使用淡入淡出替代生硬的显示/隐藏,提升交互体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:50:18