用d3.js对信号处理的结果数据作图,得到可缩放交互的动态SVG图
d3.js 有何用
D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
D3.js 是一个强大的通用数据可视化工具。吕之华著电子工业出版社出版的《精通D3.js交互式数据可视化高级编程》对D3.js 有专门论述。可做参照。
用 D3.js 进行数据曲线的动态作图也很方便。只要在html文件中引入
<script src="https://d3js.org/d3.v5.min.js"></script>
即可。或下载d3.v5.min.js到本地,再行引入。
应用例
html文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>D3.js SVG多折线图表DEMO演示</title>
<link rel="stylesheet" href="css/style.css" media="screen" type="text/css" />
</head>
<body>
<script src="js/d3.v3.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>
其中,核心代码为在body标签内引入的两行:
<script src="js/d3.v3.min.js"></script>
<script src="js/index.js"></script>
数据在js/index.js
文件中,数据格式如下:
{'x':1.00E+02,'y':3.50E+02},
{'x':1.04E+02,'y':3.21E+02},
{'x':1.08E+02,'y':2.46E+02},
{'x':1.11E+02,'y':1.54E+02},
{'x':1.15E+02,'y':8.06E+01},
......
js 文件:
//************************************************************
// Data notice the structure
//************************************************************
var data = [
[
{'x':1.00E+02,'y':3.50E+02},
{'x':1.04E+02,'y':3.21E+02},
{'x':1.08E+02,'y':2.46E+02},
{'x':1.11E+02,'y':1.54E+02},
{'x':1.15E+02,'y':8.06E+01},
{'x':1.19E+02,'y':5.38E+01},
{'x':1.23E+02,'y':8.31E+01},
{'x':1.26E+02,'y':1.56E+02},
{'x':1.30E+02,'y':2.43E+02},
{'x':1.34E+02,'y':3.12E+02},
{'x':1.38E+02,'y':3.35E+02},
{'x':1.41E+02,'y':3.07E+02},
{'x':1.45E+02,'y':2.40E+02},
{'x':1.49E+02,'y':1.61E+02},
{'x':1.53E+02,'y':1.01E+02},
{'x':1.56E+02,'y':8.09E+01},
{'x':1.60E+02,'y':1.07E+02},
{'x':1.64E+02,'y':1.65E+02},
{'x':1.68E+02,'y':2.33E+02},
{'x':1.71E+02,'y':2.84E+02},
{'x':1.75E+02,'y':3.00E+02},
{'x':1.79E+02,'y':2.78E+02},
{'x':1.83E+02,'y':2.28E+02},
{'x':1.86E+02,'y':1.73E+02},
{'x':1.90E+02,'y':1.32E+02},
{'x':1.94E+02,'y':1.19E+02},
{'x':1.98E+02,'y':1.37E+02},
{'x':2.01E+02,'y':1.77E+02},
{'x':2.05E+02,'y':2.22E+02},
{'x':2.09E+02,'y':2.55E+02},
{'x':2.13E+02,'y':2.65E+02},
{'x':2.16E+02,'y':2.50E+02},
{'x':2.20E+02,'y':2.18E+02},
{'x':2.24E+02,'y':1.82E+02},
{'x':2.28E+02,'y':1.55E+02},
{'x':2.31E+02,'y':1.46E+02},
{'x':2.35E+02,'y':1.58E+02},
{'x':2.39E+02,'y':1.84E+02},
{'x':2.43E+02,'y':2.16E+02},
{'x':2.46E+02,'y':2.41E+02},
{'x':2.50E+02,'y':2.50E+02},
{'x':2.54E+02,'y':2.41E+02},
{'x':2.58E+02,'y':2.16E+02},
{'x':2.61E+02,'y':1.84E+02},
{'x':2.65E+02,'y':1.58E+02},
{'x':2.69E+02,'y':1.46E+02},
{'x':2.73E+02,'y':1.55E+02},
{'x':2.76E+02,'y':1.82E+02},
{'x':2.80E+02,'y':2.18E+02},
{'x':2.84E+02,'y':2.50E+02},
{'x':2.88E+02,'y':2.65E+02},
{'x':2.91E+02,'y':2.55E+02},
{'x':2.95E+02,'y':2.22E+02},
{'x':2.99E+02,'y':1.77E+02},
{'x':3.03E+02,'y':1.37E+02},
{'x':3.06E+02,'y':1.19E+02},
{'x':3.10E+02,'y':1.32E+02},
{'x':3.14E+02,'y':1.73E+02},
{'x':3.18E+02,'y':2.28E+02},
{'x':3.21E+02,'y':2.78E+02},
{'x':3.25E+02,'y':3.00E+02},
{'x':3.29E+02,'y':2.84E+02},
{'x':3.33E+02,'y':2.33E+02},
{'x':3.36E+02,'y':1.65E+02},
{'x':3.40E+02,'y':1.07E+02},
{'x':3.44E+02,'y':8.09E+01},
{'x':3.48E+02,'y':1.01E+02},
{'x':3.51E+02,'y':1.61E+02},
{'x':3.55E+02,'y':2.40E+02},
{'x':3.59E+02,'y':3.07E+02},
{'x':3.63E+02,'y':3.35E+02},
{'x':3.66E+02,'y':3.12E+02},
{'x':3.70E+02,'y':2.43E+02},
{'x':3.74E+02,'y':1.56E+02},
{'x':3.78E+02,'y':8.31E+01},
{'x':3.81E+02,'y':5.38E+01},
{'x':3.85E+02,'y':8.06E+01},
{'x':3.89E+02,'y':1.54E+02},
{'x':3.93E+02,'y':2.46E+02},
{'x':3.96E+02,'y':3.21E+02},
{'x':4.00E+02,'y':3.50E+02},
{'x':4.04E+02,'y':3.21E+02},
{'x':4.08E+02,'y':2.46E+02},
{'x':4.11E+02,'y':1.54E+02},
{'x':4.15E+02,'y':8.06E+01},
{'x':4.19E+02,'y':5.38E+01},
{'x':4.23E+02,'y':8.31E+01},
{'x':4.26E+02,'y':1.56E+02},
{'x':4.30E+02,'y':2.43E+02},
{'x':4.34E+02,'y':3.12E+02},
{'x':4.38E+02,'y':3.35E+02},
{'x':4.41E+02,'y':3.07E+02},
{'x':4.45E+02,'y':2.40E+02},
{'x':4.49E+02,'y':1.61E+02},
{'x':4.53E+02,'y':1.01E+02},
{'x':4.56E+02,'y':8.09E+01},
{'x':4.60E+02,'y':1.07E+02},
{'x':4.64E+02,'y':1.65E+02},
{'x':4.68E+02,'y':2.33E+02},
{'x':4.71E+02,'y':2.84E+02},
{'x':4.75E+02,'y':3.00E+02},
{'x':4.79E+02,'y':2.78E+02},
{'x':4.83E+02,'y':2.28E+02},
{'x':4.86E+02,'y':1.73E+02},
{'x':4.90E+02,'y':1.32E+02},
{'x':4.94E+02,'y':1.19E+02},
{'x':4.98E+02,'y':1.37E+02},
{'x':5.01E+02,'y':1.77E+02},
{'x':5.05E+02,'y':2.22E+02},
{'x':5.09E+02,'y':2.55E+02},
{'x':5.13E+02,'y':2.65E+02},
{'x':5.16E+02,'y':2.50E+02},
{'x':5.20E+02,'y':2.18E+02},
{'x':5.24E+02,'y':1.82E+02},
{'x':5.28E+02,'y':1.55E+02},
{'x':5.31E+02,'y':1.46E+02},
{'x':5.35E+02,'y':1.58E+02},
{'x':5.39E+02,'y':1.84E+02},
{'x':5.43E+02,'y':2.16E+02},
{'x':5.46E+02,'y':2.41E+02},
{'x':5.50E+02,'y':2.50E+02},
{'x':5.54E+02,'y':2.41E+02},
{'x':5.58E+02,'y':2.16E+02},
{'x':5.61E+02,'y':1.84E+02},
{'x':5.65E+02,'y':1.58E+02},
{'x':5.69E+02,'y':1.46E+02},
{'x':5.73E+02,'y':1.55E+02},
{'x':5.76E+02,'y':1.82E+02},
{'x':5.80E+02,'y':2.18E+02},
{'x':5.84E+02,'y':2.50E+02},
{'x':5.88E+02,'y':2.65E+02},
{'x':5.91E+02,'y':2.55E+02},
{'x':5.95E+02,'y':2.22E+02},
{'x':5.99E+02,'y':1.77E+02},
{'x':6.03E+02,'y':1.37E+02},
{'x':6.06E+02,'y':1.19E+02},
{'x':6.10E+02,'y':1.32E+02},
{'x':6.14E+02,'y':1.73E+02},
{'x':6.18E+02,'y':2.28E+02},
{'x':6.21E+02,'y':2.78E+02},
{'x':6.25E+02,'y':3.00E+02},
{'x':6.29E+02,'y':2.84E+02},
{'x':6.33E+02,'y':2.33E+02},
{'x':6.36E+02,'y':1.65E+02},
{'x':6.40E+02,'y':1.07E+02},
{'x':6.44E+02,'y':8.09E+01},
{'x':6.48E+02,'y':1.01E+02},
{'x':6.51E+02,'y':1.61E+02},
{'x':6.55E+02,'y':2.40E+02},
{'x':6.59E+02,'y':3.07E+02},
{'x':6.63E+02,'y':3.35E+02},
{'x':6.66E+02,'y':3.12E+02},
{'x':6.70E+02,'y':2.43E+02},
{'x':6.74E+02,'y':1.56E+02},
{'x':6.78E+02,'y':8.31E+01},
{'x':6.81E+02,'y':5.38E+01},
{'x':6.85E+02,'y':8.06E+01},
{'x':6.89E+02,'y':1.54E+02},
{'x':6.93E+02,'y':2.46E+02},
{'x':6.96E+02,'y':3.21E+02},
{'x':7.00E+02,'y':3.50E+02},
{'x':7.04E+02,'y':3.21E+02},
{'x':7.08E+02,'y':2.46E+02},
{'x':7.11E+02,'y':1.54E+02},
{'x':7.15E+02,'y':8.06E+01},
{'x':7.19E+02,'y':5.38E+01},
{'x':7.23E+02,'y':8.31E+01},
{'x':7.26E+02,'y':1.56E+02},
{'x':7.30E+02,'y':2.43E+02},
{'x':7.34E+02,'y':3.12E+02},
{'x':7.38E+02,'y':3.35E+02},
{'x':7.41E+02,'y':3.07E+02},
{'x':7.45E+02,'y':2.40E+02},
{'x':7.49E+02,'y':1.61E+02},
{'x':7.53E+02,'y':1.01E+02},
{'x':7.56E+02,'y':8.09E+01},
{'x':7.60E+02,'y':1.07E+02},
{'x':7.64E+02,'y':1.65E+02},
{'x':7.68E+02,'y':2.33E+02},
{'x':7.71E+02,'y':2.84E+02},
{'x':7.75E+02,'y':3.00E+02},
{'x':7.79E+02,'y':2.78E+02},
{'x':7.83E+02,'y':2.28E+02},
{'x':7.86E+02,'y':1.73E+02},
{'x':7.90E+02,'y':1.32E+02},
{'x':7.94E+02,'y':1.19E+02},
{'x':7.98E+02,'y':1.37E+02},
{'x':8.01E+02,'y':1.77E+02},
{'x':8.05E+02,'y':2.22E+02},
{'x':8.09E+02,'y':2.55E+02},
{'x':8.13E+02,'y':2.65E+02},
{'x':8.16E+02,'y':2.50E+02},
{'x':8.20E+02,'y':2.18E+02},
{'x':8.24E+02,'y':1.82E+02},
{'x':8.28E+02,'y':1.55E+02},
{'x':8.31E+02,'y':1.46E+02},
{'x':8.35E+02,'y':1.58E+02},
{'x':8.39E+02,'y':1.84E+02},
{'x':8.43E+02,'y':2.16E+02},
{'x':8.46E+02,'y':2.41E+02},
],
[
{'x':0,'y':200},
{'x':900,'y':200},
],
[
{'x':0,'y':50},
{'x':900,'y':50},
],
[
{'x':0,'y':350},
{'x':900,'y':350},
],
];
var colors = [
'steelblue',
'green',
'red',
'purple'
]
//************************************************************
// Create Margins and Axis and hook our zoom function
//************************************************************
var margin = {top: 20, right: 30, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([0, 900])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, 400])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(-height)
.tickPadding(10)
.tickSubdivide(true)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.tickPadding(10)
.tickSize(-width)
.tickSubdivide(true)
.orient("left");
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
//************************************************************
// Generate our SVG object
//************************************************************
var svg = d3.select("body").append("svg")
.call(zoom)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("class", "axis-label")
.attr("transform", "rotate(-90)")
.attr("y", (-margin.left) + 10)
.attr("x", -height/2)
.text('Axis Label');
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
//************************************************************
// Create D3 line object and draw data on our SVG object
//************************************************************
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y); });
svg.selectAll('.line')
.data(data)
.enter()
.append("path")
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.attr('stroke', function(d,i){
return colors[i%colors.length];
})
.attr("d", line);
//************************************************************
// Draw points on SVG object based on the data given
//************************************************************
var points = svg.selectAll('.dots')
.data(data)
.enter()
.append("g")
.attr("class", "dots")
.attr("clip-path", "url(#clip)");
points.selectAll('.dot')
.data(function(d, index){
var a = [];
d.forEach(function(point,i){
a.push({'index': index, 'point': point});
});
return a;
})
.enter()
.append('circle')
.attr('class','dot')
.attr("r", 2.5)
.attr('fill', function(d,i){
return colors[d.index%colors.length];
})
.attr("transform", function(d) {
return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; }
);
//************************************************************
// Zoom specific updates
//************************************************************
function zoomed() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll('path.line').attr('d', line);
points.selectAll('circle').attr("transform", function(d) {
return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; }
);
}
修改 .attr("r", 2.5)
即可修改作图打点的大小。
作图结果:
通过鼠标可对曲线缩放观察。
更多例子
可以显示音频信号的波形和频谱。与Wavosaur所得结果对比。