# d3画布
第一个图
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
*{margin:0;padding:0}
#k{
border:1px solid red
}
</style>
<script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<body>
<div id="k"></div>
<script type="text/javascript">
let k=d3.select("#k")
let svg=k.append("svg")
.attr("width",300)
.attr("height",300)
.append("g")
.attr("transform","translate(10,10)")
.append("rect")
.attr("x",50)
.attr("width",20)
.attr("height",30)
console.log(svg)
</script>
</body>
</html>
# 使用d3绘制圆+矩形+椭圆+文字
- 圆:圆心坐标(cx,cy),半径r
- 矩形:起点坐标(x,y) 宽width 高height rx控制(border-radius)
- 椭圆:椭圆中心坐标(cx,cy) x轴半径rx y轴半径ry
- 文字: 起点坐标(x,y) 偏移dx 偏移dy
- 直线:x1 y1 x2 y2
- 多边形: points
let svg =d3.select("body").append("svg")
.attr("width",300)
.attr("height",300)
.style("border","1px solid red")
svg.append("circle")
.attr("cx",20)
.attr("cy",20)
.attr("r",20)
.style("fill",'red')
svg.append("rect")
.attr("x",50)
.attr("y",10)
.attr("width",50)
.attr("height",30)
.style("fill",'purple')
svg.append("ellipse")
.attr("cx",200)
.attr("cy",100)
.attr("rx",50)
.attr("ry",20)
.style("fill",'orange')
svg.append("text")
.text(d=>d)
.style("font-size",30)
.attr("x",(x,i)=>{
console.log(x,i)
return i*60+10
})
.attr("y",y=>y)
.attr("dy",10)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Simple Shapes</title>
<link rel="stylesheet" type="text/css" href="../../css/styles.css"/>
<script type = "text/javascript" src = "https://d3js.org/d3.v6.min.js"></script>
<style>
svg line{
stroke: grey;
stroke-width: 2;
}
svg circle{
stroke: red;
fill: none;
stroke-width: 2;
}
svg rect{
stroke: steelblue;
fill: none;
stroke-width: 2;
}
svg polygon{
stroke: green;
fill: none;
stroke-width: 2;
}
</style>
</head>
<body>
<script type="text/javascript">
var width = 600,
height = 500;
var svg = d3.select("body").append("svg");
svg.attr("height", height)
.attr("width", width);
svg.append("line") // <-A
.attr("x1", 0)
.attr("y1", 200)
.attr("x2", 100)
.attr("y2", 100);
svg.append("circle") // <-B
.attr("cx", 200)
.attr("cy", 150)
.attr("r", 50);
svg.append("rect")
.attr("x", 300) // <-C
.attr("y", 100)
.attr("width", 100) // <-D
.attr("height", 100)
.attr("rx", 5); // <-E
svg.append("polygon")
.attr("points", "450,200 500,100 550,200"); // <-F
</script>
</body>
</html>
# d3.area区域生成器
d3.area().x([x]).y0([y]).y1([y])
d3.area 可以生成一个图形生成器,输入一个数组数据,将返回值传入 path 元素的 d 属性就可以渲染出对应的 area 图形。
注意:data需要是二维数组,如果不是写成[data]这种形式作为参数
svg.append("path")
.data(data)
.attr("fill", "#cce5df")
.attr("stroke", "#69b3a2")
.attr("stroke-width", 1.5)
.attr("d", d3.area()
.x(function(d) { return funx(d.date) })
.y0(y(0))
.y1(function(d) { return funy(d.value) })
)
//funx和funy是两个方向的比例尺
var area = d3.area() // <-C
.x(function(d) { return x(d.x); }) // <-D
.y0(y(0)) // <-E
.y1(function(d) { return y(d.y); }); // <-F
svg.selectAll("path.area") // <-G
.data([data])
.enter()
.append("path")
.attr("class", "area")
.style("fill","green")
.attr("d", function(d){return area(d);})
# d3.area 断面曲线
同d3.line的curve曲线一样,tension也一样
var area = d3.area()
.x(function(d) { return x(d.x); })
.y0(y(0))
.y1(function(d) { return y(d.y); })
.curve(d3.curveCardinal.tension(1)); // <-B
# d3.symbol创建散点图
let _data = [];
_symbolTypes = d3.scaleOrdinal() // <-A
.range([d3.symbolCircle,
d3.symbolCross,
d3.symbolDiamond,
d3.symbolSquare,
d3.symbolStar,
d3.symbolTriangle,
d3.symbolWye
]);
function renderSymbols() { // <-B
_data.forEach(function (list, i) {
var symbols = _bodyG.selectAll("path._" + i)
.data(list);
symbols.enter()
.append("path")
.merge(symbols)
.attr("class", "symbol _" + i)
.classed(_symbolTypes(i), true)
.transition() // <-C
.attr("transform", function(d){
return "translate(" // <-D
+ _x(d.x)
+ ","
+ _y(d.y)
+ ")";
})
.attr("d",
d3.symbol() // <-E
.type(_symbolTypes(i))
);
});
}
# d3.stack堆栈图
var stack = d3.stack() // <-A
.keys(['value1', 'value2', 'value3'])
.offset(d3.stackOffsetNone);
console.log(_data)
var series = stack(_data); //<-B
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Stacked Area Chart</title>
<link rel="stylesheet" type="text/css" href="../../css/styles.css"/>
<script type = "text/javascript" src = "https://d3js.org/d3.v6.min.js"></script>
</head>
<body>
<script type="text/javascript">
function stackedAreaChart() {
var _chart = {};
var _width = 900, _height = 450,
_margins = {top: 30, left: 30, right: 30, bottom: 30},
_x, _y,
_data = [],
_colors = d3.scaleOrdinal(d3.schemeCategory10),
_svg,
_bodyG,
_line;
_chart.render = function () {
if (!_svg) {
_svg = d3.select("body").append("svg")
.attr("height", _height)
.attr("width", _width);
renderAxes(_svg);
defineBodyClip(_svg);
}
renderBody(_svg);
};
function renderAxes(svg) {
var axesG = svg.append("g")
.attr("class", "axes");
renderXAxis(axesG);
renderYAxis(axesG);
}
function renderXAxis(axesG) {
var xAxis = d3.axisBottom()
.scale(_x.range([0, quadrantWidth()]));
axesG.append("g")
.attr("class", "x axis")
.attr("transform", function () {
return "translate(" + xStart() + "," + yStart() + ")";
})
.call(xAxis);
d3.selectAll("g.x g.tick")
.append("line")
.classed("grid-line", true)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 0)
.attr("y2", -quadrantHeight());
}
function renderYAxis(axesG) {
var yAxis = d3.axisLeft()
.scale(_y.range([quadrantHeight(), 0]));
axesG.append("g")
.attr("class", "y axis")
.attr("transform", function () {
return "translate(" + xStart() + "," + yEnd() + ")";
})
.call(yAxis);
d3.selectAll("g.y g.tick")
.append("line")
.classed("grid-line", true)
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", quadrantWidth())
.attr("y2", 0);
}
function defineBodyClip(svg) {
var padding = 5;
svg.append("defs")
.append("clipPath")
.attr("id", "body-clip")
.append("rect")
.attr("x", 0 - padding)
.attr("y", 0)
.attr("width", quadrantWidth() + 2 * padding)
.attr("height", quadrantHeight());
}
function renderBody(svg) {
if (!_bodyG)
_bodyG = svg.append("g")
.attr("class", "body")
.attr("transform", "translate("
+ xStart() + ","
+ yEnd() + ")")
.attr("clip-path", "url(#body-clip)");
console.log(d3.stackOffsetNone)
var stack = d3.stack() // <-A
.keys(['value1', 'value2', 'value3'])
.offset(d3.stackOffsetNone);
console.log(_data)
var series = stack(_data); //<-B
console.log(series)
renderLines(series);
renderAreas(series);
}
function renderLines(series) {
_line = d3.line()
.x(function (d, i) {
return _x(i); //<-C
})
.y(function (d) {
return _y(d[1]); //<-D
});
var linePaths = _bodyG.selectAll("path.line")
.data(series);
linePaths.enter()
.append("path")
.merge(linePaths)
.style("stroke", function (d, i) {
return _colors(i);
})
.attr("class", "line")
.transition()
.attr("d", function (d) {
return _line(d);
});
}
function renderAreas(series) {
console.log(series)
var area = d3.area()
.x(function (d, i) {
return _x(i); //<-E
})
.y0(function(d){return _y(d[0]);}) //<-F
.y1(function (d) {
return _y(d[1]); //<-G
});
var areaPaths = _bodyG.selectAll("path.area")
.data(series);
areaPaths.enter()
.append("path")
.merge(areaPaths)
.style("fill", function (d, i) {
return _colors(i);
})
.attr("class", "area")
.transition()
.attr("d", function (d) {
return area(d);
});
}
function xStart() {
return _margins.left;
}
function yStart() {
return _height - _margins.bottom;
}
function xEnd() {
return _width - _margins.right;
}
function yEnd() {
return _margins.top;
}
function quadrantWidth() {
return _width - _margins.left - _margins.right;
}
function quadrantHeight() {
return _height - _margins.top - _margins.bottom;
}
_chart.width = function (w) {
if (!arguments.length) return _width;
_width = w;
return _chart;
};
_chart.height = function (h) {
if (!arguments.length) return _height;
_height = h;
return _chart;
};
_chart.margins = function (m) {
if (!arguments.length) return _margins;
_margins = m;
return _chart;
};
_chart.colors = function (c) {
if (!arguments.length) return _colors;
_colors = c;
return _chart;
};
_chart.x = function (x) {
if (!arguments.length) return _x;
_x = x;
return _chart;
};
_chart.y = function (y) {
if (!arguments.length) return _y;
_y = y;
return _chart;
};
_chart.data = function (data) {
if (!arguments.length) return _data;
_data = data;
return _chart;
};
return _chart;
}
function randomData() {
return Math.random() * 9;
}
function update() {
data = d3.range(numberOfDataPoint).map(function (i) {
return {value1: randomData(), value2: randomData(), value3: randomData()};
});
chart.data(data).render();
}
var numberOfDataPoint = 51,
data = [];
var chart = stackedAreaChart()
.x(d3.scaleLinear().domain([0, numberOfDataPoint - 1]))
.y(d3.scaleLinear().domain([0, 26]));
update();
</script>
<div class="control-group">
<button onclick="update()">Update</button>
</div>
</body>
</html>