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
600
[.NET Conf 2020 Taiwan] 以輕前端視角進入 Vue 3.0 的世界
kurotanshi
0
660
[MOPCON 2020] vite: Make web dev fast again
kurotanshi
0
2.3k
[ModernWeb'20] Vue.js :The Bad Parts
kurotanshi
1
90
[MOPCON 2019] Vue.js 3.0 與 Composition API 的變革
kurotanshi
1
1.2k
[JSDC2019] 我有一堆選擇 Vue 開發框架的理由
kurotanshi
1
700
[COSCUP 2019] 前端工程師的養成之路與開源工具
kurotanshi
3
380
初探 Vue 3.0 Function API
kurotanshi
4
2.9k
VueJS Style Guide 導讀
kurotanshi
6
1.7k
Other Decks in Technology
See All in Technology
Envoy External AuthZとgRPC Extensionを利用した「頑張らない」Microservices認証認可基盤
andoshin11
0
250
「自動テストのプラクティスを効果的に学ぶためのカードゲーム」 ( #sqip2024 )
teyamagu
PRO
2
180
GC24 Recap: Interface Internals
task4233
0
150
Next.js のページ遷移を全力で止める
ypresto
7
3.3k
Fediverse Discovery Providers overview
andypiper
0
170
Oracle Autonomous Database:サービス概要のご紹介
oracle4engineer
PRO
1
7.1k
開発生産性を始める前に開発チームができること / optim-improve-development-productivity.pdf
optim
0
110
やってやろうじゃないかメカアジャイル! / Let's do it, mechanical agile!
psj59129
1
670
効果的なオンコール対応と障害対応
ryuichi1208
6
3.1k
内製化を目指す事業会社が、システム開発会社と共に進める「開発生産性改善」の取り組み事例 #devsumi
yuwji
0
100
社内の学びの場・コミュニティ形成とエンジニア同士のリレーションシップ構築/devreljapan2024
nishiuma
3
290
React Aria で実現する次世代のアクセシビリティ
ryo_manba
4
1.2k
Featured
See All Featured
How to name files
jennybc
75
98k
The Illustrated Children's Guide to Kubernetes
chrisshort
47
48k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
131
32k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
227
52k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
502
140k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
24
610
How GitHub Uses GitHub to Build GitHub
holman
472
290k
Learning to Love Humans: Emotional Interface Design
aarron
270
40k
Building an army of robots
kneath
302
42k
Code Review Best Practice
trishagee
62
16k
Keith and Marios Guide to Fast Websites
keithpitt
408
22k
Reflections from 52 weeks, 52 projects
jeffersonlam
346
20k
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!