使用D3.JS在mapbox地图添加饼图

        本来想用popups然后用echarts拿popups里的自定义DOM初始化饼图,方法确实可行但是会影响下方图层的点击事件,移入事件等(popup会遮挡图层)。下方dome可解决遮挡问题,可复制替换自己mapbox的tk直接运行,各位大佬如有更好的方法欢迎分享~~~

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>D3.js在mapbox上添加饼图</title>
  <link href="https://cdn.bootcdn.net/ajax/libs/mapbox-gl/2.10.0/mapbox-gl.css" rel="stylesheet">
  <script src="https://cdn.bootcdn.net/ajax/libs/mapbox-gl/2.10.0/mapbox-gl.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/d3/7.9.0/d3.js"></script>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    #map {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 100%;
    }

    .pie-chart {
      position: absolute;
    }

    .tooltip {
      position: absolute;
      padding: 5px;
      background-color: white;
      border: 1px solid #ccc;
      border-radius: 3px;
      pointer-events: none;
      opacity: 0;
      transition: opacity 0.2s;
      z-index: 1000;
      /* 默认设置一个较高的 z-index */
    }
  </style>
</head>

<body>
  <div id="map"></div>

  <script>
    mapboxgl.accessToken = '你的mapbox tk';
    const map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/streets-v11',
      center: [
          114.21988636442639,
          22.6870220693995
        ],
      zoom: 10,
      pitch: 45
    });

    // 用于存储饼图标记
    const districtMarkers = [];
    const usageColorList = [
      { name: '用途1', color: '#6B8BEB' },
      { name: '用途2', color: '#3FD4BA' },
      { name: '用途3', color: '#F9D04B' },
      { name: '用途4', color: '#6DC2F1' },
    ];


    // 数据结构 可根据自己需求改
    const pieData = [
      {
        "coordinates": [ // 饼图中心
          114.3573332397592,
          22.69108655884441
        ],
        "data": [ // 该点的数据 
          {
            "label": "用途1",
            "value": 101,
            "pie": {
              "用途1": 101,
              "用途2": 22,
              "name": "区域1",
              "x": 114.3573332397592,
              "y": 22.69108655884441,
              "全部": 236,
              "用途3": 75,
              "用途4": 38,
              "key": "index1"
            }
          },
          {
            "label": "用途2",
            "value": 22,
            "pie": {
              "用途1": 101,
              "用途2": 22,
              "name": "区域1",
              "x": 114.3573332397592,
              "y": 22.69108655884441,
              "全部": 236,
              "用途3": 75,
              "用途4": 38,
              "key": "index1"
            }
          },
          {
            "label": "用途3",
            "value": 75,
            "pie": {
              "用途1": 101,
              "用途2": 22,
              "name": "区域1",
              "x": 114.3573332397592,
              "y": 22.69108655884441,
              "全部": 236,
              "用途3": 75,
              "用途4": 38,
              "key": "index1"
            }
          },
          {
            "label": "用途4",
            "value": 38,
            "pie": {
              "用途1": 101,
              "用途2": 22,
              "name": "区域1",
              "x": 114.3573332397592,
              "y": 22.69108655884441,
              "全部": 236,
              "用途3": 75,
              "用途4": 38,
              "key": "index1"
            }
          }
        ],
        "text": [
          "区域1",
          236,
          "XX数量"
        ]
      },
      {
        "coordinates": [
          114.14335649496182,
          22.577424965775723
        ],
        "data": [
          {
            "label": "用途1",
            "value": 1130,
            "pie": {
              "用途1": 1130,
              "用途2": 428,
              "name": "区域2",
              "x": 114.14335649496182,
              "y": 22.577424965775723,
              "全部": 2473,
              "用途3": 696,
              "用途4": 219,
              "key": "index2"
            }
          },
          {
            "label": "用途2",
            "value": 428,
            "pie": {
              "用途1": 1130,
              "用途2": 428,
              "name": "区域2",
              "x": 114.14335649496182,
              "y": 22.577424965775723,
              "全部": 2473,
              "用途3": 696,
              "用途4": 219,
              "key": "index2"
            }
          },
          {
            "label": "用途3",
            "value": 696,
            "pie": {
              "用途1": 1130,
              "用途2": 428,
              "name": "区域2",
              "x": 114.14335649496182,
              "y": 22.577424965775723,
              "全部": 2473,
              "用途3": 696,
              "用途4": 219,
              "key": "index2"
            }
          },
          {
            "label": "用途4",
            "value": 219,
            "pie": {
              "用途1": 1130,
              "用途2": 428,
              "name": "区域2",
              "x": 114.14335649496182,
              "y": 22.577424965775723,
              "全部": 2473,
              "用途3": 696,
              "用途4": 219,
              "key": "index2"
            }
          }
        ],
        "text": [
          "区域2",
          2473,
          "XX数量"
        ]
      },
      {
        "coordinates": [
          113.9414783873699,
          22.558112817122733
        ],
        "data": [
          {
            "label": "用途1",
            "value": 1000,
            "pie": {
              "用途1": 1000,
              "用途2": 294,
              "name": "区域3",
              "x": 113.9414783873699,
              "y": 22.558112817122733,
              "全部": 2388,
              "用途3": 766,
              "用途4": 328,
              "key": "index3"
            }
          },
          {
            "label": "用途2",
            "value": 294,
            "pie": {
              "用途1": 1000,
              "用途2": 294,
              "name": "区域3",
              "x": 113.9414783873699,
              "y": 22.558112817122733,
              "全部": 2388,
              "用途3": 766,
              "用途4": 328,
              "key": "index3"
            }
          },
          {
            "label": "用途3",
            "value": 766,
            "pie": {
              "用途1": 1000,
              "用途2": 294,
              "name": "区域3",
              "x": 113.9414783873699,
              "y": 22.558112817122733,
              "全部": 2388,
              "用途3": 766,
              "用途4": 328,
              "key": "index3"
            }
          },
          {
            "label": "用途4",
            "value": 328,
            "pie": {
              "用途1": 1000,
              "用途2": 294,
              "name": "区域3",
              "x": 113.9414783873699,
              "y": 22.558112817122733,
              "全部": 2388,
              "用途3": 766,
              "用途4": 328,
              "key": "index3"
            }
          }
        ],
        "text": [
          "区域3",
          2388,
          "XX数量"
        ]
      },
      {
        "coordinates": [
          114.02988636442639,
          22.6870220693995
        ],
        "data": [
          {
            "label": "用途1",
            "value": 474,
            "pie": {
              "用途1": 474,
              "用途2": 74,
              "name": "区域4",
              "x": 114.02988636442639,
              "y": 22.6870220693995,
              "全部": 932,
              "用途3": 273,
              "用途4": 111,
              "key": "index4"
            }
          },
          {
            "label": "用途2",
            "value": 74,
            "pie": {
              "用途1": 474,
              "用途2": 74,
              "name": "区域4",
              "x": 114.02988636442639,
              "y": 22.6870220693995,
              "全部": 932,
              "用途3": 273,
              "用途4": 111,
              "key": "index4"
            }
          },
          {
            "label": "用途3",
            "value": 273,
            "pie": {
              "用途1": 474,
              "用途2": 74,
              "name": "区域4",
              "x": 114.02988636442639,
              "y": 22.6870220693995,
              "全部": 932,
              "用途3": 273,
              "用途4": 111,
              "key": "index4"
            }
          },
          {
            "label": "用途4",
            "value": 111,
            "pie": {
              "用途1": 474,
              "用途2": 74,
              "name": "区域4",
              "x": 114.02988636442639,
              "y": 22.6870220693995,
              "全部": 932,
              "用途3": 273,
              "用途4": 111,
              "key": "index4"
            }
          }
        ],
        "text": [
          "区域4",
          932,
          "XX数量"
        ]
      },
      {
        "coordinates": [
          114.26641888001215,
          22.598780315920703
        ],
        "data": [
          {
            "label": "用途1",
            "value": 353,
            "pie": {
              "用途1": 353,
              "用途2": 112,
              "name": "区域5",
              "x": 114.26641888001215,
              "y": 22.598780315920703,
              "全部": 748,
              "用途4": 87,
              "用途3": 196,
              "key": "index5"
            }
          },
          {
            "label": "用途2",
            "value": 112,
            "pie": {
              "用途1": 353,
              "用途2": 112,
              "name": "区域5",
              "x": 114.26641888001215,
              "y": 22.598780315920703,
              "全部": 748,
              "用途4": 87,
              "用途3": 196,
              "key": "index5"
            }
          },
          {
            "label": "用途3",
            "value": 196,
            "pie": {
              "用途1": 353,
              "用途2": 112,
              "name": "区域5",
              "x": 114.26641888001215,
              "y": 22.598780315920703,
              "全部": 748,
              "用途4": 87,
              "用途3": 196,
              "key": "index5"
            }
          },
          {
            "label": "用途4",
            "value": 87,
            "pie": {
              "用途1": 353,
              "用途2": 112,
              "name": "区域5",
              "x": 114.26641888001215,
              "y": 22.598780315920703,
              "全部": 748,
              "用途4": 87,
              "用途3": 196,
              "key": "index5"
            }
          }
        ],
        "text": [
          "区域5",
          748,
          "XX数量"
        ]
      },
      {
        "coordinates": [
          114.49800579316843,
          22.579158819024364
        ],
        "data": [
          {
            "label": "用途1",
            "value": 97,
            "pie": {
              "用途1": 97,
              "用途2": 20,
              "name": "区域6",
              "x": 114.49800579316843,
              "y": 22.579158819024364,
              "全部": 181,
              "用途3": 53,
              "用途4": 11,
              "key": "index6"
            }
          },
          {
            "label": "用途2",
            "value": 20,
            "pie": {
              "用途1": 97,
              "用途2": 20,
              "name": "区域6",
              "x": 114.49800579316843,
              "y": 22.579158819024364,
              "全部": 181,
              "用途3": 53,
              "用途4": 11,
              "key": "index6"
            }
          },
          {
            "label": "用途3",
            "value": 53,
            "pie": {
              "用途1": 97,
              "用途2": 20,
              "name": "区域6",
              "x": 114.49800579316843,
              "y": 22.579158819024364,
              "全部": 181,
              "用途3": 53,
              "用途4": 11,
              "key": "index6"
            }
          },
          {
            "label": "用途4",
            "value": 11,
            "pie": {
              "用途1": 97,
              "用途2": 20,
              "name": "区域6",
              "x": 114.49800579316843,
              "y": 22.579158819024364,
              "全部": 181,
              "用途3": 53,
              "用途4": 11,
              "key": "index6"
            }
          }
        ],
        "text": [
          "区域6",
          181,
          "XX数量"
        ]
      },
      {
        "coordinates": [
          113.8574291143083,
          22.6842750470609
        ],
        "data": [
          {
            "label": "用途1",
            "value": 1206,
            "pie": {
              "用途1": 1206,
              "用途2": 347,
              "name": "区域7",
              "x": 113.8574291143083,
              "y": 22.6842750470609,
              "全部": 5064,
              "用途3": 834,
              "用途4": 2677,
              "key": "index7"
            }
          },
          {
            "label": "用途2",
            "value": 347,
            "pie": {
              "用途1": 1206,
              "用途2": 347,
              "name": "区域7",
              "x": 113.8574291143083,
              "y": 22.6842750470609,
              "全部": 5064,
              "用途3": 834,
              "用途4": 2677,
              "key": "index7"
            }
          },
          {
            "label": "用途3",
            "value": 834,
            "pie": {
              "用途1": 1206,
              "用途2": 347,
              "name": "区域7",
              "x": 113.8574291143083,
              "y": 22.6842750470609,
              "全部": 5064,
              "用途3": 834,
              "用途4": 2677,
              "key": "index7"
            }
          },
          {
            "label": "用途4",
            "value": 2677,
            "pie": {
              "用途1": 1206,
              "用途2": 347,
              "name": "区域7",
              "x": 113.8574291143083,
              "y": 22.6842750470609,
              "全部": 5064,
              "用途3": 834,
              "用途4": 2677,
              "key": "index7"
            }
          }
        ],
        "text": [
          "区域7",
          5064,
          "XX数量"
        ]
      },
      {
        "coordinates": [
          114.2067663059172,
          22.69559735797399
        ],
        "data": [
          {
            "label": "用途1",
            "value": 1206,
            "pie": {
              "用途1": 1206,
              "用途2": 182,
              "name": "区域8",
              "x": 114.2067663059172,
              "y": 22.69559735797399,
              "全部": 3283,
              "用途3": 849,
              "用途4": 1046,
              "key": "index8"
            }
          },
          {
            "label": "用途2",
            "value": 182,
            "pie": {
              "用途1": 1206,
              "用途2": 182,
              "name": "区域8",
              "x": 114.2067663059172,
              "y": 22.69559735797399,
              "全部": 3283,
              "用途3": 849,
              "用途4": 1046,
              "key": "index8"
            }
          },
          {
            "label": "用途3",
            "value": 849,
            "pie": {
              "用途1": 1206,
              "用途2": 182,
              "name": "区域8",
              "x": 114.2067663059172,
              "y": 22.69559735797399,
              "全部": 3283,
              "用途3": 849,
              "用途4": 1046,
              "key": "index8"
            }
          },
          {
            "label": "用途4",
            "value": 1046,
            "pie": {
              "用途1": 1206,
              "用途2": 182,
              "name": "区域8",
              "x": 114.2067663059172,
              "y": 22.69559735797399,
              "全部": 3283,
              "用途3": 849,
              "用途4": 1046,
              "key": "index8"
            }
          }
        ],
        "text": [
          "区域8",
          3283,
          "XX数量"
        ]
      },
      {
        "coordinates": [
          114.04449564558202,
          22.54946366732896
        ],
        "data": [
          {
            "label": "用途1",
            "value": 917,
            "pie": {
              "用途1": 917,
              "用途2": 320,
              "name": "区域9",
              "x": 114.04449564558202,
              "y": 22.54946366732896,
              "全部": 2169,
              "用途3": 743,
              "用途4": 189,
              "key": "index9"
            }
          },
          {
            "label": "用途2",
            "value": 320,
            "pie": {
              "用途1": 917,
              "用途2": 320,
              "name": "区域9",
              "x": 114.04449564558202,
              "y": 22.54946366732896,
              "全部": 2169,
              "用途3": 743,
              "用途4": 189,
              "key": "index9"
            }
          },
          {
            "label": "用途3",
            "value": 743,
            "pie": {
              "用途1": 917,
              "用途2": 320,
              "name": "区域9",
              "x": 114.04449564558202,
              "y": 22.54946366732896,
              "全部": 2169,
              "用途3": 743,
              "用途4": 189,
              "key": "index9"
            }
          },
          {
            "label": "用途4",
            "value": 189,
            "pie": {
              "用途1": 917,
              "用途2": 320,
              "name": "区域9",
              "x": 114.04449564558202,
              "y": 22.54946366732896,
              "全部": 2169,
              "用途3": 743,
              "用途4": 189,
              "key": "index9"
            }
          }
        ],
        "text": [
          "区域9",
          2169,
          "XX数量"
        ]
      }
    ];

    // 动态创建 tooltip 元素并添加到 body 中
    const tooltip = d3.select('body').append('div').attr('class', 'tooltip');

    const markers = [];  // 用于存储饼图标记

    // 添加饼图
    function addPieCharts () {
      const colors = []; // 各用扇区途颜色
      usageColorList.forEach((e) => {
        colors.push(e.color);
      });
      pieData.forEach((pie) => {
        const svg = d3
          .create('svg')
          .attr('class', 'pie-chart')
          .attr('width', 120)
          .attr('height', 120);

        const radius = Math.min(120, 120) / 2;
        const g = svg.append('g').attr('transform', `translate(${radius},${radius})`);

        // 白色实心圆
        g.append('circle').attr('r', radius).attr('fill', 'white');

        const color = d3
          .scaleOrdinal()
          .domain(pie.data.map((d) => d.label))
          .range(colors);

        const pieGenerator = d3.pie().value((d) => d.value);

        const arc = d3
          .arc()
          .innerRadius(radius * 0.6) // 白色饼图半径
          .outerRadius(radius);

        g.selectAll('path')
          .data(pieGenerator(pie.data))
          .enter()
          .append('path')
          .attr('d', arc)
          .attr('fill', (d) => color(d.data.label))
          .on('mouseover', (event, d) => {
            let _ = '';
            // 自定义tooltip dom结构和样式 样式可以不写内联提取出去
            usageColorList.forEach((use) => {
              _ += `
              <div style="display: flex; flex-direction: row; align-items: center;margin-top: 17px;">
                <div style="width: 10px; height: 10px; background: ${use.color
                };border-radius: 50%;"></div>
                <div style="font-family: Microsoft YaHei, Microsoft YaHei;font-weight: 400;font-size: 16px;color: #5677A8; margin: 0 30px 0 10px">${use.name
                }</div>
                <div style="font-family: D-DIN, D-DIN;font-weight: 700;font-size: 20px;color: #5677A8;">${d.data.pie[use.name]
                }</div>
              </div>
            `;
            });
            const html = `
            <div style="padding: 16px 20px;">
              <div style="font-family: Microsoft YaHei, Microsoft YaHei; font-weight: 700; font-size: 16px; color: #1D70EB; ma">XX数量(个)</div>
              ${_}
            </div>
          `;
            tooltip
              .style('opacity', 1)
              .html(html)
              .style('left', `${event.pageX + 10}px`)
              .style('top', `${event.pageY + 10}px`);
          })
          .on('mouseout', () => {
            tooltip.style('opacity', 0);
          });

        // 添加饼图中心文字 三行
        const textLines = pie.text;
        const fontSizes = ['14px', '22px', '12px']; // 每一行的位置
        const lineHeight = 5; // 设置行间距为5px
        let currentY = [-14, 8, 24]; // 每一行的位置
        const fontWeights = ['normal', 'bold', 'normal']; // 每一行的加粗样式
        textLines.forEach((line, index) => {
          g.append('text')
            .attr('text-anchor', 'middle')
            .attr('dy', currentY[index])
            .style('font-size', fontSizes[index])
            .style('fill', '#1D70EB')
            .style('font-weight', fontWeights[index])
            .text(line);
        });
        const marker = new mapboxgl.Marker({ element: svg.node() })
          .setLngLat(pie.coordinates)
          .addTo(map);
        districtMarkers.push(marker);
      });
    };

    // 移除饼图方法
    function removePieCharts () {
      districtMarkers.forEach(marker => marker.remove());
      districtMarkers.length = 0;  // 清空标记数组
      tooltip.style("opacity", 0);  // 隐藏tooltip
    }


    map.on('load', () => {
      addPieCharts();
    });

    // zoom 大于 13 移除饼图 小于 10 添加饼图
    map.on('zoom', () => {
      const zoom = map.getZoom();
      if (zoom > 13) {
        removePieCharts();
      } else if (zoom  <= 10) {
        if (districtMarkers.length === 0) {
          addPieCharts();
        }
      }
    });
  </script>
</body>

</html>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值