腾讯地图Web版解决热力图被轮廓覆盖的问题

前言

你好,我是喵喵侠。

还记得那天傍晚,我正对着电脑调试一个腾讯地图的热力图页面。项目是一个区域人流密度可视化模块,我加了一个淡蓝色的轮廓图层用于表示区域范围,热力图放在下面用于展示人流热度。效果一预览,瞬间眉头皱了起来:热力图几乎被轮廓"盖没了"!

经过一番摸索与咨询官方技术支持,问题终于迎刃而解。这篇文章就来分享这次踩坑经历,告诉你该怎么正确"安排"这两张图层的关系。

问题复现

为了复现这个问题,我在官方demo的基础上,写了一个问题demo如下:

html 复制代码
<!--
 * @Author: Cooper [email protected]
 * @Date: 2025-06-11 09:24:38
 * @LastEditors: Cooper [email protected]
 * @LastEditTime: 2025-06-11 09:38:01
 * @FilePath: /mapjs/qqmap.html
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>腾讯地图热力图与轮廓示例</title>
  <meta name="viewport"
    content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
  <style type="text/css">
    html,
    body {
      width: 100%;
      height: 100%;
    }

    * {
      margin: 0;
      padding: 0;
    }

    #container {
      height: 90vh;
      width: 100vw;
    }

    #setOptions {
      position: absolute;
      top: 10px;
      left: 10px;
      z-index: 10;
      background: rgba(255, 255, 255, 0.9);
      border-radius: 8px;
      box-shadow: 0 2px 8px #0001;
      padding: 8px;
    }

    button {
      margin: 4px;
      padding: 6px 12px;
      border: 1px solid #555;
      border-radius: 4px;
      background: #f5f5f5;
      cursor: pointer;
    }
  </style>
  <script charset="utf-8"
    src="https://map.qq.com/api/js?v=2.exp&libraries=visualization&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77"></script>
</head>

<body>
  <div id="container"></div>
  <div id="setOptions">
    <button id="show">显示/隐藏热力图</button>
    <button id="data">更新数据</button>
    <button id="radius">改变半径</button>
    <button id="gradient">改变颜色</button>
    <button id="opacity">改变透明度</button>
    <button id="destroy">销毁热力图</button>
    <button id="toggleContour">显示/隐藏轮廓</button>
  </div>
  <script>
    window.onload = function () {
      // 创建地图
      var map = new qq.maps.Map(document.getElementById("container"), {
        center: new qq.maps.LatLng(39.9847, 116.3074),
        zoom: 12
      });
      // 创建热力图对象
      var heat = new qq.maps.visualization.Heat({
        map: map,
        radius: 30,
      });
      // 获取热力数据
      var data = getHeatData();
      heat.setData(data);

      // 以热力图中心点为中心,生成覆盖热力图的轮廓
      function generateCircleContour(center, radius, pointsCount) {
        var contour = [];
        for (var i = 0; i < pointsCount; i++) {
          var angle = 2 * Math.PI * i / pointsCount;
          var lat = center.lat + radius * Math.sin(angle);
          var lng = center.lng + radius * Math.cos(angle);
          contour.push(new qq.maps.LatLng(lat, lng));
        }
        // 闭合多边形
        contour.push(contour[0]);
        return contour;
      }
      var center = { lat: 39.9847, lng: 116.3074 };
      var radius = 0.08; // 与热力图点分布半径一致
      var haidianPath = generateCircleContour(center, radius, 40);
      var contour = new qq.maps.Polygon({
        map: map,
        path: haidianPath,
        strokeColor: new qq.maps.Color(173, 216, 230, 0.8),
        fillColor: new qq.maps.Color(173, 216, 230, 0.5),
      });
      var contourVisible = true;

      // 按钮事件
      document.getElementById("setOptions").addEventListener("click", function (e) {
        var target = e.target;
        switch (target.id) {
          case "show":
            if (heat.visible) {
              heat.hide();
            } else {
              heat.show();
            }
            break;
          case "data":
            data = getHeatData(200);
            heat.setData(data);
            break;
          case "radius":
            let radius = heat.getRadius();
            heat.setRadius(radius + 10 > 80 ? 20 : radius + 10);
            break;
          case "gradient":
            let gradient = heat.getGradient();
            gradient[1.0] = "#fff";
            heat.setGradient(gradient);
            break;
          case "opacity":
            let opacity = heat.getOpacity();
            opacity = [0.1, 0.8];
            heat.setOpacity(opacity);
            break;
          case "destroy":
            heat.destroy();
            break;
          case "toggleContour":
            contourVisible = !contourVisible;
            contour.setMap(contourVisible ? map : null);
            break;
          default:
        }
      });

      function getHeatData(cnt, max, min) {
        let data = [];
        let center = { lat: 39.9847, lng: 116.3074 };
        cnt = cnt || 100;
        max = max || 100;
        min = min || 0;
        for (let index = 0; index < cnt; index++) {
          let r = Math.random() * 0.08;
          let angle = Math.random() * Math.PI * 2;
          let heatValue = Math.random() * (max - min) + min;
          data.push({
            lat: center.lat + r * Math.sin(angle),
            lng: center.lng + r * Math.cos(angle),
            value: heatValue
          });
        }
        return { max: max, min: min, data: data };
      }
    }
  </script>
</body>

</html>

可以看到这样效果如下图所示,热力图被盖住。

解决办法

我咨询官方给出解决办法是,设置热力图的层级比轮廓大就可以了,也就是设置zIndex。

设置了层级后,效果如下,这样就明显多了!

总结

通过本文的介绍,相信你已经掌握了腾讯地图中热力图被遮挡的解决技巧 ------ 只需要添加 zIndex 属性,就能轻松让热力图"浮上来"

这个问题本身不复杂,但由于文档提示不足,很容易被忽略。很多开发者第一时间想到的是换透明度、调整颜色,其实只差了一个小小的 zIndex

这种操作看似简单,其实很多人都没用过,写这篇文章就是为了帮大家少走弯路。

如果你也觉得有帮助,记得点赞、收藏、关注支持我哟~我们下篇地图踩坑笔记再见!

相关推荐
睡觉z1 小时前
Haproxy搭建web群集
前端
codingandsleeping1 小时前
重读《你不知道的JavaScript》(上)- this
前端·javascript
孩子 你要相信光3 小时前
前端如何通过 Blob 下载 Excel 文件
前端·javascript
IT猫咪酱3 小时前
【前端】yarn install error
前端
喜欢打篮球的普通人3 小时前
Flang:LLVM Fortran 前端简介
前端
qq_2786672864 小时前
ros中相机话题在web页面上的显示,尝试js解析sensor_msgs/Image数据
前端·javascript·ros
烛阴5 小时前
JavaScript并发控制:从Promise到队列系统
前端·javascript
zhangxingchao5 小时前
关于《黑马鸿蒙5.0零基础入门》课程的总结
前端
zhangxingchao5 小时前
Flutter的Widget世界
前端