概述
D3基于SVG来绘制矢量图,也支持Canvas绘制标量图。提供基于DOM的操作模型,支持事件的绑定,用起来比较方便。
D3将数据集合与数据绑定做得比较优秀,提供了组件管理能力,用来实现一些图形化的拖曳式配置界面,无疑是很好的选择。
实例
简单动画
Html页面代码【./d3/demo04.html】如下:
<html>
<head>
<meta charset="UTF-8">
<script src="./Js/d3.v6.min.js"></script>
<script src="./Js/demo/demo_04.js"></script>
</head>
<body onload="makeDemo04()">
</body>
</html>
?
Javascript脚本代码【./d3/Js/demo/demo_04.js】如下:
function makeDemo04(){
var vs = ["From East","to West","at Home","is Best"];
d3.select("body")
.append("ul").selectAll("li")
.data(vs).enter()
.append("li").text(d => d)
.on("click",function(){
this.toggleState = ! this.toggleState;
d3.select(this)
.transition().duration(1000)
.style("color",this.toggleState?"red":"black");
}
);
}
折线图
Html页面代码如下
<html>
<head>
<meta charset="UTF-8">
<script src="./Js/d3.v6.min.js"></script>
<script src="./Js/demo/demo_03.js?20201230"></script>
</head>
<body onload="makeDemo03()">
<svg id="demo03" width="600" height="300" style="background-color: antiquewhite;"></svg>
</body>
</html>
Javascript脚本代码如下:
function makeDemo03(){
d3.tsv("./Dat/demo02.tsv")
.then(function(data){
var svg = d3.select("svg");
var pxX = svg.attr("width");
var pxY = svg.attr("height");
var makeScale = function (accessor,range){
return d3.scaleLinear()
.domain(d3.extent(data,accessor))
.range(range)
.nice();
}
var scX = makeScale(d => d.x , [0,pxX]);
var scY1 = makeScale(d => d.y1, [pxY,0]);
var scY2 = makeScale(d => d.y2, [pxY,0]);
var drawData = function (g,accessor,curve) {
// draw circle
g.selectAll("circle").data(data).enter()
.append("circle")
.attr("r",5)
.attr("cx",d => scX(d.x))
.attr("cy", accessor);
// draw lines
var lnMkr = d3.line().curve(curve)
.x( d => scX(d.x))
.y( accessor);
g.append("path").attr("fill","none")
.attr("d",lnMkr(data));
}
var g1 = svg.append("g");
var g2 = svg.append("g");
drawData(g1, d => scY1(d.y1) ,d3.curveStep);
drawData(g2, d => scY2(d.y2), d3.curveNatural);
g1.selectAll("circle").attr("fill","green");
g1.selectAll("path").attr("stroke","cyan");
g2.selectAll("circle").attr("fill","blue");
g2.selectAll("path").attr("stroke","red");
var axMkr = d3.axisRight(scY1);
axMkr(svg.append("g"));
// draw bottom & right axis with dimon
axMkr = d3.axisLeft(scY2);
svg.append("g")
.attr("transform","translate("+pxX+",0)")
.call(axMkr);
svg.append("g")
.call(d3.axisTop(scX))
.attr("transform","translate(0,"+pxY+")");
})
}
拖曳
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>拖拽操作</title>
<meta charset="UTF-8">
<script src="./Js/d3.v6.min.js"></script>
<script src="./Js/demo/drag.js?123"></script>
</head>
<body onload="makeDragDrop();">
<svg id="dragdrop" width="600" height="200">
<circle cx="100" cy="100" r="20" fill="red" />
<circle cx="300" cy="100" r="20" fill="green" />
<circle cx="500" cy="100" r="20" fill="blue" />
</svg>
</body>
</html>
function makeDragDrop(){
var widget = undefined, color = undefined;
var preX = 0, preY = 0;
var preCX = 0, preCY = 0;
var drag = d3.drag()
.on("start",function (e){
console.log("start",this)
color = d3.select(this).attr("fill");
widget = d3.select(this).attr("fill","gray");
preCX = parseInt(widget.attr("cx"));
preCY = parseInt(widget.attr("cy"));
var pt = d3.pointer(e);
console.log("start",e,pt)
preX = pt[0];
preY = pt[1];
console.log(preX,preY,preCX,preCY);
})
.on("drag",function(e){
var pt = d3.pointer(e);
console.log("drag",e,pt)
widget.attr("cx",preCX + pt[0]-preX).attr("cy",preCY+pt[1]-preY);
})
.on("end",function(e){
console.log("end",this)
widget.attr("fill",color);
widget = undefined;
});
drag(d3.select("#dragdrop").selectAll("circle"));
}
事件
基于选择集合,绑定事件处理函数,并可分发事件。获取时间发生所在坐标。主要通过on、dispatch、pointer、pointers来完成。
动画
提供了一些过渡效果,缩放以及滤镜。可参考Transitions,Zooming等API来实现。
生成器
这个比较有特点,可以将准备好的数据做成组件,然后放置到页面上。并且其自己也提供了一些内置的算法与数据,用来生成一些常用图形样式与组件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Symbol</title>
<meta charset="UTF-8">
<script src="./Js/d3.v6.min.js"></script>
<script>
function arrow(){
return "M0 0 L16 0 M8 4 L16 0 L8 -4";
}
function makeSymbols(){
var data = [
{"x":40, "y":10, "val":"A"},
{"x":80, "y":30, "val":"B"},
{"x":120, "y":-10, "val":"C"},
{"x":160, "y":15, "val":"D"},
{"x":200, "y":0, "val":"E"},
{"x":240, "y":10, "val":"F"},
{"x":280, "y":10, "val":"G"},
{"x":320, "y":30, "val":"H"},
{"x":360, "y":-10, "val":"I"},
{"x":400, "y":15, "val":"J"},
{"x":440, "y":0, "val":"K"},
{"x":480, "y":10, "val":"L"},
];
var symMkr = d3.symbol().size(181).type(d3.symbolStar);
var scY = d3.scaleLinear().domain([-10,30]).range([80,40]);
d3.select("#symbols").append("g")
.selectAll("patch").data(data).enter().append("path")
.attr("d",symMkr)
//.attr("d",arrow)
.attr("fill","red")
.attr("transform",d=>"translate("+d["x"]+","+scY(d["y"])+")");
var scT = d3.scaleOrdinal(d3.symbols).domain(["A","B","C","D","E","F","G","H","I","J","K","L"]);
d3.select("#symbols").append("g")
.attr("transform","translate(000,100)")
.selectAll("path").data(data).enter().append("path")
.attr("d",d=>symMkr.type(scT(d["val"]))())
.attr("fill","blue")
.attr("stroke","green").attr("stroke-width",2)
.attr("transform",d=>"translate("+d["x"]+","+scY(d["y"])+")");
}
</script>
</head>
<body onload="makeSymbols();">
<svg id="symbols" width="600" height="200"> </svg>
</body>
</html>
比例尺
d3引入这个概念给绘图带了较大的方便,可以将x、y坐标按照设定的区间进行缩放。例如
d3.scaleLineear().domain([1,9]).range([50,250])
直线与曲线
<html>
<head>
<meta charset="UTF-8">
<title>Line</title>
<meta charset="UTF-8">
<script src="./Js/d3.v6.min.js"></script>
<script>
function makeLine(){
var data =[
[1,1],[2,2],[3,4],[4,4],[5,2],
[6,2],[7,3],[8,1],[9,2]
];
var xSc = d3.scaleLinear().domain([1,9]).range([50,250]);
var ySc = d3.scaleLinear().domain([0,5]).range([175,25]);
data = data.map(d=>[ xSc(d[0]),ySc(d[1] ) ]);
d3.select("#lines").append("g")
.selectAll("circle").data(data).enter().append("circle")
.attr("r",3)
.attr("cx",d=>d[0])
.attr("cy",d=>d[1]);
//var lineMkr = d3.line();
//var lineMkr = d3.line().defined((d,i) => i==3?false:true);
// 设定线型
//var lineMkr = d3.line().curve(d3.curveLinear);
var lineMkr = d3.line().curve(d3.curveNatural);
d3.select("#lines").append("g").append("path")
.attr("d",lineMkr(data))
.attr("fill","none")
.attr("stroke","red");
}
</script>
</head>
<body onload="makeLine();">
<svg id="lines" width="600" height="300">
</svg>
</body>
</html>
布局
布局可协助计算数据相关的位置数据,便于绘制图形。
var data =[
{name:"A",votes:"30"},
{name:"B",votes:"40"},
{name:"C",votes:"20"},
];
var pie = d3.pie().value(d=>d.votes).padAngle(0.025)(data);
console.log(pie);
组件
<html>
<head>
<meta charset="UTF-8">
<title>Com</title>
<meta charset="UTF-8">
<script src="./Js/d3.v6.min.js"></script>
<script>
function sticker(sel,label){
sel.append("rect").attr("rx",5).attr("ry",5)
.attr("width",70).attr("height",30)
.attr("x",-35).attr("y",-15)
.attr("fill","none").attr("stroke","blue")
.classed("frame",true);
sel.append("text").attr("x",0).attr("y",5)
.attr("text-anchor","middle").attr("font-family","sans-serif")
.attr("font-size",14).attr("stroke","blue")
.classed("label",true)
.text( label ? label: d=>d );
}
function makeCom(){
var labels = ["Hello","World","How" ,"Are","You?"];
var scX = d3.scaleLinear().domain([0,labels.length-1]).range([100,500]);
var scY = d3.scaleLinear().domain([0,labels.length-1]).range([50,150]);
d3.select("#com").selectAll("g").data(labels).enter().append("g")
.attr("transform",(d,i) => "translate(" + scX(i)+","+scY(i)+")")
.call(sticker);
d3.select("#com").append("g")
.attr("transform","translate(75,150)")
.call(sticker,"I'am fine.")
.selectAll(".label").attr("stroke","red");
}
</script>
</head>
<body onload="makeCom();">
<svg id="com" width="600" height="500"> </svg>
</body>
</html>
本文暂时没有评论,来添加一个吧(●'◡'●)