0

0

D3.js创建物流地图

php中世界最好的语言

php中世界最好的语言

发布时间:2018-03-23 13:17:34

|

2543人浏览过

|

来源于php中文网

原创

这次给大家带来D3.js创建物流地图,D3.js创建物流地图的注意事项有哪些,下面就是实战案例,一起来看一下。

示例图

制作思路

  1. 需要绘制一张中国地图,做为背景。

  2. 需要主要城市的经纬坐标,以绘制路张起点和终点。

  3. 接收到物流单的城市,绘制一个闪烁的标记。

  4. 已经有过物流单的目标城市,不再绘制路线。

  5. 每次新产生一笔物流单,都有一个标记沿路线移向目标的动画效果。

  6. 绘制结束后的数据,需要清理掉,以减少对浏览器的资源占用。

开始撸码

1.创建网页模板

加载D3JS,为了方便调试,直接下载d3.js文件在本地,实际使用的时候,可以换成加载路径。注意,使用的是V4版的D3,和V3版有差异。

创建一个p块,准备绘图。



  
    
    
    地图
  
  
    

创建SVG,以下所有代码放在

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. buttion,测试用的按钮

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 是将经纬度转换为连线绘制点坐标的方法(省得自己再写函数构造path路径)

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

创建marker标记,以便多个连线终点调用

  1. 由于会有多个物流连线的终点,所以都放在一个marker标记中调用。

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

创建方法,绘制一条从指定起点到终点的连线,并在络点绘制marker标记。

  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中文网其它相关文章!

推荐阅读:

JS获取图片的top N色值方法

简单CMS
简单CMS

简单CMS购物分享平台是一套基于LAMP架构和ThinkPHP框架为基础的、免费的、开源系统,为广大站长建站提供简单创建一个属于自己的电子商务导购平台及图片信息分享平台。 简单CMS的主要特点: 1模板均来自目前最流行的平台。如:美丽说,蘑菇街,下一件等。 2数据可根据站长的需求进行自动有效推送。 3数据均为用户分享。 4广告精准定位。 5注重用户体验。 6运行高效。简单CMS(jdcms)发布

下载

使用render方法的图文详解

小程序使用.getImageInfo()获取图片信息

相关专题

更多
php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

150

2025.12.31

php网站源码教程大全
php网站源码教程大全

本专题整合了php网站源码相关教程,阅读专题下面的文章了解更多详细内容。

88

2025.12.31

视频文件格式
视频文件格式

本专题整合了视频文件格式相关内容,阅读专题下面的文章了解更多详细内容。

90

2025.12.31

不受国内限制的浏览器大全
不受国内限制的浏览器大全

想找真正自由、无限制的上网体验?本合集精选2025年最开放、隐私强、访问无阻的浏览器App,涵盖Tor、Brave、Via、X浏览器、Mullvad等高自由度工具。支持自定义搜索引擎、广告拦截、隐身模式及全球网站无障碍访问,部分更具备防追踪、去谷歌化、双内核切换等高级功能。无论日常浏览、隐私保护还是突破地域限制,总有一款适合你!

61

2025.12.31

出现404解决方法大全
出现404解决方法大全

本专题整合了404错误解决方法大全,阅读专题下面的文章了解更多详细内容。

493

2025.12.31

html5怎么播放视频
html5怎么播放视频

想让网页流畅播放视频?本合集详解HTML5视频播放核心方法!涵盖<video>标签基础用法、多格式兼容(MP4/WebM/OGV)、自定义播放控件、响应式适配及常见浏览器兼容问题解决方案。无需插件,纯前端实现高清视频嵌入,助你快速打造现代化网页视频体验。

16

2025.12.31

关闭win10系统自动更新教程大全
关闭win10系统自动更新教程大全

本专题整合了关闭win10系统自动更新教程大全,阅读专题下面的文章了解更多详细内容。

12

2025.12.31

阻止电脑自动安装软件教程
阻止电脑自动安装软件教程

本专题整合了阻止电脑自动安装软件教程,阅读专题下面的文章了解更多详细教程。

5

2025.12.31

html5怎么使用
html5怎么使用

想快速上手HTML5开发?本合集为你整理最实用的HTML5使用指南!涵盖HTML5基础语法、主流框架(如Bootstrap、Vue、React)集成方法,以及无需安装、直接在线编辑运行的平台推荐(如CodePen、JSFiddle)。无论你是新手还是进阶开发者,都能轻松掌握HTML5网页制作、响应式布局与交互功能开发,零配置开启高效前端编程之旅!

2

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 1.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号