Slide 1

Slide 1 text

Kuro Hsu @ ๖檚ᑀದय़䋊 D3.js 虻碘憙憽玕獈槹 2015/12/23

Slide 2

Slide 2 text

ᛔ౯Օ奧 Kuro Hsu • 獮ᒒૡ纷䒍 @ ࿞睃瞆叨褸㿁 • COSCUP 拻ᘏ • JSDC 拻ᘏ • kurotanshi [at] gmail.com • http://kuro.tw

Slide 3

Slide 3 text

̿ض獨ᓕ D3 ԧ牧֦肯螂虻懱憙憽玕㻟牫̀ 磪䷱磪Օ奧 D3.js 墋䁭ጱᒫӞ殷疰ݞՈ獨ᓕ D3 ጱ獌ܠ

Slide 4

Slide 4 text

ݶ䰬ฎ Web 懿袅獤ຉ牧ߺ㮆ฃ睞牫

Slide 5

Slide 5 text

ݶ䰬ฎ Web 懿袅獤ຉ牧ߺ㮆ฃ睞牫

Slide 6

Slide 6 text

傶Ջ讕襑ᥝ疥虻懱憙憽玕 • य़ᰁ虻碘ݢࣁ縣樌ᤩቘ薹牧虻懱㯽螏ๅ磪硳ሲ • 磪ۗෝ薪疗ڊٌ犢珊匍ොୗ犋ฃ疗憽کጱ虻碘粬௔ • ݢ犥盄਻ฃ፡ڊ虻碘๜蛪ጱቭ綦膏梊藮 • ֵአٌ犢承᥺ጱ捝ᘏ犖胼਻ฃ፡睞

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

蕣֢虻懱瑽蔭ጱᥝᔰ • ก嘦ጱԆ氂 • 虻懱羊墋玕牧Ԇ氂ๅ统ڊ • 殼䛑憙憽㵕娄牧珅୚捝ᘏፓط • 篷襑෈ਁ藯ก犖胼ቘ薹

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

http://d3js.org/ Demo: https://goo.gl/idrDMt

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

* svg 媑瑽襑ᥝ IE9+

Slide 15

Slide 15 text

• D3 = Data-Driven Documents. • ֵአ翕殷秂伛ದ蔩 (HTML / CSS / JavaScript / SVG) • 䔶य़ጱ Data-Driven 疥虻碘䌘䛑ک DOM Ӥ牧۱ೡزᔰ ጱी㳫现痀௔虋玕 • ൉׀ SVG ፘ橕媑瑽ૡٍ䓚牧蒈圸 SVG ኴጱ jQuery • 䕃௔᩻य़֕䋿֢斃ٌ犢憙憽玕ૡٍ耆卓 D3.js ฎՋ讕

Slide 16

Slide 16 text

螡䢔瑊膏 DOM 砺֢

Slide 17

Slide 17 text

螡䢔瑊 JavaScript jQuery D3.js document.querySelectorAll(".block") $(".block") d3.selectAll(".block")

Slide 18

Slide 18 text

螡䢔瑊 d3.select("body").selectAll(".block") d3.selectAll("body .block")

Slide 19

Slide 19 text

ොဩ袽 (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!');

Slide 20

Slide 20 text

痀௔ (attr) 
 // attr() d3.selectAll("circle") .attr("cx", 50) .attr("cy", 50) .attr("r", 25) .style("fill", "red");


Slide 21

Slide 21 text

痀௔ (attr) 
 // 犥̿ᇔկ̀ጱොୗ瞲ਧ痀௔ d3.selectAll("circle") .attr({ "cx": 50, "cy": 50, "r": 25 }) .style("fill", "red");
 // 玲஑ circle cx 痀௔ጱ独 d3.select("circle").attr("cx");

Slide 22

Slide 22 text

痀௔ (property) 
 d3.selectAll('.name')
 .property('value', 'Kuro'); 
 አဩ膏 attr() ፘݶ牧֕ property() ֵአࣁ篷ਁᶎ瞲ਧጱ痀௔牐 ই: disabled, checked 犥现 value 缛牐 
 d3.selectAll('.name')
 .property('disabled'); 


Slide 23

Slide 23 text

class 
 d3.selectAll('.block')
 .classed('item', true); 
 d3.selectAll('.block')
 .classed('item', false);
 
 d3.selectAll('.block')
 .classed('item big', true); 


Slide 24

Slide 24 text

styles 
 d3.selectAll('.block')
 .style('color', '#f00'); 
 
 d3.selectAll('.block')
 .style({ 'color': '#f00', 'font-size': '15px' }); 


Slide 25

Slide 25 text

text & html var foo = d3.selectAll('.foo'); foo.text('Hello World!'); foo.html('
Hello
');

Slide 26

Slide 26 text

ℂ虻碘ک瑽猟زᔰ

Slide 27

Slide 27 text

Data - ಅ磪ጱ虻碘᮷ฎ檋ڜ var data = [1, 3, 5, 2, 4, 6, 8, 10];

Slide 28

Slide 28 text

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}, …… ];

Slide 29

Slide 29 text

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 + '䵇'; });


Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

Enter, Update, Exit Pattern data = [10, 20, 30];
 d3.select('body')
 .selectAll('div') .data( data ) .exit() .remove(); 1 3 5 7 9

Slide 34

Slide 34 text

Enter, Update, Exit Pattern data = [10, 20, 30];
 d3.select('body')
 .selectAll('div') .data( data ) .exit() .remove(); 1 3 5 7 9 ?

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

SELECTION Datas Enter & Update Exit & Remove SELECTION

Slide 38

Slide 38 text

Enter: Data > Elements. Update: Data = Elements. Remove: Data < Elements.

Slide 39

Slide 39 text

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
 });

Slide 40

Slide 40 text

穉ֺ疳膏ଷ秂數

Slide 41

Slide 41 text


 d3.scale.linear().domain().range() 補間⽅法 輸入範圍 輸出範圍

Slide 42

Slide 42 text

Domain Range

Slide 43

Slide 43 text

穉ֺ疳 0 1000 0 100 500 50 Domain Range

Slide 44

Slide 44 text


 var d3Scale = d3.scale.linear() // linear .domain([0, 1000]) // 㯽獈塅瑻 .range([0, 100]); // 蜍ڊ塅瑻 console.log( d3Scale(500) ); // 50 console.log( d3Scale(123) ); // 12.3 穉ֺ疳

Slide 45

Slide 45 text

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));
 }


Slide 46

Slide 46 text

var widthScale = d3.scale.linear() .domain([0, 12]) .range(["0px", "720px"]); for (var i = 0; i < 13; i++) { body.append('div').text( widthScale(i) ); }

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

d3.scale.category10() d3.scale.category20() d3.scale.category20b() d3.scale.category20c()

Slide 50

Slide 50 text

ଷ秂數

Slide 51

Slide 51 text

數娄 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 አ㬵蔭纈ṛଶ

Slide 52

Slide 52 text

數娄 // x 數 var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom"); // ڰଶ֖ᗝ // y 數 var yAxis = d3.svg.axis() .scale(yScale) .orient("left"); // ڰଶ֖ᗝ

Slide 53

Slide 53 text

數娄 蝚螂 orient() 矒ګ數娄ොݻ现ڰଶ֖ᗝ

Slide 54

Slide 54 text

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");

Slide 55

Slide 55 text

裾礿瑽

Slide 56

Slide 56 text

㾼讨瑽

Slide 57

Slide 57 text

穥ု瑽 http://jsbin.com/yepapa

Slide 58

Slide 58 text

螂䁰㵕向 SELECTION.transition() .duration(1000) // 㵕向䁆ᤈ碻樌 .delay(1000) // 皤螛 .ease( ... ) // Easing 獢碍 .attr({ 'transform': function(d){ ....... } }); *D3.js Easing Checker - http://bl.ocks.org/hunzy/9929724

Slide 59

Slide 59 text

螂䁰㵕向 SELECTION.transition() .duration(1000) .each('start', function(){ … }) // 㵕向樄ত獮䁆ᤈ .attr({ … }) .each('end', function(){ … }); // 㵕向奾๳盅䁆ᤈ

Slide 60

Slide 60 text

ے獈Ԫկ SELECTION.on('click', function(){ alert('Hello D3!'); }); SELECTION.on('click', null);

Slide 61

Slide 61 text

ے獈Ԫկ SELECTION.on('click.event1', function(){ alert('Hello D3 event 1'); }); SELECTION.on('click.event2', function(){ alert('Hello D3 event 2'); });

Slide 62

Slide 62 text

穥ု瑽ےӤ㵕向硳ຎ

Slide 63

Slide 63 text

SVG च器

Slide 64

Slide 64 text

SVG 讨檋ୗ瑽粙婘硯碻䨝叨ኞ०፥硳䛑 source: http://www.cs.cmu.edu/~chuck/lennapg/lenna.shtml

Slide 65

Slide 65 text

SVG ݻᰁୗ瑽粙ኧӞ蝫Ԁଷ秂懯ᓒ奲౮牧硯ٚय़犖犋ொ source: http://komica.chiisana.net/vector/src/1205520731301.svg

Slide 66

Slide 66 text

rect 


Slide 67

Slide 67 text

circle 


Slide 68

Slide 68 text

line x1, y1 x2, y2

Slide 69

Slide 69 text

text 
 Hello 
 text-anchor="[start/middle/end]"

Slide 70

Slide 70 text

text - tspan 
 Hello, World 


Slide 71

Slide 71 text

text - tspan 
 Hello, World 


Slide 72

Slide 72 text

g (group) … 
 … 
 …

Slide 73

Slide 73 text

path • 犨఺娄ྦྷጱ奲ݳ牧ಅ磪瑽୵᮷向஑ڊ㬵 • d 痀௔物Ӟᗭ̿瞲犤̀+̿ଷ秂̀ጱ奲ݳ

Slide 74

Slide 74 text

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)

Slide 75

Slide 75 text

path

Slide 76

Slide 76 text

娄ྦྷ叨ኞ瑊 - d3.svg.line var linePath = d3.svg.line(); var data = [[10,50], [390, 130]]; svg.append('path') .attr('d', linePath(data));


Slide 77

Slide 77 text

娄ྦྷ叨ኞ瑊 - 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) });

Slide 78

Slide 78 text

ರ娄瑽

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

ರ娄瑽 - 虋୵

Slide 81

Slide 81 text

ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc

Slide 82

Slide 82 text

ୡ娄ྦྷ叨ኞ瑊 - 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 };

Slide 83

Slide 83 text

ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc var arc = d3.svg.arc() .innerRadius(50) .outerRadius(150); svg.append('path') .attr({ 'd': arc(myArc1) });

Slide 84

Slide 84 text

ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc

Slide 85

Slide 85 text

ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc http://community.yungching.com.tw/Building/9443

Slide 86

Slide 86 text

ୡ娄ྦྷ叨ኞ瑊 - d3.svg.arc

Slide 87

Slide 87 text

Responsive with D3

Slide 88

Slide 88 text

www.nytimes.com/interactive/2015/06/17/world/middleeast/map-isis-attacks-around-the-world.html

Slide 89

Slide 89 text

www.nytimes.com/interactive/2015/06/17/world/middleeast/map-isis-attacks-around-the-world.html

Slide 90

Slide 90 text

Responsive with D3

Slide 91

Slide 91 text

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;


Slide 92

Slide 92 text


 var svg = d3.select('.svg'); // 疥媑蕣㵕֢۱蕕ᛗ function 獉 function rendering() { // 疥媑蕣ጱ纷ୗ嘨蝢蝢砆ک愊ᶎ // ኼ } // 疥 window 翉ਧ resize Ԫկ牧㪔᯿碝媑蕣瑽ࣳ d3.select(window).on('resize', rendering); // Ḓ稞媑蕣 rendering();


Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

// resize 碻, 㵕眲ๅ碝 x, y 數ڰଶ, ๅ螕ݳ褂捝 var yAxis = d3.svg.axis() .scale(yScale2) .orient("left") .ticks( Math.max(height/50, 2) ); Responsive with D3

Slide 95

Slide 95 text

No content

Slide 96

Slide 96 text

Responsive with D3 • य़ग़碍ᤈ㵕蕕ᗝ䌘 SVG ඪൔ臑অ • ݻᰁ瑽୵牧婘硯犋०፥ • 㵕向 / زᔰ螂ग़碻ฃ磪硳胼㺔氂 • 犋ฎ犨֜瑽୵᮷螕ݳࣁಋ秚Ӥ氥纈物
 狶 RWD ౲ฎݚ狶Ӟ㮆ಋ秚粚๜牫

Slide 97

Slide 97 text

d3 Layouts

Slide 98

Slide 98 text

D3.js Layouts • d3.js ൉׀ԧ 11 圵粚ࣳ (layouts) • ݝ襑൉׀扗粚ࣳ瞲ਧጱ虻碘໒ୗ疰ݢ犥ፗ矑ॺአ • layouts ๜蛪犋൉׀媑瑽ۑ胼牧ᘒฎ疥ܻতጱ虻碘 旉矦౮螕ݳᤩ d3 媑瑽ጱ虻碘໒ୗ • 睱஑懯ᓒ top, left, d 缛缛痀௔ጱ碻狡粬獨অአ

Slide 99

Slide 99 text

Pie Layout

Slide 100

Slide 100 text

Pie Layout - Ӟᑁ虋綎綎瑹

Slide 101

Slide 101 text

Chord Layout 2015 ᒫӞ䌵Ӯኴ12䔶༉純搴 A 奲毆搴䌘䜗奾ຎ

Slide 102

Slide 102 text

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 -

Slide 103

Slide 103 text

Chord Layout

Slide 104

Slide 104 text

Chord Layout

Slide 105

Slide 105 text

Chord Layout

Slide 106

Slide 106 text

Chord Layout

Slide 107

Slide 107 text

Hierarchy Layout 塅ֺ虻碘: 2014 ݣ玖૱裾螡膐ݱᤈ硰玟ಭ纏翄懯

Slide 108

Slide 108 text

Partition Layout

Slide 109

Slide 109 text

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);

Slide 110

Slide 110 text

Partition Layout

Slide 111

Slide 111 text

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); });


Slide 112

Slide 112 text

http://bl.ocks.org/mbostock/1256572

Slide 113

Slide 113 text

捝ᘏ蚤֦మጱ犋Ӟ䰬 ইຎ獉瑹դ蔭 100牧 क़瑹䨝ฎग़੝牫

Slide 114

Slide 114 text

捝ᘏ蚤֦మጱ犋Ӟ䰬 500 1500

Slide 115

Slide 115 text

捝ᘏ蚤֦మጱ犋Ӟ䰬 500 1500 1500 500

Slide 116

Slide 116 text

憙憽玕犋ฎ磪瑽疰অ 瑽粙㬵რ物 https://www.facebook.com/forpeople/photos/a. 989035831154301.1073741835.153819538009272/989036197820931/

Slide 117

Slide 117 text

憙憽玕犋ฎ笖犝疰অ (࿞睃瞆լ翕ᤈ眐毱螇) (礓瞆լ翕ᒊ)

Slide 118

Slide 118 text

窾窫憙肯

Slide 119

Slide 119 text

ై螡Ԇ氂

Slide 120

Slide 120 text

ై螡Ԇ氂 0 200000000000000000000 400000000000000000000 600000000000000000000 800000000000000000000 1000000000000000000000 ྎॠ聲䒍 碝୛ڥ๝

Slide 121

Slide 121 text

No content

Slide 122

Slide 122 text

http://p.udn.com.tw/upf/newmedia/2015_data/20150930_udntyphoon/udntyphoon/index.html

Slide 123

Slide 123 text

No content

Slide 124

Slide 124 text

http://blog.infographics.tw/

Slide 125

Slide 125 text

No content

Slide 126

Slide 126 text

– Randy Krum, 
 Author of Cool Infographics. ̿፡ک牧疰睞ԧ牐̀

Slide 127

Slide 127 text

Q & A

Slide 128

Slide 128 text

• Kuro Hsu • Demo code: https://github.com/kurotanshi/d3js-samples • kurotanshi [at] gmail.com • http://kuro.tw Thanks!