├── .gitignore ├── Challenges.md ├── Challenges_solutions.md ├── LICENSE ├── README.md ├── pictures ├── 00A_libs.png ├── 00B_Series1.png ├── 00B_Series2.png ├── 00B_Series3.png ├── 00C_Main1.png ├── 00C_Main2.png ├── 00C_Main3.png ├── 02_Chart_Bar_Padding.png ├── 02_Chart_Original.png ├── 02_vertical.png ├── 03_twolines.png └── 06_pie.png └── samples ├── 00 nvd3 ├── 00 Lines │ ├── data.js │ ├── index.html │ ├── main.js │ └── readme.md └── 01 BubbleChart │ ├── data.js │ ├── index.html │ ├── main.js │ └── readme.md ├── 01 basics-web ├── 00 HTML │ ├── index.html │ └── readme.md ├── 01 CSS │ ├── index.html │ ├── readme.md │ └── styles.css ├── 02 DOM │ ├── index.html │ ├── main.js │ ├── readme.md │ └── styles.css ├── 03 DOM 2 │ ├── index.html │ ├── main.js │ └── readme.md ├── 04 SVG │ ├── index.html │ ├── readme.md │ └── styles.css └── 05 SVG 2 │ ├── index.html │ ├── readme.md │ └── styles.css ├── 02 Charts ├── 00 SVG │ ├── index.html │ ├── readme.md │ └── styles.css ├── 02 BarChart │ ├── index.html │ ├── main.js │ └── readme.md ├── 03 BarChartAxis │ ├── index.html │ ├── main.js │ ├── readme.md │ └── styles.css ├── 04 BarChartRefactor │ ├── data.js │ ├── index.html │ ├── main.js │ └── styles.css ├── 05 Lines │ ├── data.js │ ├── index.html │ ├── main.js │ └── styles.css ├── 06 Pie │ ├── data.js │ ├── index.html │ ├── main.js │ └── styles.css └── 07 Refresh │ ├── data.csv │ ├── index.html │ ├── main.js │ └── styles.css ├── 03 Sleek Charts └── 01 Bubble Chart │ ├── .babelrc │ ├── base.webpack.config.js │ ├── data │ └── StatsPerCountry.txt │ ├── dev.webpack.config.js │ ├── fonts │ └── rajdhani │ │ ├── Rajdhani-Bold.ttf │ │ ├── Rajdhani-Light.ttf │ │ ├── Rajdhani-Medium.ttf │ │ ├── Rajdhani-Regular.ttf │ │ └── Rajdhani-SemiBold.ttf │ ├── package.json │ ├── prod.webpack.config.js │ └── src │ ├── app.js │ ├── bubbleChart.js │ ├── bubbleChartStyles.scss │ ├── delimitedDataParser.js │ ├── index.html │ └── pageStyles.scss └── 04 maps ├── 00 world_basic ├── index.html ├── main.js └── readme.md ├── 01 world_interaction ├── d3-tip.js ├── index.html ├── main.js ├── package-lock.json ├── package.json ├── readme.md ├── world_countries.json └── world_population.tsv ├── 02 spain ├── ccaa.json ├── index.html ├── main.js ├── municipios.json ├── package.json └── readme.md └── 03 others └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist/ 4 | *.orig 5 | .idea/ -------------------------------------------------------------------------------- /Challenges.md: -------------------------------------------------------------------------------- 1 | # 02 Charts / 02 BarChart 2 | 3 | 1) Add a padding between each of the chart bars. 4 | 5 |  6 |  7 | 8 | 2) What about adding some color to each bar, based on the product Id ? 9 | 10 | Some tips: 11 | 12 | - We can treat product category as an ordinal. 13 | 14 | - We can create a function that returns a color based on 15 | an existing d3 SchemeCategory 16 | 17 | ```javascript 18 | // helper that returns a color based on an ID 19 | var barColor = d3.scaleOrdinal(d3.schemeCategory10); 20 | ``` 21 | 22 | The React it self has an attribute called filled, we can 23 | attach to it a _function(d)_ extract from it the current product 24 | and invoke the color function we have previously created. 25 | 26 | 3) Let's rotate 90º the bar chart, we want it to show it like: 27 | 28 |  29 | 30 | If you need some help, a similar sample can be found: 31 | 32 | [Blocks Sample](http://bl.ocks.org/d3noob/8952219) 33 | 34 | # 02 Charts / 05 Lines 35 | 36 | 4) Add one more line to the chart, this line will represent 37 | a set of expenses. 38 | 39 |  40 | 41 | # 02 Charts / 06 Pie 42 | 43 | 4) Create a Doughnut like chart. 44 | 45 |  46 | 47 | 5) Make the pie chart scale and take all the available canvas space, plus include margin for legend. 48 | -------------------------------------------------------------------------------- /Challenges_solutions.md: -------------------------------------------------------------------------------- 1 | # 02 Charts / 02 BarChart 2 | 3 | 1) Add a padding between each of the chart bars. 4 | 5 |  6 |  7 | 8 | **Solution** 9 | 10 | ```diff 11 | newRects.append('rect') 12 | .attr('x', x(0)) 13 | .attr('y', function(d, i) { 14 | return y(d.product); 15 | }) 16 | - .attr('height', y.bandwidth) 17 | + .attr('height', function(d, i) { 18 | + return y.bandwidth() - 5; 19 | + }) 20 | .attr('width', function(d, i) { 21 | return x(d.sales); 22 | }); 23 | 24 | ``` 25 | 26 | 2) What about adding some color to each bar, based on the product Id ? 27 | 28 | Some tips: 29 | 30 | - We can treat product category as an ordinal. 31 | 32 | - We can create a function that returns a color based on 33 | an existing d3 SchemeCategory 34 | 35 | ```javascript 36 | // helper that returns a color based on an ID 37 | var barColor = d3.scaleOrdinal(d3.schemeCategory10); 38 | ``` 39 | 40 | The React it self has an attribute called filled, we can 41 | attach to it a _function(d)_ extract from it the current product 42 | and invoke the color function we have previously created. 43 | 44 | **Solution** 45 | 46 | ```diff 47 | + // helper that returns a color based on an ID 48 | + var barColor = d3.scaleOrdinal(d3.schemeCategory10); 49 | 50 | 51 | newRects.append('rect') 52 | .attr('x', x(0)) 53 | .attr('y', function(d, i) { 54 | return y(d.product); 55 | }) 56 | .attr('height', y.bandwidth) 57 | .attr('width', function(d, i) { 58 | return x(d.sales); 59 | }) 60 | + .attr('fill', function(d) { 61 | + return barColor(d.product); 62 | + }); 63 | ``` 64 | 65 | 3) Let's rotate 90º the bar chart, we want it to show it like: 66 | 67 |  68 | 69 | First let's swap X Scale and Y Scale 70 | 71 | 72 | ```javascript 73 | 74 | let margin = null, 75 | width = null, 76 | height = null; 77 | 78 | let svg = null; 79 | let x, y = null; // scales 80 | 81 | setupCanvasSize(); 82 | appendSvg("body"); 83 | setupXScale(); 84 | setupYScale(); 85 | appendXAxis(); 86 | appendYAxis(); 87 | appendChartBars(); 88 | 89 | // 1. let's start by selecting the SVG Node 90 | function setupCanvasSize() { 91 | margin = {top: 100, left: 180, bottom: 120, right: 130}; 92 | width = 960 - margin.left - margin.right; 93 | height = 800 - margin.top - margin.bottom; 94 | } 95 | 96 | function appendSvg(domElement) { 97 | svg = d3.select(domElement).append("svg") 98 | .attr("width", width + margin.left + margin.right) 99 | .attr("height", height + margin.top + margin.bottom) 100 | .append("g") 101 | .attr("transform", 102 | "translate(" + margin.left + "," + margin.top + ")"); 103 | ; 104 | } 105 | 106 | 107 | function setupXScale() 108 | { 109 | x = d3.scaleBand() 110 | .rangeRound([0, width]) 111 | .domain(totalSales.map(function(d, i) { 112 | return d.product; 113 | })); 114 | 115 | } 116 | 117 | function setupYScale() 118 | { 119 | var maxSales = d3.max(totalSales, function(d, i) { 120 | return d.sales; 121 | }); 122 | 123 | y = d3.scaleLinear() 124 | .range([height,0]) 125 | .domain([0, maxSales]); 126 | } 127 | 128 | function appendXAxis() { 129 | // Add the X Axis 130 | svg.append("g") 131 | .attr("transform", "translate(0," + height + ")") 132 | .call(d3.axisBottom(x)); 133 | } 134 | 135 | function appendYAxis() { 136 | // 137 | // Add the Y Axis 138 | svg.append("g") 139 | 140 | .call(d3.axisLeft(y)); 141 | } 142 | 143 | function appendChartBars() 144 | { 145 | // 2. Now let's select all the rectangles inside that svg 146 | // (right now is empty) 147 | var rects = svg.selectAll('rect') 148 | .data(totalSales); 149 | 150 | // Now it's time to append to the list of Rectangles we already have 151 | var newRects = rects.enter(); 152 | 153 | 154 | newRects.append('rect') 155 | .attr('x', function(d, i) { 156 | return x(d.product); 157 | }) 158 | .attr('y', function(d) { 159 | return y(d.sales); 160 | }) 161 | .attr('height', function(d, i) { 162 | return height - y(d.sales); 163 | }) 164 | .attr('width', x.bandwidth) 165 | ; 166 | 167 | } 168 | ``` 169 | 170 | **There's a second solution that you can try... what about keeping the chart 171 | as it was original and just rotate it?** 172 | 173 | # 02 Charts / 05 Lines 174 | 175 | 4) Add one more line to the chart, this line will represent 176 | a set of expenses. 177 | 178 |  179 | 180 | Let's start by adding a new style for the new line (styles.css) 181 | 182 | ```css 183 | .lineB { 184 | fill: none; 185 | stroke: red; 186 | stroke-width: 2px; 187 | } 188 | ``` 189 | 190 | We will add a new line of data 191 | 192 | ```javascript 193 | var totalExpenses = [ 194 | { month: new Date(2016,10, 01), sales: 3500 }, 195 | { month: new Date(2016,11, 01), sales: 2400 }, 196 | { month: new Date(2016,12, 01), sales: 1500 }, 197 | { month: new Date(2017,1, 01), sales: 6000 }, 198 | { month: new Date(2017,2, 01), sales: 4500 }, 199 | ]; 200 | ``` 201 | 202 | > For the sake of simplicity we will keep the same dates (as an additional excercise, what should 203 | you take care if we have different date ranges? we should combine min and max for the X timeline). 204 | 205 | Next step let's add the new line 206 | 207 | ```javascript 208 | function appendLineCharts() 209 | { 210 | // (...) 211 | var expenseline = d3.line() 212 | .x(function(d) { return x(d.month); }) 213 | .y(function(d) { return y(d.expense); }); 214 | 215 | // Add the valueline path. 216 | svg.append("path") 217 | .data([totalExpenses]) 218 | .attr("class", "lineB") 219 | .attr("d", expenseline); 220 | } 221 | ``` 222 | 223 | # 02 Charts / 06 Pie 224 | 225 | 4) Create a Doughnut like chart. 226 | 227 |  228 | 229 | You only need to play with the innerRadius property: 230 | 231 | ```javascript 232 | // Pie chart size 233 | var arc = d3.arc() 234 | .innerRadius(20) 235 | .outerRadius(50); 236 | ``` 237 | 238 | 5) Make the pie chart scale and take all the available canvas space, plus include margin for legend. 239 | 240 | ```diff 241 | function setupCanvasSize() { 242 | margin = {top: 0, left: 80, bottom: 20, right: 30}; 243 | + width = 760 - margin.left - margin.right; 244 | + height = 660 - margin.top - margin.bottom; 245 | } 246 | 247 | function appendPieChart() 248 | { 249 | // Where to get the measure data 250 | var pie = d3.pie() 251 | .value(function(d) { return d.sales }) 252 | 253 | // Calculate Arcs 254 | var slices = pie(totalSales); 255 | 256 | // Pie chart size 257 | var arc = d3.arc() 258 | .innerRadius(0) 259 | + .outerRadius(height / 2); 260 | 261 | + var positionX = width / 2; 262 | + var positionY = height / 2; 263 | 264 | // Draw the pie 265 | svg.selectAll('path.slice') 266 | .data(slices) 267 | .enter() 268 | .append('path') 269 | .attr('class', 'slice') 270 | .attr('d', arc) 271 | .attr('fill', function(d) { 272 | return color(d.data.product); 273 | }) 274 | + .attr("transform", `translate(${positionX}, ${positionY})`) 275 | ; 276 | } 277 | 278 | ``` 279 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Braulio Diez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # d3js-samples 2 | 3 | Simple d3js (v. 4) samples: 4 | - Basic HTML / CSS sample (intro to developers that are NOOB to web development). 5 | - Basic d3js charts samples: 6 | - Consuming third partie libraries. 7 | - Creating barchart from scratch. 8 | - Creating a pie chart. 9 | - Working with maps (guide included). 10 | 11 | # About Basefactor + Lemoncode 12 | 13 | We are an innovating team of Javascript experts, passionate about turning your ideas into robust products. 14 | 15 | [Basefactor, consultancy by Lemoncode](http://www.basefactor.com) provides consultancy and coaching services. 16 | 17 | [Lemoncode](http://lemoncode.net/services/en/#en-home) provides training services. 18 | 19 | For the LATAM/Spanish audience we are running an Online Front End Master degree, more info: http://lemoncode.net/master-frontend 20 | 21 | 22 | -------------------------------------------------------------------------------- /pictures/00A_libs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/00A_libs.png -------------------------------------------------------------------------------- /pictures/00B_Series1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/00B_Series1.png -------------------------------------------------------------------------------- /pictures/00B_Series2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/00B_Series2.png -------------------------------------------------------------------------------- /pictures/00B_Series3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/00B_Series3.png -------------------------------------------------------------------------------- /pictures/00C_Main1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/00C_Main1.png -------------------------------------------------------------------------------- /pictures/00C_Main2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/00C_Main2.png -------------------------------------------------------------------------------- /pictures/00C_Main3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/00C_Main3.png -------------------------------------------------------------------------------- /pictures/02_Chart_Bar_Padding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/02_Chart_Bar_Padding.png -------------------------------------------------------------------------------- /pictures/02_Chart_Original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/02_Chart_Original.png -------------------------------------------------------------------------------- /pictures/02_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/02_vertical.png -------------------------------------------------------------------------------- /pictures/03_twolines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/03_twolines.png -------------------------------------------------------------------------------- /pictures/06_pie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lemoncode/d3js-samples/52942f4da800cfadef0ab47e58726d8cde30ad29/pictures/06_pie.png -------------------------------------------------------------------------------- /samples/00 nvd3/00 Lines/data.js: -------------------------------------------------------------------------------- 1 | function sinAndCos() { 2 | var sin = [], 3 | sin2 = [], 4 | cos = [], 5 | rand = [], 6 | rand2 = [] 7 | ; 8 | for (var i = 0; i < 100; i++) { 9 | sin.push({x: i, y: i % 10 == 5 ? null : Math.sin(i/10) }); //the nulls are to show how defined works 10 | sin2.push({x: i, y: Math.sin(i/5) * 0.4 - 0.25}); 11 | cos.push({x: i, y: .5 * Math.cos(i/10)}); 12 | rand.push({x:i, y: Math.random() / 10}); 13 | rand2.push({x: i, y: Math.cos(i/10) + Math.random() / 10 }) 14 | } 15 | return [ 16 | { 17 | area: true, 18 | values: sin, 19 | key: "Sine Wave", 20 | color: "#ff7f0e", 21 | strokeWidth: 4, 22 | classed: 'dashed' 23 | }, 24 | { 25 | values: cos, 26 | key: "Cosine Wave", 27 | color: "#2ca02c" 28 | }, 29 | { 30 | values: rand, 31 | key: "Random Points", 32 | color: "#2222ff" 33 | }, 34 | { 35 | values: rand2, 36 | key: "Random Cosine", 37 | color: "#667711", 38 | strokeWidth: 3.5 39 | }, 40 | { 41 | area: true, 42 | values: sin2, 43 | key: "Fill opacity", 44 | color: "#EF9CFB", 45 | fillOpacity: .1 46 | } 47 | ]; 48 | } 49 | -------------------------------------------------------------------------------- /samples/00 nvd3/00 Lines/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |