Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
D3.js 資料視覺化入門
Search
Kuro Hsu
December 23, 2015
Technology
2
230
D3.js 資料視覺化入門
2015/12/23 @ 朝陽科技大學
Kuro Hsu
December 23, 2015
Tweet
Share
More Decks by Kuro Hsu
See All by Kuro Hsu
Laravel x Vite
kurotanshi
0
610
[.NET Conf 2020 Taiwan] 以輕前端視角進入 Vue 3.0 的世界
kurotanshi
0
680
[MOPCON 2020] vite: Make web dev fast again
kurotanshi
0
2.3k
[ModernWeb'20] Vue.js :The Bad Parts
kurotanshi
1
95
[MOPCON 2019] Vue.js 3.0 與 Composition API 的變革
kurotanshi
1
1.2k
[JSDC2019] 我有一堆選擇 Vue 開發框架的理由
kurotanshi
1
710
[COSCUP 2019] 前端工程師的養成之路與開源工具
kurotanshi
3
380
初探 Vue 3.0 Function API
kurotanshi
4
2.9k
VueJS Style Guide 導讀
kurotanshi
6
1.8k
Other Decks in Technology
See All in Technology
初心者向けAWS Securityの勉強会mini Security-JAWSを9ヶ月ぐらい実施してきての近況
cmusudakeisuke
0
120
Taming you application's environments
salaboy
0
180
iOS/Androidで同じUI体験をネ イティブで作成する際に気をつ けたい落とし穴
fumiyasac0921
1
110
誰も全体を知らない ~ ロールの垣根を超えて引き上げる開発生産性 / Boosting Development Productivity Across Roles
kakehashi
1
220
[CV勉強会@関東 ECCV2024 読み会] オンラインマッピング x トラッキング MapTracker: Tracking with Strided Memory Fusion for Consistent Vector HD Mapping (Chen+, ECCV24)
abemii
0
220
テストコード品質を高めるためにMutation Testingライブラリ・Strykerを実戦導入してみた話
ysknsid25
7
2.6k
透過型SMTPプロキシによる送信メールの可観測性向上: Update Edition / Improved observability of outgoing emails with transparent smtp proxy: Update edition
linyows
2
210
[FOSS4G 2024 Japan LT] LLMを使ってGISデータ解析を自動化したい!
nssv
1
210
TypeScript、上達の瞬間
sadnessojisan
46
13k
Terraform CI/CD パイプラインにおける AWS CodeCommit の代替手段
hiyanger
1
240
VideoMamba: State Space Model for Efficient Video Understanding
chou500
0
190
Adopting Jetpack Compose in Your Existing Project - GDG DevFest Bangkok 2024
akexorcist
0
100
Featured
See All Featured
Measuring & Analyzing Core Web Vitals
bluesmoon
4
120
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.4k
Docker and Python
trallard
40
3.1k
Become a Pro
speakerdeck
PRO
25
5k
Building Your Own Lightsaber
phodgson
103
6.1k
Ruby is Unlike a Banana
tanoku
97
11k
Code Review Best Practice
trishagee
64
17k
Building an army of robots
kneath
302
43k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
28
2k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
27
4.3k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Transcript
Kuro Hsu @ ๖檚ᑀದय़䋊 D3.js 虻碘憙憽玕獈槹 2015/12/23
ᛔ౯Օ奧 Kuro Hsu • 獮ᒒૡ纷䒍 @ 睃瞆叨褸㿁 • COSCUP 拻ᘏ
• JSDC 拻ᘏ • kurotanshi [at] gmail.com • http://kuro.tw
̿ض獨ᓕ D3 ԧ牧֦肯螂虻懱憙憽玕㻟牫̀ 磪䷱磪Օ奧 D3.js 墋䁭ጱᒫӞ殷疰ݞՈ獨ᓕ D3 ጱ獌ܠ
ݶ䰬ฎ Web 懿袅獤ຉ牧ߺ㮆ฃ睞牫
ݶ䰬ฎ Web 懿袅獤ຉ牧ߺ㮆ฃ睞牫
傶Ջ讕襑ᥝ疥虻懱憙憽玕 • य़ᰁ虻碘ݢࣁ縣樌ᤩቘ薹牧虻懱㯽螏ๅ磪硳ሲ • 磪ۗෝ薪疗ڊٌ犢珊匍ොୗ犋ฃ疗憽کጱ虻碘粬 • ݢ犥盄ฃ፡ڊ虻碘蛪ጱቭ綦膏梊藮 • ֵአٌ犢承ጱ捝ᘏ犖胼ฃ፡睞
None
None
None
蕣֢虻懱瑽蔭ጱᥝᔰ • ก嘦ጱԆ氂 • 虻懱羊墋玕牧Ԇ氂ๅ统ڊ • 殼䛑憙憽㵕娄牧珅捝ᘏፓط • 篷襑ਁ藯ก犖胼ቘ薹
None
http://d3js.org/ Demo: https://goo.gl/idrDMt
None
* svg 媑瑽襑ᥝ IE9+
• D3 = Data-Driven Documents. • ֵአ翕殷秂伛ದ蔩 (HTML / CSS
/ JavaScript / SVG) • 䔶य़ጱ Data-Driven 疥虻碘䌘䛑ک DOM Ӥ牧۱ೡزᔰ ጱी㳫现痀虋玕 • ׀ SVG ፘ橕媑瑽ૡٍ䓚牧蒈圸 SVG ኴጱ jQuery • 䕃᩻य़֕䋿֢斃ٌ犢憙憽玕ૡٍ耆卓 D3.js ฎՋ讕
螡䢔瑊膏 DOM 砺֢
螡䢔瑊 JavaScript jQuery D3.js document.querySelectorAll(".block") $(".block") d3.selectAll(".block")
螡䢔瑊 d3.select("body").selectAll(".block") d3.selectAll("body .block")
ොဩ袽 (method chaining) var box = d3.selectAll('.box'); box.style('color', '#f00');
box.text('Hello World!'); var box = d3.selectAll('.box') .style('color', '#f00') .text('Hello World!');
痀 (attr) // attr() d3.selectAll("circle") .attr("cx", 50) .attr("cy", 50)
.attr("r", 25) .style("fill", "red");
痀 (attr) // 犥̿ᇔկ̀ጱොୗ瞲ਧ痀 d3.selectAll("circle") .attr({ "cx": 50, "cy":
50, "r": 25 }) .style("fill", "red"); // 玲 circle cx 痀ጱ独 d3.select("circle").attr("cx");
痀 (property) d3.selectAll('.name') .property('value', 'Kuro'); አဩ膏 attr() ፘݶ牧֕
property() ֵአࣁ篷ਁᶎ瞲ਧጱ痀牐 ই: disabled, checked 犥现 value 缛牐 d3.selectAll('.name') .property('disabled');
class d3.selectAll('.block') .classed('item', true); d3.selectAll('.block') .classed('item', false);
d3.selectAll('.block') .classed('item big', true);
styles d3.selectAll('.block') .style('color', '#f00'); d3.selectAll('.block') .style({ 'color':
'#f00', 'font-size': '15px' });
text & html var foo = d3.selectAll('.foo'); foo.text('Hello World!'); foo.html('<div
class="bar">Hello</div>');
ℂ虻碘ک瑽猟زᔰ
Data - ಅ磪ጱ虻碘᮷ฎ檋ڜ var data = [1, 3, 5, 2,
4, 6, 8, 10];
Data - ಅ磪ጱ虻碘᮷ฎ檋ڜ jsbin.com/kifihirugu var data = [ {x: 10.0,
y: 9.14}, {x: 8.0, y: 8.14}, {x: 13.0, y: 8.74}, {x: 9.0, y: 8.77}, …… ];
key function var data = [ { 'name': 'kuro', 'age':
30 }, { 'name': 'John', 'age': 20 }, { 'name': 'Mary', 'age': 18 } ]; var p = d3.select('body') .selectAll('p') .data(data) .enter() .append('p') .text(function(d, i) { return d.name + ': ' + d.age + '䵇'; });
None
Enter, Update, Exit Pattern var data = [1, 2,
3, 4, 5]; d3.select('body') .selectAll('div') .data( data ) .enter() .append('div') .text(function(d, i){ return d; }); 1 2 3 4 5
Enter, Update, Exit Pattern data = [1, 3, 5,
7, 9]; d3.select('body') .selectAll('div') .data( data ) .text(function(d, i){ return d }); 1 3 5 7 9
Enter, Update, Exit Pattern data = [10, 20, 30]; d3.select('body')
.selectAll('div') .data( data ) .exit() .remove(); 1 3 5 7 9
Enter, Update, Exit Pattern data = [10, 20, 30]; d3.select('body')
.selectAll('div') .data( data ) .exit() .remove(); 1 3 5 7 9 ?
Enter, Update, Exit Pattern data = [10, 20, 30]; d3.select('body')
.selectAll('div') .data( data ) .text( function(d, i){ return d; }) .exit() .remove(); 10 20 30 7 9
None
SELECTION Datas Enter & Update Exit & Remove SELECTION
Enter: Data > Elements. Update: Data = Elements. Remove: Data
< Elements.
Ajax with D3 d3.json([URL], function(error, data){ if (error) return console.warn(error);
// do something }); d3.csv([URL]).get(function(error, data){ // do something });
穉ֺ疳膏ଷ秂數
d3.scale.linear().domain().range() 補間⽅法 輸入範圍 輸出範圍
Domain Range
穉ֺ疳 0 1000 0 100 500 50 Domain Range
var d3Scale = d3.scale.linear() // linear .domain([0, 1000]) //
㯽獈塅瑻 .range([0, 100]); // 蜍ڊ塅瑻 console.log( d3Scale(500) ); // 50 console.log( d3Scale(123) ); // 12.3 穉ֺ疳
var colorScale = d3.scale.linear() .domain([0, 20]) .range(["#f00", "#0f0"]); for (var
i = 0; i < 21; i++) { body.append('div') .style('background-color', colorScale(i)); }
var widthScale = d3.scale.linear() .domain([0, 12]) .range(["0px", "720px"]); for (var
i = 0; i < 13; i++) { body.append('div').text( widthScale(i) ); }
var red = d3.rgb(255,0,0); var green = d3.rgb(0,255,0); var compute
= d3.interpolate(red, green); console.log( compute(0) ); // #ff0000 console.log( compute(0.3) ); // #b34d00 console.log( compute(0.5) ); // #808000 console.log( compute(0.7) ); // #4db300 console.log( compute(1) ); // #00ff00
var a = "50px"; var b = "1000px"; var compute
= d3.interpolate(a, b); console.log( compute(0) ); // 50px console.log( compute(0.3) ); // 335px console.log( compute(0.5) ); // 525px console.log( compute(0.7) ); // 715px console.log( compute(1) ); // 1000px
d3.scale.category10() d3.scale.category20() d3.scale.category20b() d3.scale.category20c()
ଷ秂數
數娄 var data = [0, 150, 200, 300, 500, 1000];
// x 數 scale 穉ֺ疳 var xScale = d3.scale.linear() .domain(d3.extent(data)) // [0, 1000] .range([0, 500]); // x-range አ㬵蔭纈疝ଶ // y 數 scale 穉ֺ疳 var yScale = d3.scale.linear() .domain(d3.extent(data)) // [0, 1000] .range([0, 300]); // y-range አ㬵蔭纈ṛଶ
數娄 // x 數 var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom");
// ڰଶ֖ᗝ // y 數 var yAxis = d3.svg.axis() .scale(yScale) .orient("left"); // ڰଶ֖ᗝ
數娄 蝚螂 orient() 矒ګ數娄ොݻ现ڰଶ֖ᗝ
Ticks - ڰଶ jsbin.com/cuvubiwipo // x 數 var xAxis =
d3.svg.axis() .scale(xScale) .orient("bottom") .ticks(15) // 瞲ਧڰଶ碍ᰁ, 㻌֖ .tickFormat(function(d){ return d + "px"; }); // y 數 var yAxis = d3.svg.axis() .scale(yScale) .orient("left");
裾礿瑽
㾼讨瑽
穥ု瑽 http://jsbin.com/yepapa
螂䁰㵕向 SELECTION.transition() .duration(1000) // 㵕向䁆ᤈ碻樌 .delay(1000) // 皤螛 .ease( ...
) // Easing 獢碍 .attr({ 'transform': function(d){ ....... } }); *D3.js Easing Checker - http://bl.ocks.org/hunzy/9929724
螂䁰㵕向 SELECTION.transition() .duration(1000) .each('start', function(){ … }) // 㵕向樄ত獮䁆ᤈ .attr({
… }) .each('end', function(){ … }); // 㵕向奾盅䁆ᤈ
ے獈Ԫկ SELECTION.on('click', function(){ alert('Hello D3!'); }); SELECTION.on('click', null);
ے獈Ԫկ SELECTION.on('click.event1', function(){ alert('Hello D3 event 1'); }); SELECTION.on('click.event2', function(){
alert('Hello D3 event 2'); });
穥ု瑽ےӤ㵕向硳ຎ
SVG च器
SVG 讨檋ୗ瑽粙婘硯碻䨝叨ኞ०፥硳䛑 source: http://www.cs.cmu.edu/~chuck/lennapg/lenna.shtml
SVG ݻᰁୗ瑽粙ኧӞ蝫Ԁଷ秂懯ᓒ奲౮牧硯ٚय़犖犋ொ source: http://komica.chiisana.net/vector/src/1205520731301.svg
rect <rect x="20" y="20" width="150" height="100" rx="0"></rect>
circle <circle cx="55" cy="55" r="50"></circle>
line <line x1="10" y1="30" x2="230" y2="60"></line> x1, y1 x2, y2
text <text x="0" y="0" dx="0" dy="0" font-size="50" text-anchor="start"> Hello
</text> text-anchor="[start/middle/end]"
text - tspan <text x="0" y="20" style="font-size: 17px;"> <tspan>Hello,
</tspan> <tspan fill="red">World </tspan> </text>
text - tspan <text x="0" y="20" style="font-size: 17px;"> <tspan
x="10" dy="10">Hello, </tspan> <tspan x="10" dy="20">World </tspan> </text>
g (group) <g transform="rotate(45 50 50)"> <line> … </line> <rect>
… </rect> <text> … </text> </g>
path • 犨娄ྦྷጱ奲ݳ牧ಅ磪瑽୵᮷向ڊ㬵 • d 痀物Ӟᗭ̿瞲犤̀+̿ଷ秂̀ጱ奲ݳ
path • ᑏ㵕: M (MoveTo) • ፗ娄: L (LineTo) /
H (Horizontal) / V (Vertical) • ใ娄: C (CurveTo) / S (Shorthand/Smooth CurveTo) Q (Quadratic Bezier CurveTo) T (smooth quadratic Bezier CurveTo) • 皭娄: A (elliptical Arc) • 樂ݳ: Z (close-path)
path <line x1="10" y1="50" x2="390" y2="130"> <path d="M10,50L390,130">
娄ྦྷ叨ኞ瑊 - d3.svg.line var linePath = d3.svg.line(); var data =
[[10,50], [390, 130]]; svg.append('path') .attr('d', linePath(data)); <path d="M10,50L390,130">
娄ྦྷ叨ኞ瑊 - d3.svg.line var svg = d3.select('.svg'); var linePath
= d3.svg.line() .x(function(d, i){ return d; }) .y(function(d, i){ return (i%2 === 0) ? 40 : 120;}) var data = [40, 80, 120, 160, 200, 240, 280, 320, 360]; svg.append('path') .attr({ 'd': linePath(data) });
ರ娄瑽
d3.svg.line() .x(…).y(…) .interpolate("linear"); .interpolate("linear-closed"); .interpolate("basis"); .interpolate("cardinal"); .interpolate("step"); https://github.com/mbostock/d3/wiki/SVG-Shapes#user-content-line_interpolate
ರ娄瑽 - 虋୵
ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc
ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc var myArc1 = { "startAngle": 0, "endAngle":
Math.PI }; var myArc2 = { "startAngle": Math.PI, "endAngle": Math.PI * 1.5 }; var myArc3 = { "startAngle": Math.PI * 1.5, "endAngle": Math.PI * 2 };
ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc var arc = d3.svg.arc() .innerRadius(50) .outerRadius(150); svg.append('path')
.attr({ 'd': arc(myArc1) });
ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc
ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc http://community.yungching.com.tw/Building/9443
ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc
Responsive with D3
www.nytimes.com/interactive/2015/06/17/world/middleeast/map-isis-attacks-around-the-world.html
www.nytimes.com/interactive/2015/06/17/world/middleeast/map-isis-attacks-around-the-world.html
Responsive with D3
Responsive with D3 // 疥疳ੑ硬౮ܨ碻玲ጱ疝ṛ width = parseInt(d3.select(".content").style("width")) -
margin*2; height = parseInt(d3.select(".content").style("height")) - margin*2; // 䌃稴ጱ疝ṛ var margin = 40, width = 960 - margin*2, height = 500 - margin*2;
var svg = d3.select('.svg'); // 疥媑蕣㵕֢۱蕕ᛗ function 獉 function
rendering() { // 疥媑蕣ጱ纷ୗ嘨蝢蝢砆ک愊ᶎ // ኼ } // 疥 window 翉ਧ resize Ԫկ牧㪔᯿碝媑蕣瑽ࣳ d3.select(window).on('resize', rendering); // Ḓ稞媑蕣 rendering();
None
// resize 碻, 㵕眲ๅ碝 x, y 數ڰଶ, ๅ螕ݳ褂捝 var yAxis
= d3.svg.axis() .scale(yScale2) .orient("left") .ticks( Math.max(height/50, 2) ); Responsive with D3
None
Responsive with D3 • य़ग़碍ᤈ㵕蕕ᗝ䌘 SVG ඪൔ臑অ • ݻᰁ瑽୵牧婘硯犋०፥ •
㵕向 / زᔰ螂ग़碻ฃ磪硳胼㺔氂 • 犋ฎ犨֜瑽୵᮷螕ݳࣁಋ秚Ӥ氥纈物 狶 RWD ฎݚ狶Ӟ㮆ಋ秚粚牫
d3 Layouts
D3.js Layouts • d3.js ׀ԧ 11 圵粚ࣳ (layouts) • ݝ襑׀扗粚ࣳ瞲ਧጱ虻碘໒ୗ疰ݢ犥ፗ矑ॺአ
• layouts 蛪犋׀媑瑽ۑ胼牧ᘒฎ疥ܻতጱ虻碘 旉矦౮螕ݳᤩ d3 媑瑽ጱ虻碘໒ୗ • 睱懯ᓒ top, left, d 缛缛痀ጱ碻狡粬獨অአ
Pie Layout
Pie Layout - Ӟᑁ虋綎綎瑹
Chord Layout 2015 ᒫӞ䌵Ӯኴ12䔶༉純搴 A 奲毆搴䌘䜗奾ຎ
Chord Layout ݣ傀 ݘ૬ 艰葦 ے೭ य़ ူग़ 讝ݱ 嬝य़ڥ
ݣ傀 - 4 4 8 4 7 ݘ૬ 1 - 6 1 8 2 艰葦 7 5 - 1 11 16 ے೭य़ 9 5 3 - 2 4 ူग़ 讝ݱ 7 7 7 0 - 7 嬝य़ڥ 1 1 1 0 1 -
Chord Layout
Chord Layout
Chord Layout
Chord Layout
Hierarchy Layout 塅ֺ虻碘: 2014 ݣ玖૱裾螡膐ݱᤈ硰玟ಭ纏翄懯
Partition Layout
Partition Layout // 疥ኞ౮অጱ nodes 蝚螂 data() 癲獈 var gRects
= svg.selectAll("g").data(nodes).enter().append("g"); // ے獈 rect gRects.append("rect").attr({ ... }).style({ ... }); // ے獈ਁ gRects.append("text").attr({ ... }).style({ ... }); // 縷୵褩䍅瑽: d3.layout.partition() // size 瞲ਧ瑽礯य़ੜ, ڥአ .nodes 癲獈虻碘 var nodes = d3.layout.partition() .size([600, 400]) // [width, height] .nodes(data);
Partition Layout
Partition Layout // 㾼୵褩䍅瑽: d3.layout.partition() // size 瞲ਧ瑽礯य़ੜ, ڥአ .nodes
癲獈虻碘 var nodes = d3.layout.partition() .size([2 * Math.PI, radius * radius]) .nodes(data); // d3.svg.arc 蕣֢皭୵ var arc = d3.svg.arc() .startAngle(function (d) { return d.x; }) .endAngle(function (d) { return d.x + d.dx; }) .innerRadius(function (d) { return Math.sqrt(d.y); }) .outerRadius(function (d) { return Math.sqrt(d.y + d.dy); });
http://bl.ocks.org/mbostock/1256572
捝ᘏ蚤֦మጱ犋Ӟ䰬 ইຎ獉瑹դ蔭 100牧 क़瑹䨝ฎग़牫
捝ᘏ蚤֦మጱ犋Ӟ䰬 500 1500
捝ᘏ蚤֦మጱ犋Ӟ䰬 500 1500 1500 500
憙憽玕犋ฎ磪瑽疰অ 瑽粙㬵რ物 https://www.facebook.com/forpeople/photos/a. 989035831154301.1073741835.153819538009272/989036197820931/
憙憽玕犋ฎ笖犝疰অ (睃瞆լ翕ᤈ眐毱螇) (礓瞆լ翕ᒊ)
窾窫憙肯
ై螡Ԇ氂
ై螡Ԇ氂 0 200000000000000000000 400000000000000000000 600000000000000000000 800000000000000000000 1000000000000000000000 ྎॠ聲䒍 碝ڥ
None
http://p.udn.com.tw/upf/newmedia/2015_data/20150930_udntyphoon/udntyphoon/index.html
None
http://blog.infographics.tw/
None
– Randy Krum, Author of Cool Infographics. ̿፡ک牧疰睞ԧ牐̀
Q & A
• Kuro Hsu • Demo code: https://github.com/kurotanshi/d3js-samples • kurotanshi [at]
gmail.com • http://kuro.tw Thanks!