>  기사  >  웹 프론트엔드  >  D3.js를 활용한 물류 지도 제작 사례 공유

D3.js를 활용한 물류 지도 제작 사례 공유

小云云
小云云원래의
2018-01-29 09:11:362259검색

이 글에서는 주로 D3.js를 사용하여 물류 지도를 작성하기 위한 샘플 코드를 소개합니다. 편집자는 꽤 좋다고 생각하여 지금 공유하고 참고용으로 제공하겠습니다. 편집자를 따라가서 모두에게 도움이 되기를 바랍니다.

예시

제작 아이디어

  1. 배경으로 중국 지도를 그려야 합니다.

  2. 도로 시트의 시작점과 끝점을 그리려면 주요 도시의 위도와 경도 좌표가 필요합니다.

  3. 물류 주문이 접수된 도시에는 깜박이는 표시가 그려집니다.

  4. 이미 물류주문 대상 도시가 있어 경로는 그려지지 않습니다.

  5. 새로운 물류 주문이 생성될 때마다 마크가 대상까지의 경로를 따라 이동하는 애니메이션 효과가 발생합니다.

  6. 브라우저의 리소스 사용량을 줄이기 위해 그리기 후 데이터를 정리해야 합니다.

코딩 시작

1. 웹 페이지 템플릿 만들기

D3JS 로드 실제 사용 시에는 d3.js 파일을 직접 다운로드하여 로드할 수 있습니다. . D3의 V4 버전이 사용되며 이는 V3 버전과 다릅니다.

그림을 그릴 준비가 된 p 블록을 만듭니다.


<!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>

SVG 생성, 다음 코드는 모두 3f1c4e4b6b16bbbd69b2ee476dc4f83a2cacc6d41bbb37262a98f745aa00fbf0


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

SVG 그래픽 그룹화 생성을 통해 통화 준비

  1. gmp, 배경 맵 저장 그리고 시작점 표시.

  2. mline은 시작점과 목표점 사이의 연결은 물론 목표점까지 저장합니다.

  3. 버튼, 테스트용 버튼


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");

투영 기능 만들기

  1. 경도와 위도는 직접 그릴 수 없으며 평면 좌표로 변환해야 합니다. d3js는 상대적으로 다양한 투영 방법을 제공합니다. 이 예에서는 geoEquirectangular() 방법이 사용됩니다.

  2. 투영은 경도와 위도를 평면 좌표로 변환하는 방법입니다.

  3. path는 경도와 위도를 선 연결을 위한 점 좌표로 변환하는 방법입니다(경로를 구성하기 위해 함수를 작성할 필요가 없습니다)


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

여러 연결 끝점이 호출될 수 있도록 마커를 생성합니다. 여러 개의 물류 연결 끝점이 있으므로 모두 하나의 마커에서 호출됩니다.

  1. 이 마크는 중앙의 원 + 바깥쪽 고리로 구성되어 있습니다. 외부 링의 깜박임 효과는 별도로 생성됩니다.

  2. 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");
중국 지도를 그리고 시작점(창사)을 표시하세요.


지도에 사용된 위도와 경도 설정은 china.json입니다. 온라인에 많은 파일이 있습니다

// 记录长沙坐标
    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");
    });
.

선을 그리는 생성 방법 지정된 시작점에서 끝점까지 선을 그리고 네트워크 지점에 마커를 그립니다.


메소드는 목적지 도시명(city)과 경도, 위도(data)를 입력해야 합니다.

  1. 이전에 구축한 project() 메소드를 호출하여 목적지 경도, 위도를 평면 좌표로 변환합니다.

  2. 시작점(창사)과 끝점 사이의 거리를 선 길이와 애니메이션 시간 매개변수로 계산합니다.

  3. 선에 원형 표시를 그리고 시작점에서 끝점까지의 움직임을 애니메이션화합니다.

  4. 마크가 끝점으로 이동한 후에는 리소스 절약을 위해 삭제됩니다.

  5. 이전에 선점이 그려져 있었다면 선은 그려지지 않고 움직이는 표시만 그려집니다.

  6. 물류 주문이 처리될 때마다 도시 기록이 +1됩니다.

  7. // 创建对象,保存每个城市的物流记录数量
        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();
        };
  8. 마크 바깥쪽 원의 깜박이는 효과를 얻기 위해 애니메이션 대기열 예제 만들기


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);
    });

테스트 버튼 만들기 및 대상 도시 데이터 테스트


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]]);
    });

관련 추천:


Three.js 3D 지도 구현 사례 공유

D3.js를 활용한 테이블 제작 방법 소개

d3.js 벡터 그래픽 그리기 + 드래그 앤 드롭 구현 아이디어

위 내용은 D3.js를 활용한 물류 지도 제작 사례 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.