# D3

一個可以簡單用 JS 操作 SVG 的框架。

## 推薦資料來源：

{% embed url="<https://www.gapminder.org/data/>" %}

## 使用

主要會使用到包含：

```javascript
<line> elements for the edges
<text> elements for the labels
<circle> elements to represent the nodes
<g> elements as containers that move the nodes and labels together
```

1.選擇元素

```javascript
d3.select('')
d3.selectAll('')
```

2.設定屬性

```javascript
d3.select('').attr('width', 20)
```

設定 style

```javascript
.style("fill", "#69b3a2")
```

3.新增元素

```javascript
d3.select('').append("svg")
```

4.設定相關範圍，讓數值縮小

```javascript
const x = d3.scaleLinear()
    .domain([0, 4000]) // 數值範圍
    .range([ 0, width ]); // 實際顯示範圍
```

5.傳入資料並且遍歷

> 記得 append 前要用 selectAll 相同東西，不然不會顯示

```javascript
const data = [{...}...]

d3.select('#test')
    .selectAll('circle')
    .data(data)
    .enter() // 類似forEach
    .append("circle")
```

6.添加座標軸

```javascript
const data = [{
  case: 23,
}....]

let aScale = d3
    .scaleLinear()
    .domain([0, d3.max(data, (d) => d.cases)])
    .range([0, 300]);
  
  d3.select("#scatterplot #x-axis")
    .call(d3.axisBottom(aScale).ticks(5));
```

7\. 加上動畫

```javascript
    .transition()
    .duration(1000)
```

## 地圖

typojson 比 geojson 檔案小。

以下範例讀取 typojson 然後用 相關套件轉換為geojson 並顯示到 d3 上

<https://github.com/topojson/topojson-client/blob/master/README.md#feature>

```javascript
d3.json('data/world.json').then(world => {
    let projection = d3.geoWinkel3().scale(140).translate([365, 225]);
    let geoPath = d3.geoPath(projection);

    const svg = d3
      .select("#map-chart")
      .append("svg")
      .attr("width", 365 * 2)
      .attr("height", 225 * 2);

    svg
      .selectAll("path")
      .data(topojson.feature(world, world.objects.countries).features)
      .enter()
      .append("path")
      .attr("d", geoPath)
      .attr("class", "country");
});
```

### 加上地圖線

```javascript
    var graticule = d3.geoGraticule();
    svg
      .append("path")
      .datum(graticule)
      .attr("class", "graticule line")
      .attr("d", geoPath);

    svg
      .append("path")
      .datum(graticule.outline)
      .attr("class", "graticule outline")
      .attr("d", geoPath);
```

css

```css
.graticule {
    fill: none;
    stroke: #777;
    stroke-width: .5px;
    stroke-opacity: .2;
    pointer-events: none;
}
.graticule.outline {
    stroke-width: 2px;
  }
```

{% embed url="<https://github.com/d3/d3-geo/blob/master/README.md#geoGraticule>" %}

{% embed url="<https://bl.ocks.org/mbostock/3664049>" %}

### &#x20;更新 x 與 y 軸

> merge 與 exit().remove() 是給傳入 .data 用的，如果是軸要用以下方式判斷

```javascript
    if(!document.querySelector('.wrapper-group g')) {
      // 第一次 init
      d3.select(".wrapper-group")
        .attr("transform", "translate(180, 10)")
        .append("g")
        .attr("id", "x-axis")
        .attr("transform", `translate(0,${this.height})`)
        .call(d3.axisBottom(xScale).ticks(5));
      d3.select(".wrapper-group")
        .append("g")
        .attr("id", "y-axis")
        .attr("transform", "translate(0,0)")
        .call(d3.axisLeft(yScale).ticks(5));
    } else {
      // 更新 axis
      d3.select(".wrapper-group #x-axis")
      .call(d3.axisBottom(xScale).ticks(5));
      d3.select(".wrapper-group #y-axis")
      .call(d3.axisLeft(yScale).ticks(5));
    }
```

畫 x, y 軸標籤

> 必須要手動添加 text，如果沒有顯示試著加在 svg 標籤下

```javascript
      // 畫 y 軸 標籤
      d3.select(".plot-svg")
        .append("g")
        .attr(
          "transform",
          "translate(" + this.width / 6 + ", " + this.height / 2 + ")"
        )
        .append("text")
        .attr("text-anchor", "middle")
        .attr("transform", "rotate(-90)")
        .text('test');
```

## 事件綁定

點擊後觸發顏色改變

```javascript
      ......
      .on('click', function(e) {
        d3.select(this).style("fill", 'black');
      })
```

讓顏色變深

```javascript
      .on('click', function(e) {
        d3.select(this).style("fill", d3.color(d3.select(this).attr("fill")).darker());
      })
```

## 隱藏動畫

如果要讓隱藏和顯示有動畫，必須用 opacity，`display: none` 會沒作用

```javascript
      d3.select(ele)
        .select("text")
        .transition()
        .duration(600)
        .attr("opacity", switchOn ? 1 : 0);
```

## Forcing

類似於物體碰撞等物理效果

<https://github.com/d3/d3-force>

> v3 之後的用法有改變

範例：

<https://codepen.io/EasonWang01/pen/RwRoXZb><https://bl.ocks.org/HarryStevens/f636199a46fc4b210fbca3b1dc4ef372>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://easonwang.gitbook.io/web_advance/tu-biao-lei/d3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
