最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to output SVG in a Jupyter notebook using jsdom, D3 and IJavascript - Stack Overflow

programmeradmin5浏览0评论

I'm not strong on frontend development but I have toyed around with a lot of Javascript and D3 recently. Being used to doing scientific analysis in Python using Jupyter Notebooks, I figured it should be possible to use a similar workflow for developing scientific visualizations with D3 using JS code in a Jupiter notebook with a JS kernel. I've looked at n-riesco's IJavascript project and it seems promising, but when trying to import D3 the notebook throws an error:

// npm install d3
var d3 = require('d3');

throws

ReferenceError: document is not defined

I'm guessing this is because there is no DOM in the Jupyter environment (because Mike Bostock says so). In fact if I import jsdom, D3 will also import successfully. Awesome! However, now, I cannot select anything because, well... I'm guessing because there is nothing to select in the Jupyter environment.

The things I would like to do is either something like:

$$svg$$ = "<svg><rect width=1000 height=1000/></svg>";
var svg = d3.select("svg")
// Beautiful D3 code

Or (less cool but also favorable), get a reference to the DOM of some local server, that I can then manipulate by executing code in the notebook.


Update

With the introduction of Observable, there is no longer any need to use JavaScript in Jupyter notebooks. Observable is an awesome JavaScript notebook environment that can pretty much do everything. For example, the thing I wanted to do when I asked this question, can be done as simply as:

I'm not strong on frontend development but I have toyed around with a lot of Javascript and D3 recently. Being used to doing scientific analysis in Python using Jupyter Notebooks, I figured it should be possible to use a similar workflow for developing scientific visualizations with D3 using JS code in a Jupiter notebook with a JS kernel. I've looked at n-riesco's IJavascript project and it seems promising, but when trying to import D3 the notebook throws an error:

// npm install d3
var d3 = require('d3');

throws

ReferenceError: document is not defined

I'm guessing this is because there is no DOM in the Jupyter environment (because Mike Bostock says so). In fact if I import jsdom, D3 will also import successfully. Awesome! However, now, I cannot select anything because, well... I'm guessing because there is nothing to select in the Jupyter environment.

The things I would like to do is either something like:

$$svg$$ = "<svg><rect width=1000 height=1000/></svg>";
var svg = d3.select("svg")
// Beautiful D3 code

Or (less cool but also favorable), get a reference to the DOM of some local server, that I can then manipulate by executing code in the notebook.


Update

With the introduction of Observable, there is no longer any need to use JavaScript in Jupyter notebooks. Observable is an awesome JavaScript notebook environment that can pretty much do everything. For example, the thing I wanted to do when I asked this question, can be done as simply as:

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Apr 19, 2017 at 6:51 Ulf AslakUlf Aslak 8,6384 gold badges39 silver badges59 bronze badges 1
  • 1 I love Observable too. I do wish you could run it locally—one thing Jupyter notebooks still has going for it. – russellmania Commented Jul 5, 2018 at 20:42
Add a ment  | 

2 Answers 2

Reset to default 5

Let me give first a working example (tested on [email protected], [email protected] and [email protected]) and then some clarifications:

var jsdom = require("jsdom");
global.document = jsdom.jsdom();

var d3 = require("d3");

var svg = d3.select(document.body).append("svg");

svg.append("rect")
    .attr("width", 80)
    .attr("height", 80)
    .style("fill", "orange");

$$.svg(svg.node().outerHTML);

This solution:

  • uses the DOM provided by jsdom.

  • uses d3 to create an <svg> node and append a <rect>

  • uses outerHTML to get the string representation of the <svg> node created in the previous steps

  • and finally instructs IJavascript to return this string to the Jupyter notebook as an SVG result.

In theory, IJavascript could inject javascript code into the Jupyter notebook (to manipulate its DOM), but this code may not run (depending on the security policies of the Jupyter frontend).


Since your interest is scientific analysis, you may be interested in a module I published recently: ijavascript-plotly.


I know this answer skims through many concepts. Please, use the ments below, if you need me to update the answer and explain anything further.

A similar approach to render D3 in Jupyter:

var d3 = require("d3");
var jsdom = require("jsdom");

var dom = new jsdom.JSDOM("<svg></svg>",{QuerySelector:true});

var svg = dom.window.document.querySelector("svg");

d3.select(svg)
    .append("rect")
    .attr("width", 80)
    .attr("height", 80)
    .style("fill", "orange");

$$.html(dom.serialize());
发布评论

评论列表(0)

  1. 暂无评论