# d3

Super easy DOM and data manipulation that combos with SVG and CSS to make easy, scriptable graphics

Easy DOM manipulation, data binding, transitions, and animations

Install from [https://d3js.org/](https://d3js.org/)

Great examples of whats possible at [https://github.com/d3/d3/wiki/Gallery](https://github.com/d3/d3/wiki/Gallery)

## DOM

`select([Selector String])`

`selectAll([Selector String])`

`selectAll("h2 span")`=> span within h2

Must use d3 commands with return

## Modifiers of Selector

* `.text("hot")`
* `.html('<strong class="temp">hot</strong>'`
* `.append('span')` => add to end of element
* `.insert('span', ':first-child')` => append with granularity
* `.remove()`
* `.style('background', 'red')`&#x20;
* `.classed('label', true)` =>turn label on
* `.attr(?)` //defined in html
* `.property(?)` //property of DOM node&#x20;

#### Example

```javascript
d3.selectAll("tr:nth-child(1) .temp").text("hot")
d3.selectAll("tr:nth-child(1) .temp").append('span').html("F")
```

## Binding Data

Assign data to selector, with callback access and index

1\)`.data(...)`

* generously assigns first data to first selection
* extra data and extra html will be ignored&#x20;
* array or dict&#x20;

2\) use callback ft `function(d, i) { return d }`

```javascript
D3.selectAll(".day-high")
    .data([45,78,77,66]) //will assign when possible
    .html(function(d, i) {
        if (i == 0) {
            return d;
        } 
        return '<strong>' + d + '</strong>'
    })
```

### Inside D3 Fts

```javascript
function(d, i) {
        d //data
    i //index
    d3.event.pageX // event accesss
    d3.select(this) //get this element 
}
```

## Data

### Importing

ajax based method for csv, tsv, json, etc

Wont work locally, need server

```javascript
d3.json('[path]', function(d) {
    let data = [];
    for (let i = 0; i < d.list.length; i++) {
        data.push(d.list[i]);
    }
    //Create graphic
});
```

### Creating HTML from Data

Select things that dont exist ,enter them ,and create your selection

`.enter()` create sub-selection

`.exit()` sub-selection

HTML

```markup
<tbody> </tbody>
```

JS

```javascript
mydata = [{'date': '4/1/19'}, {'date': '4/1/19'}]
d3.select('tbody')
.selectAll('tr')//but there are none
.data(mydata)
.enter().append('tr')//appending after entering creating them
.html(function (d) { return d.date })
```

## Scales

### Linear

Can scale values to size of graphics

.scaleLinear, .domain, .range

```javascript
var yScale = d3.scaleLinear()
    .domain([0, d3.max(bardata)])
    .range([0,height]); //height of graphic

...
    .attr('height', function (d) { return yScale(d)})
//OR
    .attr('height', yScale);
```

yScale is a ft that maps values from domain to range(normalizes height)

**Colors scales**

linear extrapolation between two colors

can do multiple color stops by putting multiple values in domain\&range

```javascript
var colors = d3.scaleLinear()
    .domain([0, d3.max(bardata)])
    .range(['#FFB832', '#C61C6F'])

...
    .attr('fill', function(d) { return colors(d) }) //Hey j, Can I just put colors here?
```

#### Ordinal Scales

Ordinal needs order

.scaleBand, .domain, .range, .padding OR .paddingInner and .paddingOuter

```javascript
var xScale = d3.scaleBand()
    .domain(bardata)
    .padding(.2) //add spacing at end and beginning
    .range([0, width])
```

## Guides

* .axisTop, .axisRight, .axisBottom, .axisLeft
* tick methods, and group elements
* this is pretty complex because of padding and margins, see example
* ticks can be much more complex and date scales are possible

```javascript
let yAxisValues = d3.scaleLinear()
    .domain([0, d3.max(temps)])
    .range([height, 0]);

let yAxisTicks = d3.axisLeft(yAxisValues)
    .tick(10) //how many elements

let yGuide = d3.select('svg').append('g').call(yAxisTicks);
```

## Events

```javascript
.on('mouseover', function(d) {
    d3.select(this)
        .style('opacity', .5)
})

.on('mouseout', function(d) {
    d3.select(this)
        .style('opacity', 1)
})
```

## Transitions

Create startup animations and movement or hover effects

Check out CSS transitions for more information

* .transition()
* .duration()
* .ease()
* .delay()

```javascript
.on('mouseover', function(d) {
    d3.select(this)
        .transition()
        .delay(400)
        .duration(1000)
        .style('opacity', .5)
})
```

## Other Ideas

Tooltip, by changing absolute position of element on hover and adding transition of opacity
