script.js
circuitTracks.forEach((track, i) => {
const container = d3
.select('.circuits')
.append('div')
.attr('class', 'circuit-container')
container.append('p').html(circuitNames[i])
const svgContainer = container.append('div').attr('class', 'circuit-track')
const margin = 10
const dimension = svgContainer.node().offsetWidth - margin * 2
const xExtent = d3.extent(track, d => d.x)
const x = d3.scaleLinear().domain(xExtent)
const yExtent = d3.extent(track, d => d.y)
const y = d3.scaleLinear().domain(yExtent)
const aspect = (xExtent[1] - xExtent[0]) / (yExtent[1] - yExtent[0])
const width = Math.min(dimension * aspect, dimension)
const height = Math.min(dimension / aspect, dimension)
x.range([0, width])
y.range([0, height])
const svg = svgContainer
.append('svg')
.attr('width', width + 2 * margin)
.attr('height', height + 2 * margin)
const g = svg.append('g').attr('transform', `translate(${margin}, ${margin})`)
const line = d3
.line()
.curve(d3.curveBasis)
.x(d => x(d.x))
.y(d => y(d.y))
g
.append('path')
.datum(track)
.attr('d', line)
})
index.html
<!DOCTYPE html>
<title>blockup</title>
<link href='dist.css' rel='stylesheet' />
<body>
<div class='circuits' />
<script src='d3.v4.min.js'></script>
<script src='circuitNames.js'></script>
<script src='circuitTracks.js'></script>
<script src='dist.js'></script>
</body>
circuitNames.js
var circuitNames = [
'Melbourne Grand Prix Circuit',
'Bahrain International Circuit',
'Shanghai International Circuit',
'Baku City Circuit',
'Circuit de Barcelona-Catalunya',
'Circuit de Monaco',
'Circuit Gilles Villeneuve',
'Circuit Paul Ricard',
'Red Bull Ring',
'Silverstone Circuit',
'Hockenheimring',
'Hungaroring',
'Circuit de Spa-Francorchamps',
'Autodromo Nazionale Monza',
'Marina Bay Street Circuit',
'Sochi Autodrom',
'Suzuka International Racing Course',
'Circuit of the Americas',
'Autódromo Hermanos Rodríguez',
'Autódromo José Carlos Pace',
'Yas Marina Circuit'
];
dist.css
*{box-sizing:border-box}body{background:rgba(0,0,0,.1);margin:0;width:960px;margin:0 auto}.circuits{width:100%;overflow:hidden}.circuits .circuit-container{margin:0 0 1em 0;width:8.5em;float:left}.circuits .circuit-container p{padding:0 .5em;font-family:sans-serif;font-size:.75em;text-align:center;height:1.5em;opacity:.75}.circuits .circuit-container .circuit-track{height:8.5em}.circuits .circuit-container svg{display:block;margin:0 auto}.circuits .circuit-container svg path{fill:#8f092a}
dist.js
!function(n){function t(a){if(c[a])return c[a].exports;var i=c[a]={i:a,l:!1,exports:{}};return n[a].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var c={};t.m=n,t.c=c,t.i=function(n){return n},t.d=function(n,c,a){t.o(n,c)||Object.defineProperty(n,c,{configurable:!1,enumerable:!0,get:a})},t.n=function(n){var c=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(c,"a",c),c},t.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},t.p="",t(t.s=0)}([function(module,exports,__webpack_require__){"use strict";eval("\n\ncircuitTracks.forEach(function (track, i) {\n var container = d3.select('.circuits').append('div').attr('class', 'circuit-container');\n\n container.append('p').html(circuitNames[i]);\n\n var svgContainer = container.append('div').attr('class', 'circuit-track');\n\n var margin = 10;\n var dimension = svgContainer.node().offsetWidth - margin * 2;\n\n var xExtent = d3.extent(track, function (d) {\n return d.x;\n });\n var x = d3.scaleLinear().domain(xExtent);\n\n var yExtent = d3.extent(track, function (d) {\n return d.y;\n });\n var y = d3.scaleLinear().domain(yExtent);\n\n var aspect = (xExtent[1] - xExtent[0]) / (yExtent[1] - yExtent[0]);\n\n var width = Math.min(dimension * aspect, dimension);\n var height = Math.min(dimension / aspect, dimension);\n\n x.range([0, width]);\n y.range([0, height]);\n\n var svg = svgContainer.append('svg').attr('width', width + 2 * margin).attr('height', height + 2 * margin);\n\n var g = svg.append('g').attr('transform', 'translate(' + margin + ', ' + margin + ')');\n\n var line = d3.line().curve(d3.curveBasis).x(function (d) {\n return x(d.x);\n }).y(function (d) {\n return y(d.y);\n });\n\n g.append('path').datum(track).attr('d', line);\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy9zY3JpcHQuanM/OWE5NSJdLCJzb3VyY2VzQ29udGVudCI6WyJjaXJjdWl0VHJhY2tzLmZvckVhY2goKHRyYWNrLCBpKSA9PiB7XG4gIGNvbnN0IGNvbnRhaW5lciA9IGQzXG4gICAgLnNlbGVjdCgnLmNpcmN1aXRzJylcbiAgICAuYXBwZW5kKCdkaXYnKVxuICAgIC5hdHRyKCdjbGFzcycsICdjaXJjdWl0LWNvbnRhaW5lcicpXG5cbiAgY29udGFpbmVyLmFwcGVuZCgncCcpLmh0bWwoY2lyY3VpdE5hbWVzW2ldKVxuXG4gIGNvbnN0IHN2Z0NvbnRhaW5lciA9IGNvbnRhaW5lci5hcHBlbmQoJ2RpdicpLmF0dHIoJ2NsYXNzJywgJ2NpcmN1aXQtdHJhY2snKVxuXG4gIGNvbnN0IG1hcmdpbiA9IDEwXG4gIGNvbnN0IGRpbWVuc2lvbiA9IHN2Z0NvbnRhaW5lci5ub2RlKCkub2Zmc2V0V2lkdGggLSBtYXJnaW4gKiAyXG5cbiAgY29uc3QgeEV4dGVudCA9IGQzLmV4dGVudCh0cmFjaywgZCA9PiBkLngpXG4gIGNvbnN0IHggPSBkMy5zY2FsZUxpbmVhcigpLmRvbWFpbih4RXh0ZW50KVxuXG4gIGNvbnN0IHlFeHRlbnQgPSBkMy5leHRlbnQodHJhY2ssIGQgPT4gZC55KVxuICBjb25zdCB5ID0gZDMuc2NhbGVMaW5lYXIoKS5kb21haW4oeUV4dGVudClcblxuICBjb25zdCBhc3BlY3QgPSAoeEV4dGVudFsxXSAtIHhFeHRlbnRbMF0pIC8gKHlFeHRlbnRbMV0gLSB5RXh0ZW50WzBdKVxuXG4gIGNvbnN0IHdpZHRoID0gTWF0aC5taW4oZGltZW5zaW9uICogYXNwZWN0LCBkaW1lbnNpb24pXG4gIGNvbnN0IGhlaWdodCA9IE1hdGgubWluKGRpbWVuc2lvbiAvIGFzcGVjdCwgZGltZW5zaW9uKVxuXG4gIHgucmFuZ2UoWzAsIHdpZHRoXSlcbiAgeS5yYW5nZShbMCwgaGVpZ2h0XSlcblxuICBjb25zdCBzdmcgPSBzdmdDb250YWluZXJcbiAgICAuYXBwZW5kKCdzdmcnKVxuICAgIC5hdHRyKCd3aWR0aCcsIHdpZHRoICsgMiAqIG1hcmdpbilcbiAgICAuYXR0cignaGVpZ2h0JywgaGVpZ2h0ICsgMiAqIG1hcmdpbilcblxuICBjb25zdCBnID0gc3ZnLmFwcGVuZCgnZycpLmF0dHIoJ3RyYW5zZm9ybScsIGB0cmFuc2xhdGUoJHttYXJnaW59LCAke21hcmdpbn0pYClcblxuICBjb25zdCBsaW5lID0gZDNcbiAgICAubGluZSgpXG4gICAgLmN1cnZlKGQzLmN1cnZlQmFzaXMpXG4gICAgLngoZCA9PiB4KGQueCkpXG4gICAgLnkoZCA9PiB5KGQueSkpXG5cbiAgZ1xuICAgIC5hcHBlbmQoJ3BhdGgnKVxuICAgIC5kYXR1bSh0cmFjaylcbiAgICAuYXR0cignZCcsIGxpbmUpXG59KVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHNjcmlwdC5qcyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFHQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFJQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///0\n")}]);
package.json
{
"standard": {
"globals": [
"circuitTracks",
"circuitNames",
"d3"
]
}
}
style.styl
$red = #8f092a
*
box-sizing border-box
body
background rgba(0, 0, 0, 0.1)
margin 0
width 960px
margin 0 auto
.circuits
width 100%
overflow hidden
.circuit-container
margin 0 0 1em 0
width 8.5em
float left
p
padding 0 0.5em
font-family sans-serif
font-size 0.75em
text-align center
height 1.5em
opacity 0.75
.circuit-track
height 8.5em
svg
display block
margin 0 auto
path
fill $red