Home > Web Front-end > JS Tutorial > How to create a logistics map in D3.js (detailed tutorial)

How to create a logistics map in D3.js (detailed tutorial)

亚连
Release: 2018-06-09 11:32:36
Original
3402 people have browsed it

This article mainly introduces the sample code for using D3.js to create a logistics map. Now I share it with you and give it as a reference.

This article introduces the sample code for creating a logistics map using D3.js and shares it with everyone. The details are as follows:

Sample map

Production Ideas

  1. #You need to draw a map of China as the background.

  2. The latitude and longitude coordinates of major cities are required to draw the starting and ending points of road sheets.

  3. The city that receives the logistics order draws a flashing mark.

  4. The target city that already has a logistics order will no longer draw a route.

  5. Every time a new logistics order is generated, there will be an animation effect of the mark moving along the route to the target.

  6. The data after drawing needs to be cleaned up to reduce the resource usage of the browser.

Start coding

1. Create a web page template

Load D3JS for easy debugging , directly download the d3.js file locally. When actually using it, you can change it to the loading path. Note that the V4 version of D3 is used, which is different from the V3 version.

Create a p block and prepare it for drawing.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf8">
    <script type="text/javascript" src="../../static/d3/d3.js"></script>
    <title>地图</title>
  </head>
  <body>
    <p class="fxmap">
    </p>
  </body>
  <script type="text/javascript"></script>
</html>
Copy after login

Create SVG, all the following codes are placed in <script></script>

var width=1000 , height=800; // 定义SVG宽高
var svg = d3.select("body p.fxmap")
            .append("svg")
            .attr("width", "width) 
            .attr("height", height)
            .style("background","#000"); //
Copy after login

Create SVG graphics grouping in preparation for calling

  1. gmp, save the background map and starting point marker.

  2. mline, saves the connection between the starting point and the target, as well as the target point.

  3. button, button for testing

gmap = svg.append("g").attr("id", "map").attr("stroke", "white").attr("stroke-width",1);
    mline = svg.append("g").attr("id", "moveto").attr("stroke", "#FFF").attr("stroke-width", 1.5).attr("fill","#FFF");
    button = svg.append("g").attr("id", "button").attr("stroke", "white").attr("stroke-width", 1).attr("fill", "white");
Copy after login

Create projection function

  1. Longitude and latitude cannot be used directly for drawing and need to be converted into plane coordinates. d3js provides a relatively rich range of projection methods. In this example, the geoEquirectangular() method is used.

  2. projection is a method to convert longitude and latitude into plane coordinates

  3. path is a method to convert longitude and latitude into line drawing point coordinates (save yourself Then write the function to construct the path path)

var projection = d3.geoEquirectangular()
              .center([465,395]) // 指定投影中心,注意[]中的是经纬度
              .scale(height)
              .translate([width / 2, height / 2]);
var path = d3.geoPath().projection(projection);
Copy after login

Create a marker so that multiple connection endpoints can be called

  1. Because There will be multiple end points of the logistics line, so they are all called in a marker.

  2. This mark is composed of a circular outer ring in the middle. The flashing effect of the outer ring is created separately.

marker = svg.append("defs")
          .append("marker")
          .append("marker")
          .attr("id", "pointer")
          .attr("viewBox","0 0 12 12")  // 可见范围
          .attr("markerWidth","12")    // 标记宽度
          .attr("markerHeight","12")    // 标记高度
          .attr("orient", "auto")     //
          .attr("markerUnits", "strokeWidth") // 随连接线宽度进行缩放
          .attr("refX", "6")       // 连接点坐标
          .attr("refY", "6")
    // 绘制标记中心圆
    marker.append("circle")
        .attr("cx", "6")
        .attr("cy", "6")
        .attr("r", "3")
        .attr("fill", "white");
    // 绘制标记外圆,之后在timer()中添加闪烁效果
    marker.append("circle")
        .attr("id", "markerC")
        .attr("cx", "6")
        .attr("cy", "6")
        .attr("r", "5")
        .attr("fill-opacity", "0")
        .attr("stroke-width", "1")
        .attr("stroke", "white");
Copy after login

Draw a map of China and mark the starting point (Changsha)

The longitude and latitude set used in the map is china.json. There are many files on the Internet

// 记录长沙坐标
    var changsha = projection([112.59,28.12]);
    // 读取地图数据,并绘制中国地图
    mapdata = [];
    d3.json(&#39;china.json&#39;, function(error, data){
      if (error)
        console.log(error);
      // 读取地图数据
      mapdata = data.features;
      // 绘制地图
      gmap.selectAll("path")
        .data(mapdata)
        .enter()
        .append("path")
        .attr("d", path);
      // 标记长沙
      gmap.append("circle").attr("id","changsha")
        .attr("cx", changsha[0])
        .attr("cy", changsha[1])
        .attr("r", "6")
        .attr("fill", "yellow")
      gmap.append("circle").attr("id","changshaC")
        .attr("cx", changsha[0])
        .attr("cy", changsha[1])
        .attr("r", "10")
        .attr("stroke-width", "2")
        .attr("fill-opacity", "0");
    });
Copy after login

Create a method to draw a line from the specified starting point to the end point, and draw markers at the network points.

  1. The method requires inputting the destination city name (city) and latitude and longitude (data)

  2. Call the previously established project() method. Convert the end point latitude and longitude into plane coordinates.

  3. Calculate the distance between the starting point (Changsha) and the end point as line length and animation time parameters.

  4. Draw a circular mark on the line and animate the movement from the starting point to the end point.

  5. After the mark is moved to the end point, it will be deleted to save resources.

  6. If the line point has been drawn before, no line will be drawn, only the moving mark will be drawn.

  7. Every time a logistics order is processed, the city record is 1.

// 创建对象,保存每个城市的物流记录数量
    var citylist = new Object();
    // 创建方法,输入data坐标,绘制发射线
    var moveto = function(city, data){
      var pf = {x:projection([112.59,28.12])[0], y:projection([112.59,28.12])[1]};
      var pt = {x:projection(data)[0], y:projection(data)[1]};
      var distance = Math.sqrt((pt.x - pf.x)**2 + (pt.y - pf.y)**2);
      if (city in citylist){
        citylist[city]++;
      }else{
        mline.append("line")
            .attr("x1", pf.x)
            .attr("y1", pf.y)
            .attr("x2", pt.x)
            .attr("y2", pt.y)
            .attr("marker-end","url(#pointer)")
            .style("stroke-dasharray", " "+distance+", "+distance+" ")
            .transition()
            .duration(distance*30)
            .styleTween("stroke-dashoffset", function(){
              return d3.interpolateNumber(distance, 0);
            });
        citylist[city] = 1;
      };
      mline.append("circle")
        .attr("cx", pf.x)
        .attr("cy", pf.y)
        .attr("r", 3)
        .transition()
        .duration(distance*30)
        .attr("transform", "translate("+(pt.x-pf.x)+","+(pt.y-pf.y)+")")
        .remove();
    };
Copy after login

Create an animation queue example to achieve the flashing effect of the outer circle of the mark

var scale = d3.scaleLinear();
    scale.domain([0, 1000, 2000])
      .range([0, 1, 0]);
    var start = Date.now();
    d3.timer(function(){
      var s1 = scale((Date.now() - start)%2000);
      // console.log(s1);
      gmap.select("circle#changshaC")
        .attr("stroke-opacity", s1);
      marker.select("circle#markerC")
        .attr("stroke-opacity", s1);
    });
Copy after login

Create a test button and test target city data

var cityordinate = {
      &#39;哈尔滨&#39;:[126.5416150000,45.8088260000],
      &#39;石家庄&#39;:[116.46,39.92],
      &#39;北京&#39;:[116.39564503787867,39.92998577808024],
      &#39;上海&#39;:[121.480539,31.235929],
      &#39;广州&#39;:[113.271431,23.135336],
      &#39;重庆&#39;:[106.558434,29.568996],
      &#39;青岛&#39;:[120.38442818368189,36.10521490127382],
      &#39;福州&#39;:[119.30347,26.080429],
      &#39;兰州&#39;:[103.840521,36.067235],
      &#39;贵阳&#39;:[106.636577,26.653325],
      &#39;成都&#39;:[104.081534,30.655822],
      &#39;西安&#39;:[108.946466,34.347269],
      &#39;长春&#39;:[125.3306020000,43.8219540000],
      &#39;台湾&#39;:[120.961454,23.80406],
      &#39;呼和浩特&#39;:[111.7555090000,40.8484230000],
      &#39;澳门&#39;:[113.5494640000,22.1929190000],
      &#39;武汉&#39;:[114.3115820000,30.5984670000],
      &#39;昆明&#39;:[102.71460113878045,25.049153100453159],
      &#39;乌鲁木齐&#39;:[87.56498774111579,43.84038034721766],
      &#39;益阳&#39;:[112.36654664522563,28.58808777988717],
      &#39;南京&#39;:[118.77807440802562,32.05723550180587],
      &#39;武昌&#39;:[114.35362228468498,30.56486029278519],
    };

    // 随机获得目标城市
    var cityname = [], total = 0;
    for (var key in cityordinate){
      cityname[total++] = key;
    };
    
    // 创建操作按钮,每次点击发射一条物流线
    button.append("circle")
        .attr("cx", width*0.9)
        .attr("cy", height*0.8)
        .attr("r", width/20)
        .attr("text","click")
        .attr("fill", "grey");
    button.append("text")
        .attr("x", width*0.87)
        .attr("y", height*0.81)
        .style("font-size", "30px")
        .text("click");
    button.on("click", function(){
      var _index = ~~(Math.random() * total);
      moveto(cityname[_index], cityordinate[cityname[_index]]);
    });
Copy after login

The above is I compiled it for everyone, I hope it will be helpful to everyone in the future.

Related articles:

How to implement map grid using Baidu Maps

Comparison and distinction between Express and Koa2 in nodejs (detailed tutorial)

The singleton mode in JS implements data addition, deletion, modification and query

The above is the detailed content of How to create a logistics map in D3.js (detailed tutorial). For more information, please follow other related articles on the PHP Chinese website!

Related labels:
map
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template