12. SVG and D3.js
Today's topics
SVG
D3.js
Drawing on browser
Canvas
p5.js
/runp5
SVG
d3.js
SVG (Scalable Vector Graphics)
Vector-based drawing system
Based on XML
Declarative definition of objects
Available on modern browsers
SGML
Standard Generalized Markup Language
Markup language for documents
Hierarchical text
Developed by IBM (1980)
HTML hierarchy
https://gyazo.com/95841b7a0e0c166fb72d3b3a788d2e73
SGML example
code:sgml
<!DOCTYPE memo PUBLIC "-//SuzukiCorp//DTD Memo//JP">
<memo>
<from>Kimiura</from>
<to>Tomita</to>
<date>2023/1/7</date>
<subject>Meeting schedule</subject>
<para>Today's meeiting is is at room 203.</para>
</memo>
HTML and XML
XML
Extention to SGML
Standard format for exchanging data
Markup language using user-defined tags
Developed by W3C in 2000?
HTML
Markup language for Web pages
Developed by Tim Berners=Lee
XML example
code:xml
<レシピ 名前="パン" 準備時間="5分" 調理時間="3時間">
<料理>基本的なパン</料理>
<材料 量='3' 単位='カップ'>小麦粉</材料>
<材料 量='0.25' 単位='オンス'>イースト</材料>
<材料 量='1.5' 単位='カップ' 状態="温かい">水</材料>
<材料 量="1" 単位="ティースプーン">食塩</材料>
<要領>
<手順>全ての材料を一緒にして混ぜます。</手順>
<手順>十分にこねます。</手順>
<手順>布で覆い、暖かい部屋で1時間そのままにしておきます。</手順>
<手順>もう一度こねます。</手順>
<手順>パン焼きの容器に入れます</手順>
<手順>布で覆い、暖かい部屋で1時間そのままにしておきます。</手順>
<手順>オーブンに入れて温度を180℃にして30分間焼きます。</手順>
</要領>
</レシピ>
SVG (Scalable Vector Graphics)
Extension to XML
SVG has been in development within the World Wide Web Consortium (W3C) since 1999 after six competing proposals for vector graphics languages had been submitted to the consortium during 1998 (see below).
Vector-based drawing system
Declarative definition
Runs on most browsers
SVG History
defined by W3C
1999/2/11 SVG draft published
2001/9/4 SVG 1.0
2003/1/14 SVG 1.1, SVG Tiny・SVG Basic
2008/12/22 SVG Tiny 1.2
2011/8/16 SVG 1.1 (Second Edition)
2018/10/4 SVG 2
SVG and other drawing systems
SVG
Define drawing objects
Declarative programming
Popular drawing systems
Canvas, OpenGL, X11, Quartz (Mac), PostScript, ...
Draw objects sequentially
Draw a line
Draw a rectangle
Clear the display
SVG info
/svg-wiki
Introduction to SVG
Drawing rectangles
code:rect.svg
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="320pt" height="223pt" viewBox="0 0 100 70"
xmlns="http://www.w3.org/2000/svg">
<rect x="5" y="5" width="70" height="40" fill="blue"/>
<rect x="15" y="15" width="70" height="40" fill="orange"/>
<rect x="25" y="25" width="70" height="40" fill="yellow"/>
</svg>
Result
rect.html
http://gyazo.com/3ac4f9f16144b0fea50f9a67c322969e.png
Showing SVG on Scrapbox
using svg-hosting.vercel.app
https://github.com/takker99/svg-hosting by @takker
https://svg-hosting.vercel.app/scrapbox.io/$project/$page/$filename
https://svg-hosting.vercel.app/scrapbox.io/sfc-vis2022/12._SVG_and_D3.js/rect.svg
https://svg-hosting.vercel.app/scrapbox.io/sfc-vis2022/12._SVG_and_D3.js/rect.svg
Drawing lines
Declare lines in HTML
code:line.svg
<svg width="400pt" height="300pt" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
<path d="M 100 100 L 300 100 L 200 300 z" fill="none" stroke="blue" stroke-width="3" />
<path d="M36,203L184,203L184,79L36,79" fill="none" stroke="red" stroke-width="3" />
</svg>
Result
http://gyazo.com/33d63493ee5dc57628610aa9e00a8e91.png
https://svg-hosting.vercel.app/scrapbox.io/sfc-vis2022/12._SVG_and_D3.js/line.svg
Animation
https://svg-hosting.vercel.app/scrapbox.io/sfc-vis2022/12._SVG_and_D3.js/animation.svg
code:animation.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<path d="M 25 175 L 25 25" stroke="black" stroke-dasharray="2"/>
<path d="M 175 25 L 175 175" stroke="black" stroke-dasharray="2"/>
<path d="M 25 25 L 175 25" stroke="black" stroke-dasharray="2"/>
<path d="M 25 175 Q 25 25 175 25" stroke="black" stroke-dasharray="2" fill="none"/>
<path d="M 25 25 Q 175 25 175 175" stroke="black" stroke-dasharray="2" fill="none"/>
<path d="M 25 175 C 25 25 175 25 175 175" stroke="blue" fill="none"/>
<path stroke="red">
<animate attributeName="d" calcMode="linear" from="M 25 175 L 25 25" to="M 25 25 L 175 25" begin="0s" dur="6s" repeatCount="indefinite"/>
</path>
<path stroke="red">
<animate attributeName="d" calcMode="linear" from="M 25 25 L 175 25" to="M 175 25 L 175 175" begin="0s" dur="6s" repeatCount="indefinite"/>
</path>
<circle fill="red" r="5">
<animateMotion path="M 25 175 Q 25 25 175 25" begin="0s" dur="6s" calcMode="linear" repeatCount="indefinite"/>
</circle>
<circle fill="orange" r="5">
<animateMotion path="M 25 25 Q 175 25 175 175" begin="0s" dur="6s" calcMode="linear" repeatCount="indefinite"/>
</circle>
<circle fill="red" r="5">
<animateMotion path="M 25 175 C 25 25 175 25 175 175" begin="0s" dur="6s" calcMode="linear" repeatCount="indefinite"/>
</circle>
</svg>
Showing an image
code:image.svg
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 570 500" width="570" height="500">
<image xmlns:xlink="http://www.w3.org/1999/xlink"
x="0" y="0" width="570" height="500"
xlink:href="data:png;base64,iVBORw0KGgoAAAANSUhEUgAA...">
</image>
</svg>
Handling screenshot images on SVG
https://nextpublishing.jp/book/13148.html https://gyazo.com/7d442e5c7569b3f8e4454aa12d4c7c8a
SVG and screenshots
SVG advantages
Integration with HTML
Tags (e.g. <a> can be embedded in SVG)
Animation
Interaction
Declarative notation
No need to redraw
SVG problems
Interaction and animation features may be overspec
SVG Native = simplified version
D3.js (Data-Driven Documents)
JavaScript visualization library
Developed by Mike Bostock at 2010
Use SVG and DOM
http://gyazo.com/de8d809e2d27f77f76300a6d854fb322.png
Mike Bostock
http://gyazo.com/f72348e5c77e7e3f484b6537137d4c1e.png
Current status of D3.js
Most popular visualization system on the Web
Integration with other frameworks
D3 + React
郊外住宅地の見えない空き家
https://web.archive.org/web/20160319155221/http://www.nhk.or.jp/d-navi/link/akiya/index.html http://gyazo.com/5bed14053463cb734b174c0902dd257d.png
Interactive Data Visualization for the Web
Information visualization with d3.js
http://gyazo.com/e16c6e41256a2e95dff2b2eea9389554.png
https://www.youtube.com/watch?v=yECYJbTwlWk
Sparkline example
code:sparkline.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>title</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<style type="text/css">
div.bar {
display: inline-block;
width: 20px;
height: 75px;
background-color: teal;
}
</style>
<script type="text/javascript">
var dataset = 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5;
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", function(d) {
var barHeight = d * 5; // 高さを 5 倍にします
return barHeight + "px";
});
</script>
</body>
</html>
Sparkline example
https://gyazo.com/7514bedd99ee0246581c331b8a7cb2e2
rund3
/Rund3
Run D3.js program on Scrapbox
Using GitHub pages
Specify a JS file and run
https://masui.github.io/rund3/?code=JS-URL
Pie chart
https://gyazo.com/18726f8b9d236749c38504e131def940
Run
code:d3sample1.js
var data = 10, 20, 30, 40;
var canvas = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 500);
var g = canvas.append("g")
.attr("transform", "translate(300, 300)");
//var arc = d3.svg.arc()
var arc = d3.arc()
.innerRadius(130)
.outerRadius(200);
var pie = d3.pie()
.value(function(d) { return d; });
var arcs = g.selectAll(".arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc");
var color = d3.scaleOrdinal()
.range("yellow", "brown", "orange", "blue");
arcs.append("path")
.attr("d", arc)
.attr("fill", function (d) { return color(d.data); });
arcs.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("text-anchor", "middle")
.attr("text-size", "10px")
.text(function(d) { return d.data; });
Bar chart
Run
code:graph.js
// 1. prepare data
var dataset = [
{ "name": "A", "value": 5 },
{ "name": "B", "value": 6 },
{ "name": "C", "value": 8 },
{ "name": "D", "value": 3 },
{ "name": "E", "value": 2 },
{ "name": "F", "value": 6 },
{ "name": "G", "value": 8 },
{ "name": "H", "value": 6 },
{ "name": "I", "value": 10 },
{ "name": "J", "value": 9 }
]
var width = 400; //
var height = 300; //
var padding = 30; // margin
// 2. specify SVG region
var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);
// 3. specify coordinate scale
var xScale = d3.scaleBand()
.rangeRound(padding, width - padding)
.padding(0.1)
.domain(dataset.map(function(d) { return d.name; }));
var yScale = d3.scaleLinear()
.domain(0, d3.max(dataset, function(d) { return d.value; }))
.range(height - padding, padding);
// 4. show coordinates
svg.append("g")
.attr("transform", "translate(" + 0 + "," + (height - padding) + ")")
.call(d3.axisBottom(xScale));
svg.append("g")
.attr("transform", "translate(" + padding + "," + 0 + ")")
.call(d3.axisLeft(yScale));
// 5. show bars
svg.append("g")
.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d) { return xScale(d.name); })
.attr("y", function(d) { return yScale(d.value); })
.attr("width", xScale.bandwidth())
.attr("height", function(d) { return height - padding - yScale(d.value); })
.attr("fill", "steelblue");
Circles
https://gyazo.com/4e3437b060a422db4c9714414912a652
Run
code:circles.js
var svg = d3.select("body").append("svg").attr("width", 500).attr("height", 100);
var dataset = 1, 2, 3, 4, 5;
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");
circles.attr("cx", function(d, i) {
return (i * 50) + 25;
})
.attr("cy", 50)
.attr("r", function(d) {
return 5*d;
})
.attr("fill", "yellow")
.attr("stroke", "orange")
.attr("stroke-width", function(d) {
return d;
});
Points
https://gyazo.com/faadffbc4cbc90730a03ae98b59973ef
Run
code:scatter.js
var svg = d3.select("body").append("svg").attr("width", 500).attr("height", 100);
var dataset =
[ 5, 20, 480, 90, 250, 50, 100, 33, 330, 95,
410, 12, 475, 44, 25, 67, 85, 21, 220, 88 ];
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) { return d0; })
.attr("cy", function(d) { return d1; })
.attr("r", 4);
Treemap
Run
https://wizardace.com/d3-treemap/
code:treemap.js
// 1. 描画用のデータ準備
var width = 800;
var height = 600;
var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);
var data = {
"name": "A",
"children": [
{ "name": "B", "value": 25 },
{
"name": "C",
"children": [
{ "name": "D", "value": 10 },
{ "name": "E", "value": 15 },
{ "name": "F", "value": 10 }
]
},
{ "name": "G", "value": 15 },
{
"name": "H",
"children": [
{ "name": "I", "value": 20 },
{ "name": "J", "value": 10 }
]
},
{ "name": "K", "value": 10 }
]
};
// 2. 描画用のデータ変換
root = d3.hierarchy(data);
root
.sum(function(d) { return d.value; })
.sort(function(a, b) { return b.height - a.height || b.value - a.value; });
var treemap = d3.treemap()
.size(width, height)
.padding(1)
.round(true);
treemap(root);
// 3. svg要素の配置
var g = d3.select("svg")
.selectAll(".node")
.data(root.leaves())
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x0 + "," + (d.y0) + ")"; });
g.append("rect")
.style("width", function(d) { return d.x1 - d.x0; })
.style("height", function(d) { return d.y1 - d.y0; })
.style("fill", function(d) {
while(d.depth > 1) d = d.parent;
return d3.schemeCategory10parseInt(d.value % 7);
})
.style("opacity", 0.6)
g.append("text")
.attr("text-anchor", "start")
.attr("x", 5)
.attr("dy", 30)
.attr("font-size", "150%")
.attr("class", "node-label")
.text(function(d) { return d.data.name + " : " + d.value; });
SDraw
https://github.com/masui/SDraw
Use D3.js for drawing
https://gyazo.com/6ab47e029ae216659a006578a433c065 http://www.pitecan.com/SDraw/sdraw.html
1000 D3 examples
https://gyazo.com/4fd22526469208fb49d280edbc724f0a
D3 examples
Treemap, Sunburst, etc.
https://gyazo.com/0ce5bf9f70ca6f12d3946ef661ca30e2
Scrap-Graph
Visualization of Scrapbox links
https://gyazo.com/750fcfca435be7c85e384ea47a7d9723
d3 Treemap
https://observablehq.com/@d3/treemap
http://gyazo.com/78195b75ea63a1f901f4986d35e40be8.png
d3 Sunburst
http://gyazo.com/8abce282d17e4875f6f389b4cf2abd91.png
c.f. Overdisk
http://gyazo.com/105523c43eea6892fba4a76694f5a5bc.png
Observable
Observable is a platform where you can collaboratively explore, analyze, visualize, and communicate with data on the web.
https://www.youtube.com/@Observablehq
https://gyazo.com/bd5d8b121bed56fb0826c0b8e8f06859
Using d3.js on Observable
https://observablehq.com/@d3
https://gyazo.com/07fbfcba720d49518e583100b486dd28
D3.js references
https://gyazo.com/a3535d8eb76508fc60f8ab3e43092a21 https://shimz.me/blog/d3-js/5022
Video: Design is a search problem
https://www.youtube.com/watch?v=fThhbt23SGM