svg的基本形狀
- line 線條
- x1 定義線條起點的 x 座標
- y1 定義線條起點的 y 座標
- x2 定義線條終點的 x 座標
- y2 定義線條終點的 y 座標
- polyline 折線
- points 定義折線的一系列點座標,座標間用空格隔開
- circle 圓
- cx 定義圓心的 x 座標
- cy 定義圓心的 y 座標
- r 定義圓的半徑 r
- ellipse 橢圓
- cx 定義圓心的 x 座標
- cy 定義圓心的 y 座標
- rx 定義橢圓在 x 軸方向上的半徑
- ry 定義橢圓在 y 軸方向上的半徑
- rect 矩形
- x 定義矩形的左上角的 x 座標
- y 定義矩形的左上角的 y 座標
- width 定義矩形的寬
- height 定義矩形的高
- polygon 多邊形
- points 定義多邊形的頂點座標,座標間用空格隔開
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.line,
.polyline {
fill: none;
stroke: steelblue;
stroke-width: 2;
}
.circle {
stroke: steelblue;
stroke-width: 2;
fill: red;
fill-opacity: .7;
}
.ellipse {
stroke: steelblue;
stroke-width: 2;
fill: yellow;
fill-opacity: .7;
}
.rect,
.polygon {
stroke: steelblue;
stroke-width: 2;
fill: pink;
fill-opacity: .7;
}
</style>
</head>
<body>
<script src="../d3.js"></script>
<script>
const svg = d3.select('body').append('svg')
svg.attr('width', 1000)
.attr('height', 400)
svg.append('line')
.attr('x1', 0)
.attr('y1', 200)
.attr('x2', 100)
.attr('y2', 100)
.classed('line', true)
svg.append('circle')
.attr('cx', 200)
.attr('cy', 150)
.attr('r', 50)
.classed('circle', true)
svg.append('ellipse')
.attr('cx', 350)
.attr('cy', 150)
.attr('rx', 75)
.attr('ry', 50)
.classed('ellipse', true)
svg.append('rect')
.attr('x', 450)
.attr('y', 100)
.attr('width', 100)
.attr('height', 100)
.attr('rx', 10)
.attr('ry', 20)
.classed('rect', true)
svg.append('polygon')
.attr('points', '600,200 650,100 700,200')
.classed('polygon', true)
svg.append('polyline')
.attr('points', '750,133 780,100 850,155 900,122')
.classed('polyline', true)
</script>
</body>
</html>
複製程式碼
效果如下:
線條生成器 line()
d3 的生成器可以幫助我們將資料對映到svg的屬性中,簡化了我們對svg的操作。線條生成器就可以幫助我們十分簡單的繪製路徑。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.line {
fill: none;
stroke-width: 2;
stroke: steelblue;
}
.dot {
fill: #fff;
stroke: steelblue;
}
</style>
</head>
<body>
<h4>Interpolation Mode:</h4>
<div class="control-group">
<button onclick="render(d3.curveLinear)">linear</button>
<button onclick="render(d3.curveLinearClosed)"> linear closed</button>
<button onclick="render(d3.curveStepBefore)">step before</button>
<button onclick="render(d3.curveStepAfter)">step after</button>
<button onclick="render(d3.curveBasis)">basic</button>
<button onclick="render(d3.curveBasisOpen)">basic open</button>
<button onclick="render(d3.curveBasisClosed)">basic closed</button>
<button onclick="render(d3.curveBundle)">bundle</button>
<button onclick="render(d3.curveCardinal)">cardinal</button>
<button onclick="render(d3.curveCardinalOpen)">cardinal open</button>
<button onclick="render(d3.curveCardinalClosed)">cardinal closed</button>
<button onclick="render(d3.curveMonotoneY)">monotone y</button>
<button onclick="render(d3.curveCatmullRom)">catmull rom</button>
</div>
<script src="../d3.js"></script>
<script>
const width = 500,
height = 500,
margin = 50,
x = d3.scaleLinear()
.domain([0, 10])
.range([margin, width - margin]),
y = d3.scaleLinear()
.domain([0, 10])
.range([height - margin, margin])
const data = [
[
{x: 0, y: 5},
{x: 1, y: 9},
{x: 2, y: 7},
{x: 3, y: 5},
{x: 4, y: 3},
{x: 6, y: 4},
{x: 7, y: 2},
{x: 8, y: 3},
{x: 9, y: 2}
],
d3.range(10).map(function (i) {
return {x: i, y: Math.sin(i) + 5}
})
]
const svg = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height)
const xScale = d3.scaleLinear()
.domain([0, 10])
.range([0, width - 2 * margin])
const xAxis = d3.axisBottom()
.scale(xScale)
svg.append('g')
.classed('x-axis', true)
.attr('transform', function () {
return `translate(${margin}, ${height - margin})`
})
.call(xAxis)
const yScale = d3.scaleLinear()
.domain([10, 0])
.range([0, height - 2 * margin])
const yAxis = d3.axisLeft()
.scale(yScale)
svg.append('g')
.classed('y-axis', true)
.attr('transform', function () {
return `translate(${margin}, ${margin})`
})
.call(yAxis)
function render(mode) {
const line = d3.line()
.x(function (d) {
return x(d.x)
})
.y(function (d) {
return y(d.y)
})
.curve(mode)
const lines = svg.selectAll('path.line')
.data(data)
lines.enter()
.append('path')
.classed('line', true)
.merge(lines)
.attr('d', function (d) {
return line(d)
})
}
function renderDots() {
data.forEach(function (item) {
svg.append('g').selectAll('circle')
.data(item)
.enter()
.append('circle')
.classed('dot', true)
.attr('cx', function (d) {
return x(d.x)
})
.attr('cy', function (d) {
return y(d.y)
})
.attr('r', 4.5)
})
}
render(d3.curveLinear)
renderDots()
</script>
</body>
</html>
複製程式碼
效果如下:
在圖表中,我們的線條是用 path 繪製的而不是 line,我們用line生成器來對資料進行處理,直接生成了 path 的 d 屬性而不用我們去計算。
const line = d3.line()
.x(function (d) {
return x(d.x)
})
.y(function (d) {
return y(d.y)
})
.curve(mode)
複製程式碼
上面這段程式碼就定義了一個線條生成器,我們通過 x() y() 去指定拿來計算座標的 x y 值,返回資料在尺度中的對應值,因為這才是對應到圖表中的座標,然後 curve() 可以指定線條的型別。
檢視內建的曲線型別可以在 github.com/d3/d3-shape…
區域生成器 area()
程式碼和線條生成器的示例一樣,在 render 函式里加入以下:
const area = d3.area()
.x(function (d) {
return x(d.x)
})
.y0(y(0))
.y1(function (d) {
return y(d.y)
})
.curve(mode)
const areas = svg.selectAll('path.area')
.data([data])
areas.enter()
.append('path')
.classed('area', true)
.merge(areas)
.attr('d', function (d) {
return area(d)
})
複製程式碼
效果如下:
線上圖的基礎上,我們在其中多渲染了面積的部分,同樣是藉助於 path 元素。
區域生成器需要我們去定義上邊界和下邊界 x0() x1() y0() y1(),這裡因為我們的 x0() x1()是同樣的,可以用 x() 方法統一指定。
curve() 指定區域生成器的曲線型別,和線條生成器一般用同種。
圓弧生成器 arc()
圓弧生成器同樣要和 path 一起使用。
常使用的設定有:
- arc.innerRadius() 設定環的內半徑
- arc.outerRadius() 設定環的外半徑
- arc.cornerRadius() 設定拐角半徑
- arc.startAngle() 設定起始角度的取值,預設讀取資料中的 startAngle 屬性
- arc.endAngle() 設定終止角度的取值,預設讀取資料中的 endAngle 屬性
- arc.padAngle() 設定相鄰兩個環之間的間隙角度,預設讀取資料中的 padAngle 屬性
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="control-group">
<button onclick="render(0)">circle</button>
<button onclick="render(100)">annulus</button>
<button onclick="render(0, Math.PI)">circle sector</button>
<button onclick="render(100, Math.PI)">annulus sector</button>
</div>
<script src="../d3.js"></script>
<script>
const width = 400,
height = 400,
colors = d3.scaleOrdinal(d3.schemeCategory10)
const svg = d3.select('body').append('svg')
.classed('pie', true)
.attr('height', height)
.attr('width', width)
function render(innerRadius, endAngle) {
if (!endAngle) {
endAngle = 2 * Math.PI
}
const data = [
{startAngle: 0, endAngle: 0.1 * endAngle},
{startAngle: 0.1 * endAngle, endAngle: 0.2 * endAngle},
{startAngle: 0.2 * endAngle, endAngle: 0.4 * endAngle},
{startAngle: 0.4 * endAngle, endAngle: 0.6 * endAngle},
{startAngle: 0.6 * endAngle, endAngle: 0.7 * endAngle},
{startAngle: 0.7 * endAngle, endAngle: 0.9 * endAngle},
{startAngle: 0.9 * endAngle, endAngle: endAngle}
]
const arc = d3.arc()
.outerRadius(200)
.innerRadius(innerRadius)
svg.select('g').remove()
svg.append('g')
.attr('transform', 'translate(200, 200)')
.selectAll('path')
.data(data)
.enter()
.append('path')
.classed('arc', true)
.attr('fill', function (d, i) {
return colors(i)
})
.attr('d', function (d, i) {
return arc(d)
})
}
render(0)
</script>
</body>
</html>
複製程式碼
效果如下:
圓弧的過渡
給圓弧新增過渡效果時,要使用中間幀 attrTween()。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="../d3.js"></script>
<script>
const width = 400,
height = 400,
endAngle = 2 * Math.PI,
colors = d3.scaleOrdinal(d3.schemeCategory10)
const svg = d3.select('body').append('svg')
.classed('pie', true)
.attr('width', width)
.attr('height', height)
function render(innerRadius) {
const data = [
{startAngle: 0, endAngle: 0.1 * endAngle},
{startAngle: 0.1 * endAngle, endAngle: 0.2 * endAngle},
{startAngle: 0.2 * endAngle, endAngle: 0.4 * endAngle},
{startAngle: 0.4 * endAngle, endAngle: 0.6 * endAngle},
{startAngle: 0.6 * endAngle, endAngle: 0.7 * endAngle},
{startAngle: 0.7 * endAngle, endAngle: 0.9 * endAngle},
{startAngle: 0.9 * endAngle, endAngle: endAngle}
]
const arc = d3.arc().outerRadius(200).innerRadius(innerRadius)
svg.select('g').remove()
svg.append('g')
.attr('transform', 'translate(200, 200)')
.selectAll('path')
.data(data)
.enter()
.append('path')
.classed('arc', true)
.attr('fill', (d, i) => colors(i))
.transition().duration(1000).delay(3000)
.attrTween('d', d => {
const scale = d3.scaleLinear().domain([0, 1]).range([{startAngle: 0, endAngle: 0}, d])
return t => arc(scale(t))
})
}
render(100)
</script>
</body>
</html>
複製程式碼
效果如下: