D3 二维图表的绘制系列(二十五)中国地图

上一篇: 力导向图 https://blog.csdn.net/zjw_python/article/details/98617650

下一篇: 盒须图 https://blog.csdn.net/zjw_python/article/details/99581418

代码结构和初始化画布的Chart对象介绍,请先看 https://blog.csdn.net/zjw_python/article/details/98182540

本图完整的源码地址: https://github.com/zjw666/D3_demo/tree/master/src/map/china

1 图表效果

在这里插入图片描述

2 数据

在D3中,地图所使用的数据格式为TopoJSON,一般获得这种数据格式步骤为,去网络上下载公开的地图数据(例如natureEarth等网站),使用GDAL提供的ogr2ogr工具,将shape类型文件转换为GeoJSONTopoJSON。除此之外,一些便捷的网站提供指定地区TopoJSON格式数据的下载,例如这里。总之,获取地图数据并转化为指定格式是一件不容易的事。

在本文的源码中,提供了中国地图的TopoJSON数据

3 关键代码

导入数据TopoJSON格式的地图数据

d3.json('./chinaTopo.json').then(function(data){
....

建立投影模型,将球面坐标转换为平面坐标

/* ----------------------------尺度转换------------------------  */
    const projection = d3.geoMercator()
                            .center([104, 38])
                            .scale(355)
                            .translate([chart.getBodyWidth()/2, chart.getBodyHeight()/2])

选取特征元素,这里需要用到topojson

/* ----------------------------准备数据------------------------  */

    const handleData = topojson.feature(data, data.objects['中国']).features;

运用d3.geoPath渲染地图轮廓

扫描二维码关注公众号,回复: 9300418 查看本文章
/* ----------------------------渲染地图轮廓------------------------  */
    chart.renderMap = function(){
        const path = d3.geoPath()
                        .projection(projection);

        let map = chart.body().selectAll('path')
                                .data(handleData);
            
            map.enter()
                 .append('path')
                 .attr('class', (d) => 'provinces ' + d.properties.name)
               .merge(map)
                 .attr('d', path)
                 .attr('fill', (d,i) => chart._colors(i % 10));

            map.exit()
                .remove();
    }

渲染省市中心

/* ----------------------------渲染省市中心点------------------------  */
    chart.renderCenter = function(){
        handleData.pop();  //去除数组最后一个非省市元素

        chart.body().selectAll('circle')
                        .data(handleData)
                        .enter()
                        .append('circle')
                        .attr('class', (d) => 'center-' + d.properties.name)
                        .attr('cx', (d) => {
                            return projection(d.properties.center)[0];
                        })
                        .attr('cy', (d) => {
                            return projection(d.properties.center)[1];
                        })
                        .attr('r', 2)
                        .attr('fill', 'red')
                        .attr('stroke', 'black');
    }

绑定鼠标交互事件,当鼠标悬停在指定区域的时候显示省信息

/* ----------------------------绑定鼠标交互事件------------------------  */
    chart.addMouseOn = function(){
        //防抖函数
        function debounce(fn, time){
            let timeId = null;
            return function(){
                const context = this;
                const event = d3.event;
                timeId && clearTimeout(timeId)
                timeId = setTimeout(function(){
                    d3.event = event;
                    fn.apply(context, arguments);
                }, time);
            }
        }

        d3.selectAll('.provinces')
            .on('mouseover', function(d){
                const e = d3.event;
                const position = d3.mouse(chart.svg().node());

                d3.select(e.target)
                    .attr('fill', config.hoverColor);
                
                chart.svg()
                    .append('text')
                    .classed('tip', true)
                    .attr('x', position[0]+5)
                    .attr('y', position[1])
                    .attr('fill', config.textColor)
                    .text(d.properties.name);
            })
            .on('mouseleave', function(d,i){
                const e = d3.event;
                
                d3.select(e.target)
                    .attr('fill', chart._colors(i%10));
                    
                d3.select('.tip').remove();
            })
            .on('mousemove', debounce(function(){
                    const position = d3.mouse(chart.svg().node());
                    d3.select('.tip')
                    .attr('x', position[0]+5)
                    .attr('y', position[1]-5);
                }, 6)
            );
    }

大功告成!!!

发布了250 篇原创文章 · 获赞 88 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/zjw_python/article/details/98847312
今日推荐