D3
D3 or D3.js 代表 "Data Driven Documents"
選中、添加元素
select() 方法從檔案中選擇一個元素,它接收目標元素的名稱作為引數并回傳第一個匹配該名稱 HTML 節點,舉例:
const anchor = d3.select('a');
append()方法接收添加到檔案中的元素,它會把該元素添加到一個選中的 HTML 節點,然后回傳對該節點的參考,
text()方法可以設定被選中節點的文本也可以得到當前文本,若是設定文本,需要將字串作為引數傳遞,
D3 允許方法的嵌套,
下面是一個選中無序串列,并添加一個 list 元素的方法:
d3.select("ul")
.append("li")
.text("very important")
選中一組元素
使用 selectAll() 選中一組元素,它回傳一個 HTML 節點陣列,
下面是一個選中所有超鏈接元素的例子:
const anchors = d3.selectAll("a");
例子:
d3.selectAll("li")
.text("list item")
使用資料
首先使用 data() 方法去選擇 DOM 元素來和資料聯系在一起,資料集作為引數傳給該方法,
使用 enter() 方法為資料集中每一塊元素創建一個新的 DOM 元素,
下面的例子是選擇 ul 元素并根據陣列創建串列,
const dataset = ["a", "b", "c"];
d3.select("ul").selectAll("li")
.data(dataset)
.enter()
.append("li")
.text("New Item");
使用動態資料
text() 方法可以接收字串或者回呼函式作為引數,
selection.text((d) => d)
在上面的這個方法中,引數 d 指的是該資料集的一個入口,
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("h2")
.data(dataset)
.enter()
.append("h2")
// Add your code below this line
.text((d) => d + " USD");
// Add your code above this line
</script>
</body>
/*
12 USD
31 USD
22 USD
17 USD
25 USD
18 USD
29 USD
14 USD
9 USD
*/
給元素加行內樣式
使用 style() 各動態元素添加樣式,該方法接收一個以逗號 , 分隔的鍵值對作為引數,
下面是一個把選中文本設定為藍色的例子:
selection.style("color","blue");
設定選中字體:
d3.select("body")
.style("font-family","verdana");
基于資料改動樣式
在 style() 中同樣可以使用回呼函式來改動不同元素的樣式,使用引數 d 來代表資料點,
下面的例子是把資料集中小于 20 的元素設定為紅色,其它設定為綠色,
d3.selectAll("h2")
.style("color", (d) => {
if (d < 20) {
return "red";
} else return "green";
});
添加 class 屬性
attr() 方法和 style() 方法類似,他接收以逗號分割的值,并且可以使用回呼函式,
下面是一個給元素添加 container class 的例子,
selection.attr("class", "container");
動態修改元素的高度
結合上面所學創建一個條形圖 (bar chart),
<style>
.bar {
width: 25px;
height: 100px;
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", (d) => d + "px");
</script>
</body>
改變條形圖的展示
<style>
.bar {
width: 25px;
height: 100px;
/* Add your code below this line */
marign: 2px;
/* Add your code above this line */
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", (d) => (d*10 + "px")) // Change this line
</script>
</body>
SVG in d3
SVG 的全稱是:Scalable Vector Graphics,
scalable 的意思是對物體放大或者縮小不會使物體馬賽克(pixelated),
SVG 在 HTML 中使用 svg 標簽實作,
下面是一個創建 SVG 的例子:
<style>
svg {
background-color: pink;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 1
00;
const svg = d3.select("body")
// Add your code below this line
svg.append("svg").attr("width",w).attr("height",h);
// Add your code above this line
</script>
</body>
SVG 形狀
SVG 支持多種數量的形狀,例如:使用 <rect> 來表示矩形,
當把一個形狀放入 SVG 區域時,可以設定 x,y 坐標系,原點(0,0)表示左上角,x 的正值會使圖形向右移動,y 的正值向上移動,例如:把一個形狀放在 500 寬,100 高的位置需要設定 x = 250,y = 50,
對于 <rect> 來說,它有四個屬性,分別是高度、寬度和 x,y,該元素必須添加到 svg節點,而不是 body 節點,
下面的例子是設定一個矩形
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h)
// Add your code below this line
svg.append("rect")
.attr("width", 25)
.attr("height", 100)
.attr("x", 0)
.attr("y", 0);
// Add your code above this line
</script>
</body>
對資料集中的每一個資料點創建一個 bar
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
// Add your code below this line
.data(dataset)
.enter()
.append("rect")
// Add your code above this line
.attr("x", 0)
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
對每個 bar 動態設定坐標
條形圖的 y 坐標應該是一致的,而 x 坐標應該有所不同,通過設定 attr() 的回呼函式來動態設定,回呼函式接收兩個引數,第一個用 d 代表資料點本身,第二個代表資料點在陣列中的索引,格式:
selection.attr("property", (d,i) => {
})
注:不需要使用 for 或者 forEach() 回圈,
下面是擴大 30 倍的例子:
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => {
// Add your code below this line
return i*30;
// Add your code above this line
})
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
動態改變高度
實際上就是修改資料點
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", 0)
.attr("width", 25)
.attr("height", (d, i) => {
// Add your code below this line
return d * 3;
// Add your code above this line
});
</script>
</body>
倒置 SVG 元素
y 坐標也就是 y = heightOfSVG - heightOfBar 會把 bar 置于右上側,
一般公式:y = h - m * d,其中 m 是資料點 scale 的常量,
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => {
// Add your code below this line
return 100 - 3 * d;
// Add your code above this line
})
.attr("width", 25)
.attr("height", (d, i) => 3 * d);
</script>
</body>
改變 SVG 圖片的顏色
在 SVG 中,rect 形狀使用 fill 來控制顏色,
下面設定顏色為海軍藍,
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
// Add your code below this line
.attr("fill", "navy");
// Add your code above this line
</script>
</body>
加標簽
使用 SVG 的 text 給元素加標簽,該屬性同樣具有 x 和 y 屬性,
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
.attr("fill", "navy");
svg.selectAll("text")
.data(dataset)
.enter()
// Add your code below this line
.append("text")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d - 3)
.text((d, i) => d);
// Add your code above this line
</script>
<body>
給標簽加樣式
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => d * 3)
.attr("fill", "navy");
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3)
// Add your code below this line
.attr("fill","red")
.style("font-size", "25px")
// Add your code above this line
</script>
</body>
給元素添加 hover 效果
<style>
.bar:hover {
fill: brown;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
.attr("fill", "navy")
// Add your code below this line
.attr("class", "bar")
// Add your code above this line
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3);
</script>
</body>
給元素添加 tooltip
當用戶 hover 在一個元素上,tooltip 可以展示更多的資訊,
使用 SVG 的 title 給元素添加 tooltip,使用 title 配合 text() 方法給條動態添加資料,
下面是一個例子:
<style>
.bar:hover {
fill: brown;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => d * 3)
.attr("fill", "navy")
.attr("class", "bar")
// Add your code below this line
.append("title")
.text((d) => {
return d;
})
// Add your code above this line
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (d * 3 + 3))
</script>
</body>
使用 SVG 環形創建 scatterplot
scatterplot 是另一種可視化的型別,它使用圓環來遍歷資料點,每個資料點有兩個值,這些值和 x、y 坐標系結,用來定位圓環的位置,
SVG 的 circle 標簽創建圓形,
下面是一個圓形的例子:
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
// Add your code below this line
.data(dataset)
.enter()
.append("circle");
// Add your code above this line
</script>
</body>
給圓形添加屬性
圓形主要有三個屬性,cx 和 cy 屬性是坐標系,r 屬性規定圓形的半徑,
這三個屬性可以使用一個回呼函式動態設定它們的值,記住,所有在 data(dataset) 鏈后的方法會對每個資料項運行一次,回呼函式中的 d 表示當前資料集合中的資料項,可以使用括號表示法去得到資料集中的元素,如:d[0],
下面是一個例子:
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
// Add your code below this line
.attr("cx", (d) => d[0])
.attr("cy", (d) => h - d[1])
.attr("r", 5)
// Add your code above this line
</script>
</body>
給 scatterplot 添加標簽
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d, i) => d[0])
.attr("cy", (d, i) => h - d[1])
.attr("r", 5);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
// Add your code below this line
.attr("x", (d) => d[0] + 5)
.attr("y", (d) => h - d[1])
.text((d) => (d[0] + ", " + d[1]))
// Add your code above this line
</script>
</body>
創建線性 scale
scales 是一種函式,可以把資料集的資料映射為 SVG 畫布,
例子:
const scale = d3.scaleLinear();
默認情況,scale 使用物體關系,輸入和輸出的結果相同,
<body>
<script>
// Add your code below this line
const scale = d3.scaleLinear(); // Create the scale here
const output = scale(50); // Call scale with an argument here
// Add your code above this line
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
給 scale 設定 domain 和 range
假如一個資料集范圍從50 - 480,這是輸入的范圍,也叫 domain,
然后打算把這些資料點映射到 x 軸上,從 10 units 到 500 units,這就是輸出的范圍,也叫 range,
domian() 和 range() 方法為 scale 設定這些值,這兩個方法接收一個至少包含兩個元素陣列作為引數,例如:
scale.domain([50, 480]);
scale.range([50, 480]);
scale(40);
d3.scaleLinear();
最小的 domain 是 50 映射到最小的 range 為 10,
例子:
<body>
<script>
// Add your code below this line
const scale = d3.scaleLinear();
scale.domain([250, 500]).range([10, 150]);
// Add your code above this line
const output = scale(50);
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
使用 d3.max 和 d3.min 方法找出資料集的最大和最小元素
例子:
const exampleData = https://www.cnblogs.com/risejl/archive/2022/09/28/[3, 45, 10, 9];
d3.min(exampleData);
d3.max(exampleData);
有些時候資料集是嵌套的,這樣的情況下,需要給這兩個函式傳入回呼函式,這時,引數 d 代表當前內部的陣列,
const locationData = https://www.cnblogs.com/risejl/archive/2022/09/28/[[1, 7],[6, 3],[8, 3]];
const minX = d3.min(locationData, (d) => d[0]);
// minX = 1;
<body>
<script>
const positionData = [[1, 7, -4],[6, 3, 8],[2, 9, 3]]
// Add your code below this line
const output = d3.max(positionData, (d) => d[2]); // Change this line
// Add your code above this line
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
// output = 8;
使用動態 scale
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
// Padding between the SVG canvas boundary and the plot
const padding = 30;
// Create an x and y scale
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
// Add your code below this line
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
// Add your code above this line
const output = yScale(411); // Returns 30
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
使用預定義的 scale 放置元素
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 60;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d[0]))
.attr("cy", (d) => yScale(d[1]))
.attr("r", 5);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => (d[0] + ", " + d[1]))
.attr("x", (d) => xScale(d[0] + 10))
.attr("y", (d) => yScale(d[1]));
</script>
</body>
加入 Axes
axisLeft() 和 axisBottom() 方法,去渲染 x 軸和 y 軸,相對的,根據 xScale 創建 xAxis
const xAxis = d3.axisBottom(xScale);
下一步就是渲染
svg.append("g")
.attr("transform", "translate(0, " + (h - padding) + ")")
.call(xAxis);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/509711.html
標籤:其他
