用 d3.js 做一个地图迁徙图

目录
无目录

本次使用的是 Vue + d3v5。

<div ref="test-svg"></div>
import * as d3 from "d3";
import geoJson from "~/assets/map.json";
export default {
  name: "d3map",
  mounted() {
    const width = 1000,
      height = 800;

    /*
     * 创建一个地理投影
     * .center 设置投影中心位置
     * .scale 设置缩放系数
     *
     */
    const projection = d3
      .geoMercator()
      .center([116.3, 35.07])
      .scale(40000);

    //  创建GEO路径生成器path
    const path = d3.geoPath().projection(projection);

    // 经纬度转投影坐标
    const coo = coordinates => {
      // 转为映射在地图上的坐标
      return projection(coordinates);
    };

    // 设置颜色值
    const ss2 = d3.schemeSet2;
    const sp2 = d3.schemePastel2;

    // 获取GeoJSON数据
    const features = geoJson.features;

    // 创建d3画布
    const svg = d3
      .select(this.$refs["test-svg"])
      .append("svg")
      .attr("width", width + "px")
      .attr("height", height + "px");

    /*
     * 渲染地图
     * mouseover 鼠标移入变色
     */
    const map = svg
      .append("g") // 创建容器
      .attr("class", "map"); // 给容器class="map"

    map
      .selectAll("path") // 获取容器下的path
      .data(features) // 载入geo数据
      .join("path")
      .attr("fill", function(d, i) {
        return ss2[i % 3];
      })
      .attr("d", path)
      .on("mouseover", function(d, i) {
        d3.select(this).attr("fill", sp2[i % 3]);
      })
      .on("mouseout", function(d, i) {
        d3.select(this).attr("fill", ss2[i % 3]);
      });

    /**
     rotate:auto自动旋转方向
     dur:路径运行完成时间
     repeatCount:重复次数
     */
    map
      .append("circle")
      .attr("r", 5)
      .attr("fill", "red")
      .attr("cx", function(d) {
        return coo([116.3, 35.07])[0];
      })
      .attr("cy", function(d) {
        return coo([116.3, 35.07])[1];
      });

    map
      .append("circle")
      .attr("r", 5)
      .attr("fill", "red")
      .attr("cx", function(d) {
        return coo([116.65, 35.0])[0];
      })
      .attr("cy", function(d) {
        return coo([116.65, 35.0])[1];
      });

    const lineGenerator = d3
      .line()
      .x(function(d) {
        return d[0];
      })
      .y(function(d) {
        return d[1];
      });

    const lineData = [
      coo([116.3, 35.07]),
      coo([116.3 + (116.65 - 116.3) / 2, 35.07 + (35.07 - 35.0) / 2]),
      coo([116.65, 35.0]),
    ];
    map
      .append("path")
      .attr("d", lineGenerator.curve(d3.curveBasis)(lineData))
      .attr("stroke", "red")
      .attr("fill", "none")
      .attr("stroke-width", "2");
    svg
      .append("circle") //插入图片
      .attr("id", "img")
      .attr("r", 5)
      .attr("fill", "blue")
      .append("animateMotion")
      .attr("dur", "3s")
      .attr("repeatCount", "indefinite")
      .attr("rotate", "auto")
      .attr("path", lineGenerator.curve(d3.curveBasis)(lineData));
  },
};