D3.js创建物流地图

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

示例图

D3.js创建物流地图

制作思路

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

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

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

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

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

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

开始撸码

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图形分组,以备调用

gmp,保存背景地图和起点标记。

mline,保存起点和目标之间的连线,以及目标点。

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

登录后复制

创建投影函数

经纬度不能直接用来绘图,需要转换成平面坐标。d3js提供了比较丰富的投影方法,本例中使用了geoEquirectangular()方法。

projection 是将经纬度转换为平面坐标的方法

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

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

登录后复制

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

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

这个标记是由中间的 圆形 + 外圈 构成。外圈的闪烁效果另外创建。

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标记。

方法需要输入终点城市名称(city)和经纬度(data)

调用之前建立的project()方法,将终点经纬度转换为平面坐标。

计算起点(长沙)和终点之前的距离,做为线条长度和动画时间参数。

在线条上绘制一个圆形标记,并实现从起点到终点的移动动画。

标记移动到终点后,即删除,节省资源。

如果线点在之前已经绘制过,则不绘线条,只绘制移动标记。

每处理一次物流单,则城市记录+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]]);    });

登录后复制

相信看了本文案例你已经掌握了方法,更多精彩请关注【创想鸟】其它相关文章!

推荐阅读:

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

使用render方法的图文详解

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

以上就是D3.js创建物流地图的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2779750.html

(0)
上一篇 2025年3月8日 15:50:56
下一篇 2025年2月27日 16:56:11

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • ejsExcel模板在Vue.js中的使用

    这次给大家带来ejsExcel模板在Vue.js中的使用,ejsExcel模板在Vue.js中使用的注意事项有哪些,下面就是实战案例,一起来看一下。 什么是ejsExcel? ejsExcel是一款国人开发的、在Node.js应用程序中使用…

    2025年3月8日 编程技术
    200
  • JS如何做出公共子序列

    这次给大家带来JS如何做出公共子序列,JS实现公共子序列的注意事项有哪些,下面就是实战案例,一起来看一下。 介绍 最长公共子序列(Longest Common Subsequence LCS)是从给定的两个序列X和Y中取出尽可能多的一部分字…

    2025年3月8日 编程技术
    200
  • Web应用开发为什么选择Node.js

    这次给大家带来Web应用开发为什么选择Node.js,Web应用开发选择Node.js的注意事项有哪些,下面就是实战案例,一起来看一下。 一项颠覆性的技术进入技术市场总会带来一阵震惊,但随之而来往往是被放弃。然而,Node.js 当然不是这…

    2025年3月8日 编程技术
    200
  • JS的策略模式使用详解

    这次给大家带来JS的策略模式使用详解,使用JS策略模式的注意事项有哪些,下面就是实战案例,一起来看一下。 策略模式的概念引用: 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法…

    2025年3月8日
    200
  • JS自动计算酒店住宿费用

    这篇文章主要介绍了javascript实现获取一个日期段内每天不同的价格(计算入住总价格)的相关资料,需要的朋友可以参考下   代码例子 最近在做酒店的小程序项目开发,遇到一个这样的问题。 酒店的房间价格是浮动的,每天每时或某个特殊的日期价…

    2025年3月8日
    200
  • JS的Object内部方法图

    这次给大家带来JS的Object内部方法图,Object内部方法图注意事项有哪些,下面就是实战案例,一起来看一下。 对于JavaScript对象的操作基本上都会调用底层的对象内部方法,我们可以看出在ES6标准中定了14种内部方法. 双 [[…

    2025年3月8日
    200
  • 在Vue.JS中怎样使用echarts

    这次给大家带来在Vue.JS中怎样使用echarts,在Vue.JS中使用echarts的注意事项有哪些,下面就是实战案例,一起来看一下。 上篇文章给大家介绍了 在 webpack 中使用 ECharts的实例详解 ,可以点击查看。 1. …

    编程技术 2025年3月8日
    200
  • js的作用域与预解析使用详解

    这次给大家带来js的作用域与预解析使用详解,js作用域与预解析使用的注意事项有哪些,下面就是实战案例,一起来看一下。 虽然,ES6在我们工作中应用得越来越广泛,但是还是很多项目保留着ES5的写法,所以,今天,带着大家重新巩固下ES5下的作用…

    编程技术 2025年3月8日
    200
  • JS仿今日头条手机端主页界面

    这次给大家带来JS仿今日头条手机端主页界面,JS仿今日头条手机端主页界面的注意事项有哪些,下面就是实战案例,一起来看一下。 前言 vue也弄了一段时间了, 前段时间一直想用vue写个移动端,加之年底也不是很忙,于是前几天便着手开始弄了,到今…

    2025年3月8日 编程技术
    200
  • js的闭包使用详解

    这次给大家带来js的闭包使用详解,js闭包使用的注意事项有哪些,下面就是实战案例,一起来看一下。 闭包 按中文的意思就是关上一个包的意思。如果我们把函数的作用域当做是一个包的话,那这个词很形象体现了它的作用 。函数的正常的执行流程是当函数中…

    编程技术 2025年3月8日
    200

发表回复

登录后才能评论