3
我正嘗試用d3js創建一個典型的波德圖。用Matlab創建的典型波特圖如下所示:使用次要和主要蜱創建波德圖d3js
現在我已經來了很遠看到:http://plnkr.co/edit/BpWis5uhC8KM2tRbXMk3或嵌入在這個職位的片段。
我有的問題是,我想,如在matlab波特圖,有主要和次要的蜱蟲。主蜱是堅實的,而小蜱點綴。不幸的是,我似乎無法做到這一點。我已經從嘗試了各種解決方案:
Major and minor ticks with different style, whole page covered D3? Major and minor ticks with V3 of D3? d3.js alternative to axis.tickSubdivide? http://bl.ocks.org/vjpgo/4689130 http://bl.ocks.org/mbostock/4349486
<!DOCTYPE html>
<html lang="en">
<head>
<title>LOG</title>
<meta charset="utf-8">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//mathjs.org/js/lib/math.js"></script>
<style type="text/css">
svg {
font: 10px sans-serif;
shape-rendering: crispEdges;
}
rect {
fill: transparent;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
clip-path: url(#clip);
}
.grid .tick {
stroke: lightgrey;
opacity: 0.7;
}
.grid path {
stroke-width: 0;
}
</style>
<script type="text/javascript">
\t function linspace(a,b,n) {
\t \t var every = (b-a)/(n-1),
\t \t \t range = [];
\t \t for (i = a; i < b; i += every)
\t \t \t range.push(i);
\t \t return range.length == n ? range : range.concat(b);
\t }
\t
\t function logspace(a,b,n) {
\t \t return linspace(a,b,n).map(function(x) { return Math.pow(10,x); });
\t }
\t
\t function isInteger(value) {
\t \t return typeof value === "number" &&
\t \t \t isFinite(value) &&
\t \t \t Math.floor(value) === value;
\t };
\t
\t function leadlag(f) {
\t \t w = 2*math.pi*f;
\t \t s = math.complex(0,w);
\t \t K = 1;
\t \t fz = 20;
\t \t fp = 40;
\t \t wz = 2*math.pi*fz;
\t \t wp = 2*math.pi*fp;
\t \t return math.multiply(K,math.multiply(math.divide(wp,wz),math.divide(math.add(s,wz),(math.add(s,wp)))));
\t };
\t
\t function angle(f) {
\t \t return math.atan2(f.im,f.re);
\t };
\t
\t function deg2rad(deg) {
\t \t return deg * math.pi/180;
\t };
\t function rad2deg(rad) {
\t \t return rad * 180/math.pi;
\t };
\t
\t function mag2db(mag) {
\t \t return 20 * Math.log10(mag);
\t }
\t
\t function db2mag(db) {
\t \t return math.pow(10,db/20);
\t }
</script>
</head>
<body>
<div id="plotmagnitude"></div>
<div id="plotphase"></div>
<script type="text/javascript">
\t var margin = {
top: 20,
right: 20,
bottom: 35,
left: 50
};
\t
\t var width = 450 - margin.left - margin.right;
\t var height = 250 - margin.top - margin.bottom;
\t
\t var range = logspace(0,3,1000);
var x = d3.scale.log()
\t \t .domain([1, range[range.length-1].toFixed()])
\t \t .range([0, width]);
var y = d3.scale.linear()
\t \t .domain([-10, 2])
\t \t .range([height, 0]);
var xAxis1 = d3.svg.axis()
\t \t .scale(x)
\t \t .orient("bottom")
\t \t .ticks(1,"0.1s")
\t \t .innerTickSize(-6)
\t \t .outerTickSize(0)
\t \t .tickPadding(7);
var yAxis1 = d3.svg.axis()
\t \t .scale(y)
\t \t .orient("left")
\t \t .ticks(5)
\t \t .innerTickSize(-6)
\t \t .outerTickSize(0)
\t \t .tickPadding(7);
var xAxis2 = d3.svg.axis()
\t \t .scale(x)
\t \t .orient("top")
\t \t .ticks(5)
\t \t .innerTickSize(-6)
\t \t .tickPadding(-20)
\t \t .outerTickSize(0)
\t \t .tickFormat("");
var yAxis2 = d3.svg.axis()
\t \t .scale(y)
\t \t .orient("left")
\t \t .ticks(5)
\t \t .innerTickSize(6)
\t \t .tickPadding(-20)
\t \t .outerTickSize(0)
\t \t .tickFormat("");
var xGrid = d3.svg.axis()
\t \t .scale(x)
\t \t .orient("bottom")
\t \t .ticks(5)
\t \t .tickSize(-height, -height, 0)
\t \t .tickFormat("");
var yGrid = d3.svg.axis()
\t \t .scale(y)
\t \t .orient("left")
\t \t .ticks(5)
\t \t .tickSize(-width, -width, 0)
\t \t .tickFormat("");
\t
var line = d3.svg.line()
\t \t .x(function(d) {
\t \t \t return x(d.x);
\t \t })
\t \t .y(function(d) {
\t \t \t return y(d.y);
\t \t })
\t \t .interpolate("linear");
\t
var zoom = d3.behavior.zoom()
\t \t .x(x)
\t \t .y(y)
\t \t .scaleExtent([1, 1])
\t \t .on("zoom",redraw);
var plotMagnitude = d3.select("#plotmagnitude").append("svg")
\t \t .attr("width",width + margin.left + margin.right)
\t \t .attr("height",height + margin.top + margin.bottom)
\t \t .append("g")
\t \t .attr("transform","translate(" + margin.left + "," + margin.top + ")")
\t \t .call(zoom);
\t
// Add x grid
plotMagnitude.append("g")
\t \t .attr("class","x grid")
\t \t .attr("transform","translate(0," + height + ")")
\t \t .call(xGrid);
\t \t
// Add y grid
plotMagnitude.append("g")
\t \t .attr("class","y grid")
\t \t .call(yGrid);
plotMagnitude.append("g")
\t \t .attr("class","x1 axis")
\t \t .attr("transform","translate(0," + height + ")")
\t \t .call(xAxis1);
plotMagnitude.append("g")
\t \t .attr("class","y1 axis")
\t \t .call(yAxis1);
/* append additional X axis */
plotMagnitude.append("g")
\t \t .attr("class","x2 axis")
\t \t .attr("transform","translate(" + [0, 0] + ")")
\t \t .call(xAxis2);
/* append additional y axis */
plotMagnitude.append("g")
\t \t .attr("class","y2 axis")
\t \t .attr("transform","translate(" + [width, 0] + ")")
\t \t .call(yAxis2);
// Add x axis label
plotMagnitude.append("text")
.attr("transform","translate(" + (width/2) + "," + (height + margin.bottom) + ")")
.style("font-size","15")
.style("text-anchor","middle")
.text("x axis");
// Add y axis label
plotMagnitude.append("text")
.attr("transform", "rotate(-90)")
.attr("y",0 - margin.left)
.attr("x",0 - (height/2))
.attr("dy", "1em")
.style("font-size","15")
.style("text-anchor", "middle")
.text("y axis");
plotMagnitude.append("defs").append("clipPath")
\t \t .attr("id", "clip")
\t \t .append("rect")
\t \t .attr("width", width)
\t \t .attr("height", height);
plotMagnitude.append("rect")
\t \t .attr("width", width)
\t \t .attr("height", height);
function redraw() {
\t \t plotMagnitude.select(".x1.axis").call(xAxis1);
\t \t plotMagnitude.select(".y1.axis").call(yAxis1);
\t \t plotMagnitude.select(".x2.axis").call(xAxis2);
\t \t plotMagnitude.select(".y2.axis").call(yAxis2);
\t \t plotMagnitude.select(".x.grid").call(xGrid);
\t \t plotMagnitude.select(".y.grid").call(yGrid);
\t \t
\t \t var series = [];
\t \t var data1 = [];
\t \t var data2 = [];
\t \t var data3 = [];
\t \t for (var i = 0; i < range.length; i++) {
\t \t \t data1.push({
\t \t \t \t x: range[i],
\t \t \t \t y: leadlag(range[i])
\t \t \t });
\t \t \t data2.push({
\t \t \t \t x: range[i],
\t \t \t \t y: mag2db(math.abs(leadlag(range[i])))
\t \t \t });
\t \t \t
\t \t \t data3.push({
\t \t \t \t x: range[i],
\t \t \t \t y: rad2deg(angle(leadlag(range[i])))
\t \t \t });
\t \t }
\t \t series.push({data: data2, width: 1, color: 'blue', stroke: "0,0", legend: "MAG" });
\t \t var series = plotMagnitude.selectAll(".line").data(series);
\t \t series.enter().append('path');
\t \t series.attr("class","line")
\t \t \t .attr("d",function(d) { return line(d.data); })
\t \t \t .attr("stroke-width", function(d) { return d.width; })
\t \t \t .style("stroke", function(d) { return d.color; })
\t \t \t .style("stroke-dasharray", function(d) { return d.stroke; });
\t }
\t $(function() {
\t \t redraw();
\t });
</script>
</body>
</html>
謝謝您的回覆!起初,我對這個答案很滿意。但是,我正在創造一個預兆。這包括兩個在彼此之下的地塊。幅度圖,即上圖,通常沒有X軸標籤來節省空間,因爲它是重複的w.r.t對下面的圖,相圖。在這個解決方案之後,我會做的下一步是創建兩個圖,一個沒有x標籤,一個沒有x標籤。我願意提出改進代碼的建議,因爲我感覺它有點臃腫? –
@ WG-,如果兩個圖上的x軸均匹配,則此解決方案仍然有效。循環使用標籤的軸並從**兩個**圖中選擇相應的網格線。 – Mark
我剛試過你的解決方案,當我有兩個情節工作; http://plnkr.co/edit/HE2f7JLZOjXV0JLf7iGY?p=preview,但它似乎不工作?它不會選擇其他x軸刻度? –