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

基于日期联动JSON的HTML范围滑块实现热力图动态更新需求

实现带时间滑块的动态热力图(基于JSON时序数据)

我刚好处理过类似的需求,核心思路是把JSON数据按时间顺序映射到滑块的取值范围,拖动滑块时切换对应的数据集并重新渲染热力图。下面是完整的可运行示例,包含从数据处理到渲染的全流程:

第一步:准备JSON数据结构

假设你的JSON数据是按时间节点存储的(如果原始数据没排序,后面会处理排序),示例结构如下:

[
  {
    "timestamp": "2024-01-01T00:00:00",
    "heatPoints": [{"lat": 39.9042, "lng": 116.4074, "intensity": 0.3}, {"lat": 31.2304, "lng": 121.4737, "intensity": 0.5}]
  },
  {
    "timestamp": "2024-01-02T00:00:00",
    "heatPoints": [{"lat": 39.9042, "lng": 116.4074, "intensity": 0.7}, {"lat": 31.2304, "lng": 121.4737, "intensity": 0.8}, {"lat": 23.1291, "lng": 113.2644, "intensity": 0.4}]
  },
  {
    "timestamp": "2024-01-03T00:00:00",
    "heatPoints": [{"lat": 39.9042, "lng": 116.4074, "intensity": 0.9}, {"lat": 31.2304, "lng": 121.4737, "intensity": 1.0}, {"lat": 23.1291, "lng": 113.2644, "intensity": 0.7}, {"lat": 30.2741, "lng": 120.1551, "intensity": 0.6}]
  }
]

第二步:完整HTML+JS实现

下面的代码包含滑块、时间显示、热力图容器,以及核心的交互逻辑:

<!DOCTYPE html>
<html>
<head>
    <title>动态热力图时间滑块</title>
    <style>
        #heatmap-container {
            width: 800px;
            height: 600px;
            border: 1px solid #eee;
            margin: 20px 0;
            position: relative;
            background: #f9f9f9;
        }
        .heat-point {
            position: absolute;
            border-radius: 50%;
            opacity: 0.6;
            transform: translate(-50%, -50%);
            transition: all 0.3s ease;
        }
        #slider-container {
            width: 800px;
        }
        #current-timestamp {
            font-size: 16px;
            font-weight: 600;
            color: #333;
            margin-bottom: 10px;
        }
        input[type="range"] {
            width: 100%;
            height: 6px;
            border-radius: 3px;
            background: #ddd;
            outline: none;
        }
    </style>
</head>
<body>
    <div id="current-timestamp">当前数据:2024-01-01T00:00:00</div>
    <div id="slider-container">
        <input type="range" id="time-slider" min="0" max="2" value="0" step="1">
    </div>
    <div id="heatmap-container"></div>

    <script>
        // 模拟加载JSON数据(实际项目中用fetch从文件获取)
        let heatData = [
            {
                "timestamp": "2024-01-01T00:00:00",
                "heatPoints": [{"lat": 39.9042, "lng": 116.4074, "intensity": 0.3}, {"lat": 31.2304, "lng": 121.4737, "intensity": 0.5}]
            },
            {
                "timestamp": "2024-01-02T00:00:00",
                "heatPoints": [{"lat": 39.9042, "lng": 116.4074, "intensity": 0.7}, {"lat": 31.2304, "lng": 121.4737, "intensity": 0.8}, {"lat": 23.1291, "lng": 113.2644, "intensity": 0.4}]
            },
            {
                "timestamp": "2024-01-03T00:00:00",
                "heatPoints": [{"lat": 39.9042, "lng": 116.4074, "intensity": 0.9}, {"lat": 31.2304, "lng": 121.4737, "intensity": 1.0}, {"lat": 23.1291, "lng": 113.2644, "intensity": 0.7}, {"lat": 30.2741, "lng": 120.1551, "intensity": 0.6}]
            }
        ];

        // 确保数据按时间从旧到新排序(如果原始JSON没排序的话)
        heatData.sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));

        // 获取DOM元素
        const slider = document.getElementById('time-slider');
        const timestampDisplay = document.getElementById('current-timestamp');
        const heatmapContainer = document.getElementById('heatmap-container');

        // 初始化滑块的最大值为数据长度-1
        slider.max = heatData.length - 1;

        // 初始渲染最旧的数据
        renderHeatmap(heatData[0].heatPoints);
        updateTimestampDisplay(heatData[0].timestamp);

        // 绑定滑块拖动事件
        slider.addEventListener('input', function() {
            const currentIndex = parseInt(this.value);
            const activeData = heatData[currentIndex];
            // 更新时间显示
            updateTimestampDisplay(activeData.timestamp);
            // 重新渲染热力图
            renderHeatmap(activeData.heatPoints);
        });

        // 更新时间显示的辅助函数
        function updateTimestampDisplay(timestamp) {
            timestampDisplay.textContent = `当前数据:${timestamp}`;
        }

        // 渲染热力图的核心函数(示例用DOM元素模拟,可替换为专业图库)
        function renderHeatmap(points) {
            // 清空容器
            heatmapContainer.innerHTML = '';
            
            points.forEach(point => {
                // 简单将经纬度映射为容器内坐标(实际项目需根据地图投影转换)
                const x = (point.lng - 110) / (125 - 110) * heatmapContainer.offsetWidth;
                const y = (40 - point.lat) / (40 - 20) * heatmapContainer.offsetHeight;
                
                // 根据强度设置点的大小和透明度
                const size = 20 + point.intensity * 80;
                const opacity = 0.4 + point.intensity * 0.6;
                
                const pointEl = document.createElement('div');
                pointEl.className = 'heat-point';
                pointEl.style.width = `${size}px`;
                pointEl.style.height = `${size}px`;
                pointEl.style.left = `${x}px`;
                pointEl.style.top = `${y}px`;
                pointEl.style.backgroundColor = `rgba(220, 38, 38, ${opacity})`;
                
                heatmapContainer.appendChild(pointEl);
            });
        }
    </script>
</body>
</html>

第三步:适配专业热力图库(可选)

如果你用的是Leaflet、Google Maps这类专业地图库,只需要替换renderHeatmap函数即可。比如用Leaflet.heat的示例:

// 先引入Leaflet和Leaflet.heat的资源
// <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
// <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
// <script src="https://unpkg.com/leaflet.heat@0.2.0/dist/leaflet-heat.js"></script>

// 初始化地图
const map = L.map('heatmap-container').setView([35, 118], 5);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

// 初始化热力图层
const heatLayer = L.heatLayer([], { radius: 30 }).addTo(map);

// 重写渲染函数
function renderHeatmap(points) {
    // 转换为Leaflet.heat需要的格式:[纬度, 经度, 强度]
    const formattedPoints = points.map(p => [p.lat, p.lng, p.intensity]);
    heatLayer.setData(formattedPoints);
}

关键优化点

  • 数据排序:一定要确保JSON数据按时间从旧到新排列,否则滑块拖动顺序会错乱。
  • 节流处理:如果数据量很大,滑块拖动时会频繁触发渲染,可以加个节流函数避免卡顿:
    let debounceTimer;
    slider.addEventListener('input', function() {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => {
            const currentIndex = parseInt(this.value);
            const activeData = heatData[currentIndex];
            updateTimestampDisplay(activeData.timestamp);
            renderHeatmap(activeData.heatPoints);
        }, 60);
    });
    
  • 用户反馈:显示当前时间戳能让用户明确知道正在查看哪个时间段的数据,提升体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:21:08