## Простые типы
````javascript
var age = 26
var name = 'Dmitriy Semyushkin'
````
Числа, строки, буль, объекты, массивы, функции.
## Простые типы
````javascript
var age = 26
var name = 'Dmitriy Semyushkin'
age == 26 // true
````
## Объекты
````javascript
var person = {
age: 26,
name: 'Dmitriy Semyushkin'
}
person.age == 26 // true
person.name.length // 18
````
## Массивы
````javascript
var primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
primes[6] // 17
primes.length // 10
````
## Функции
````javascript
var lessThanTen = function (n) {
return n < 10
}
lessThanTen(6) // true
lessThanTen(15) // false
````
## Функции
````javascript
var primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
var lessThanTen = function (n) {
return n < 10
}
primes.filter(lessThanTen) // [2, 3, 5, 7]
````
### General update pattern
## Привязка данных
````html
<div></div>
<div></div>
<div></div>
````
## Выведем текст
````javascript
d3.selectAll('div')
.data([18, 4, 7])
.text(function (d) { return d })
````

### Как быть?
````javascript
d3.selectAll('div')
.data([18, 4, 7, 11])
???
.text(function (d) { return d })
````

### Добавляем элементы
````javascript
d3.selectAll('div')
.data([18, 4, 7, 11])
.enter()
.append('div')
.text(function (d) { return d })
````

## Удаляем элементы
````javascript
d3.selectAll('div')
.data([18, 4])
.exit()
.remove()
````

### Основной кейс
````javascript
d3.selectAll('div')
.data([18, 4, 7])
.enter()
.append('div')
.text(function (d) { return d })
````

## Виды шкал
- Дискретные
- Непрерывные
## Метрики и шкалы

### Линейная шкала
````javascript
var scale = d3.scaleLinear()
.domain([10, 170])
.range([0, 960])
scale(10) // 0
scale(170) // 960
scale(40) // 180
scale.invert(0) // 10
scale.invert(960) // 170
scale.invert(180) // 40
````
### Линейная шкала
````javascript
var scale = d3.scaleLinear()
.domain([10, 170])
.range([0, 960])
scale(40) // 180
scale.invert(180) // 40
````
### Убывающие значения
````javascript
var scale = d3.scaleLinear()
.domain([170, 10])
.range([0, 960])
scale(40) // 780
scale.invert(780) // 40
````
## Цвета
````javascript
var scale = d3.scaleLinear()
.domain([0, 80])
.range(['black', 'white'])
scale(10) // "#202020"
scale.invert("#202020") // NaN
````
## Несколько цветов
````javascript
var scale = d3.scaleLinear()
.domain([-100, 0, 100])
.range(['#F99', '#DDD', '#39F'])
scale(-25) // rgb(230, 204, 204)
scale(50) // rgb(136, 187, 238)
````
## Пороговая шкала
[](http://bl.ocks.org/herrstucki/6312708)
## Пороговая шкала
````javascript
var scale = d3.scaleThreshold()
.domain([45, 55, 65, 75, 85])
.range(['F', 'E', 'D', 'C', 'B', 'A'])
scale(50) // "E"
scale.invertExtent("F") // [undefined, 45]
scale.invertExtent("E") // [45, 55]
````
Создание набора данных
- Draw my data
- csvjson.com
## Данные
````javascript
[
{ X: 1, Y: 2 },
{ X: 42, Y: 7 },
{ X: 15, Y: 3 },
{ X: 32, Y: 8 },
{ X: 26, Y: 9 },
{ X: 18, Y: 5 }
]
````
jsbin.com/sicedozuba/edit
````javascript
var data = [
{ X: 1, Y: 2 },
{ X: 42, Y: 7 },
{ X: 15, Y: 3 },
{ X: 32, Y: 8 },
{ X: 26, Y: 9 },
{ X: 18, Y: 5 }
]
var width = 500
var height = 500
````
````javascript
var xScale = d3.scaleLinear()
.domain([0, 50])
.range([0, width])
var yScale = d3.scaleLinear()
.domain([0, 10])
.range([height, 0])
var color = d3.scaleLinear()
.domain([0, 10])
.range(['#500', '#F00'])
````
````javascript
d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height)
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('r', 5)
````
````javascript
...
.attr('r', 5)
.attr('cx', function (d) { return xScale(d.X) })
.attr('cy', function (d) { return yScale(d.Y) })
.attr('fill', function (d) { return color(d.Y) })
````
## Margin convention
[](https://bl.ocks.org/mbostock/3019563)
````javascript
var margin = {
top: 20,
right: 20,
bottom: 20,
left: 20
}
var fullWidth = 500
var fullHeight = 500
var width = fullWidth - margin.left - margin.right
var height = fullHeight - margin.top - margin.bottom
````
````javascript
...
.append('svg')
.attr('width', fullWidth)
.attr('height', fullHeight)
...
````
````javascript
...
.append('svg')
.attr('width', fullWidth)
.attr('height', fullHeight)
.append('g')
.attr('transform', 'translate(' + margin.left + ','
+ margin.top + ')')
...
````
## Начало работы
jsbin.com/lamedimecu/edit
````javascript
var firesUrl = 'http://d3.datalaboratory.ru'
+ '/data/fire-calls.json'
d3.json(firesUrl, function (data) {
var ordinal = d3.scaleOrdinal()
.range(d3.range(9))
var color = d3.scaleSequential(d3.interpolateYlOrRd)
var maxCalls = d3.max(data, function (d) {
return d.calls
})
color.domain([0, maxCalls])
})
````
Привязка данных и создание элементов
````javascript
d3.select('body')
.append('svg')
.selectAll('rect')
.data(data)
.enter()
.append('rect')
````
Использование данных
````javascript
...
.attr('x', function (d) {
return ((d.year - 2015) * 12 + d.month - 1) * 20
})
.attr('y', function (d) {
return ordinal(d.area) * 20
})
.attr('width', 20)
.attr('height', 20)
.attr('fill', function (d) {
return color(d.calls)
})
````
Улучшаем существующую карту
http://bl.ocks.org/KoGor/5685876
## Начало работы
http://jsbin.com/webibajiwi/edit
## Подключение библиотек
````
<script src='http://d3js.org/d3.v4.js'></script>
<script src='http://d3js.org/topojson.v1.js'></script>
<script src='http://d3js.org/colorbrewer.v1.js'></script>
````
Размер, шкала, контейнер
````javascript
var color = d3.scaleThreshold()
.domain([300, 600, 900, 1200, 1500])
.range(colorbrewer['RdYlGn'][6].reverse())
var width = 960
var height = 500
var svg = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height)
````
Загрузка данных
````javascript
d3.queue()
.defer(d3.json, 'http://d3.datalaboratory.ru'
+ '/data/russia.json')
.defer(d3.csv, 'http://d3.datalaboratory.ru'
+ '/data/accidents.csv')
.await(ready)
function ready(error, map, data) {
...
}
````
Обработка данных
````javascript
var rateById = {}
data.forEach(function (d) {
rateById[d.RegionCode] = Number(d.Deaths)
})
````
Отрисовка
````javascript
var path = d3.geoPath().projection(projection)
var mapData = topojson
.feature(map, map.objects.russia)
.features
````
Отрисовка
````javascript
svg.selectAll('path')
.data(mapData)
.enter()
.append('path')
.attr('stroke', 'white')
.attr('stroke-width', 1)
.attr('d', path)
.attr('fill', function (d) {
return color(rateById[d.properties.region])
})
````
Проекция
````javascript
var projection = d3.geoAlbers()
.rotate([-105, 0])
.center([-10, 65])
.parallels([52, 64])
.scale(700)
.translate([width * 0.5, height * 0.5])
````
## Оформление визуализации
## Вторая карта
````javascript
var svg2 = d3.select('body').append('svg')
.attr('width', width * 0.5)
.attr('height', height)
.style('border-left', '1px solid #000')
.style('margin', '10px auto')
var projection2 = d3.geoAlbers()
.rotate([-105, 0])
.center([-10, 65])
.parallels([52, 64])
.scale(500)
.translate([width * 0.1425, height * 0.65])
drawMap(svg2, map, cities, rateById, projection2)
````
## Легенда
````javascript
var legend_labels = [
'< 300', '300 +',
'600 +', '900 +',
'1200 +', '> 1500'
]
var legend = svg2.selectAll('g.legend')
.data(ext_color_domain)
.enter().append('g')
.attr('class', 'legend')
````
````javascript
legend.append('rect')
.attr('x', 200)
.attr('y', function (d, i) { return i * ls_h })
.attr('width', ls_w)
.attr('height', ls_h)
.attr('fill', function (d, i) { return color(d) })
legend.append('text')
.attr('x', 230)
.attr('dy','-4')
.attr('y', function (d, i) {
return (i + 1) * ls_h
})
.text(function (d, i) { return legend_labels[i] })
````
## Тень для текста
````javascript
city.append('text').attr('class', 'shade')
city.append('text')
````
````css
.shade {
stroke: #fff;
stroke-width: 2.75px;
fill: #fff;
text-shadow: 0 0 2px #fff;
}
````