d3.js本来主要是用于用“数据驱动dom”,在浏览器端,接收后端数据,数据绑定,渲染出svg。

即使是在ng中用,也是会由框架打包,供客户端下载。

那么,如果用所谓后端渲染,发布静态的svg,那就要在node里用d3。

几个遇到的点:

1 d3+jsdom实现后端渲染svg

node和前端的区别,就是没有全局window.document 这个对象。d3选择器无从选起。

1 创建jsdom对象

const { JSDOM } = require("jsdom");

const my_jsdom = new JSDOM(
`
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
</body>
</html>
`, {
resources: 'usable'
}
);

反引号中是一个空白网页模板,用过flask的jinja2 和ng的 templates的不会陌生,模拟浏览器里的window.document全局对象。

2 导入d3模块,并让d3获得这个模拟的网页。

//按需导入d3
var d3 = Object.assign({}, require("d3-selection"), require("d3-selection-multi"), require("d3-geo"));
//导入模拟的geojson数据
import {default as gdf} from './mock_polygon_gdf.json'; //让d3绑定到模拟的网页
const d3n = d3.select(my_jsdom.window.document); const svg = d3n.select('body')
.insert('svg','records')
.attr('width', 2400)
.attr('height', 3000);
.append('g')
.selectAll('path')
.data(gdf['features'])
.enter()
.append('path')
.attr("d", d3.geoPath()

写这么长,是想说明,注意绑定当前网页后的对象命名为d3n, 不要和开始导入的d3库混淆。

在浏览器里,d3是通过html里写另外一个<script>引入d3.min.js  直接都导入好了,而且是直接d3.select('body')的。

在node这里加了一步,而且后面主要是用d3n来做后面的工作。

前面导入的d3库对象,也是有用的。比如后面的d3.geoPath()方法

经过这样的d3一顿绑定,svg画好了。还差最后一步:

3把网页输出成string,保存到.html文件

const content = my_jsdom.serialize();

fs.writeFile('${fpath}/${fname}.html', content, { encoding: "utf8", flag: "w" }, (err) =>{ 
if (err) {
throw err;
}
});

2. 按需分模块导入d3 子module

d3发展到v4 v5之后,功能膨胀,体积变大,除了集中发布的d3 还分离成若干独立子组件,可以按需加载。

而且,有些子组件并没有打包到d3中,必须自己手动安装,按需加载

根据d3官网,node中按需加载是这样的:https://github.com/d3/d3/blob/master/README.md

In Node:

var d3 = require("d3");

You can also require individual modules and combine them into a d3 object using Object.assign:

var d3 = Object.assign({}, require("d3-format"), require("d3-geo"), require("d3-geo-projection"));

用Object.assign() 打包成一个d3对象

3 一次为selection添加多个attr

特别是不知道attr具体名字,但attr的{name:value}都在需要绑定的数据中的时候

要用到独立于d3的子组件d3-selection-multi

按上面的方式,分组导入(我只用到3个,d3-selection必选,d3-geo是为了绑定geojson)

var d3 = Object.assign({}, require("d3-selection"), require("d3-selection-multi"), require("d3-geo"));

这样就可以:

    const enter = g.selectAll('path')
.data(gjson['features'])
.enter()
.append('path')
.attrs(
(d)=> Object.assign({id: (d) => d['id']}, d['properties'])
);
通过assign拼接,把id 和 properties中的全部属性,都作为dom node的 attribute 一句话给添加好。这确实是比用py里的svgwrite方便很多的,很优雅,要是py里能这么调用d3,该多好啊!
 

4 绑定geojson格式数据

用d3-geo,把一切geometry统统转成svg里的path, 且path的 d字段自动完成,非常优雅。https://github.com/d3/d3-geo#paths
尤其是polygon ->path,  避免自己去 写d M L Z 多次拼接,虽然自己写代码也不长,但是毕竟能偷懒就偷懒:
    const enter = g.selectAll('path')
.data(gjson['features'])
.enter()
.append('path')
.attr("d", d3.geoPath());

通过数据绑定,enter新增数据,添加path,直接一句搞定。

5 d3选择集上消失的update()方法,改用merge()

《精通D3.js》里介绍的data数据绑定后,都是enter() update() exit()三件套。
但现在,v5了,selection上没有update()方法了。
官网有人报issue

给出的答案是用merge,确实更优雅了

把enter和update合并处理了

// Perform the data join and obtain the update selection.
const option = d3.select("#mySelect")
.selectAll("option")
.data(optionsData); // Append the entering nodes, and obtain the enter selection.
const enter = option.enter().append("option"); // Merge entering and updating nodes to apply some operations to both.
enter.merge(option)
.property("value", d => d.value)
.text(d => d.label); // Remove the exiting nodes.
option.exit().remove();

d3 + geojson in node的更多相关文章

  1. D3.js部署node环境开发

    总结一段D3.js部署node环境的安装过程 准备阶段: 首先电脑上要安装node环境,这个阶段过滤掉,如果node环境都不会装,那就别玩基于node环境搞的其他东西了. 搭建环境: 我在自己的F:系 ...

  2. D3.js学习记录 - 数据类型【转】【新】

    1.变量 JAVASCRIPT的变量是一种类型宽松的语言.定义变量不用指定数据类型.而且还是动态可变的. var value = 100;value = 99.9999;value = false;v ...

  3. D3 JS study notes

    如何使用d3来解析自定义格式的数据源? var psv = d3.dsvFormat("|"); // This parser can parse pipe-delimited t ...

  4. [D3] Build an Area Chart with D3 v4

    Similar to line charts, area charts are great for displaying temporal data. Whether you’re displayin ...

  5. [D3] Build a Line Chart with D3 v4

    Line charts are often used to plot temporal data, like a stock price over time. In this lesson we’ll ...

  6. [D3] Build a Scatter Plot with D3 v4

    Scatter plots, sometimes also known as bubble charts, are another common type of visualization. They ...

  7. [D3] Build a Column Chart with D3 v4

    Column and bar charts are staples of every visualization library. They also make a great project for ...

  8. [D3] Make D3 v4 Charts Responsive with the viewBox attribute

    Making SVGs responsive is unfortunately not as simple as adding some media queries. This lesson intr ...

  9. d3.js制作连线动画图和编辑器

    此文章为原创文章,原文地址:https://www.cnblogs.com/eagle1098/p/11431679.html 连线动画图 编辑器 效果如上图所示.本项目使用主要d3.jsv4制作,分 ...

随机推荐

  1. ELK学习笔记之F5-HTTP-requesting-logging logstash filter

    input { tcp { port => 514 type => 'f5-request' } } filter { if [type] == "f5-request" ...

  2. DBeaver数据库管理工具连接Sybase数据库

    DBeaver数据库管理工具连接Sybase数据库 1. 下载DBeaver 官方网站:http://dbeaver.jkiss.org/ DBeaver5.3.1解压缩版(不用安装和配置):http ...

  3. CRC、MD5和SHA1的区别?

    什么是CRC校验?CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能,对数据进行多项式计算,并将 ...

  4. python简说(二十九)线程,进程

    进程: 一些资源的集合. 一个进程里面最少有一个线程,主线程.线程: 程序执行的最小单位. import threadingfrom threading import Threadimport tim ...

  5. 20165310 NstSec2019 Week1 Exp0 Kali安装

    20165310 NstSec2019 Week1 Exp0 Kali安装 Kali下载与安装 进入Kali官网 ,进入Download选项,选择Kali Linux 64 bit VMware VM ...

  6. Junit 的Assertions的使用

    import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.anyOf; import ...

  7. FJNU2018低程A 逃跑路线(Lucas + 中国剩余定理 + LGV定理)题解

    题目描述 n个人在w*h的监狱里面想要逃跑,已知他们的同伙在坐标(bi,h)接应他们,他们现在被关在(ai,1)现在他们必须要到同伙那里才有逃出去的机会,这n个人又很蠢只会从(x,y)->(x+ ...

  8. Activit工作流学习例子

    看了网上一些文章,动手操作了一遍,终于学会了Activit的一些常规使用. 一.Eclipse中的Activiti插件安装 Activiti有一个Eclipse插件,Activiti Eclipse ...

  9. cron,linux定时脚本

    Linux的cron和crontab Cron定时执行工具详解 Linux下的crontab定时执行任务命令详解 Linux上启动Cron任务 [linux]解析crontab cron表达式详解 c ...

  10. Shell脚本(三)

    摘自:菜鸟教程 http://www.runoob.com/linux/linux-shell-echo.html Shell命令 1. echo命令 字符串输出 echo "OK! \c& ...