>  기사  >  웹 프론트엔드  >  D3.js가 물류 지도를 생성합니다.

D3.js가 물류 지도를 생성합니다.

php中世界最好的语言
php中世界最好的语言원래의
2018-03-23 13:17:342232검색

이번에는 D3.js를 사용해 물류 맵을 생성해보겠습니다. 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 생성, 다음 코드는 모두 <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"); //

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. projection은 경도와 위도를 평면 좌표로 변환하는 방법입니다.

  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('china.json', 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");
    });

생성 방법이 많이 있습니다. 지정된 시작점에서 끝점까지 연결하고 교차점에 마커를 그립니다.

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

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

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

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

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

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

  7. 물류 주문이 처리될 때마다 도시 기록이 +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();
    };

마크의 바깥쪽 원의 깜박이는 효과를 얻기 위해 애니메이션 팀 예제를 만듭니다

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

여기에서 사례를 읽고 방법을 마스터했다고 믿습니다. 기사. 더 흥미로운 내용을 보려면 온라인에서 PHP 중국어 기타 관련 기사를 주목하세요!

추천 자료:

이미지의 상위 N개 색상 값을 얻는 JS 방법

렌더링 방법을 사용하는 그래픽 및 텍스트에 대한 자세한 설명

애플릿은 .getImageInfo()를 사용하여 이미지 정보를 얻습니다

위 내용은 D3.js가 물류 지도를 생성합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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