我正在尝试用d3js创建一个典型的波特图。使用Matlab创建的典型波特图如下所示:
现在我已经相当了解: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">
function linspace(a,b,n) {
var every = (b-a)/(n-1),
range = [];
for (i = a; i < b; i += every)
range.push(i);
return range.length == n ? range : range.concat(b);
}
function logspace(a,b,n) {
return linspace(a,b,n).map(function(x) { return Math.pow(10,x); });
}
function isInteger(value) {
return typeof value === "number" &&
isFinite(value) &&
Math.floor(value) === value;
};
function leadlag(f) {
w = 2*math.pi*f;
s = math.complex(0,w);
K = 1;
fz = 20;
fp = 40;
wz = 2*math.pi*fz;
wp = 2*math.pi*fp;
return math.multiply(K,math.multiply(math.divide(wp,wz),math.divide(math.add(s,wz),(math.add(s,wp)))));
};
function angle(f) {
return math.atan2(f.im,f.re);
};
function deg2rad(deg) {
return deg * math.pi / 180;
};
function rad2deg(rad) {
return rad * 180 / math.pi;
};
function mag2db(mag) {
return 20 * Math.log10(mag);
}
function db2mag(db) {
return math.pow(10,db / 20);
}
</script>
</head>
<body>
<div id="plotmagnitude"></div>
<div id="plotphase"></div>
<script type="text/javascript">
var margin = {
top: 20,
right: 20,
bottom: 35,
left: 50
};
var width = 450 - margin.left - margin.right;
var height = 250 - margin.top - margin.bottom;
var range = logspace(0,3,1000);
var x = d3.scale.log()
.domain([1, range[range.length-1].toFixed()])
.range([0, width]);
var y = d3.scale.linear()
.domain([-10, 2])
.range([height, 0]);
var xAxis1 = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(1,"0.1s")
.innerTickSize(-6)
.outerTickSize(0)
.tickPadding(7);
var yAxis1 = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.innerTickSize(-6)
.outerTickSize(0)
.tickPadding(7);
var xAxis2 = d3.svg.axis()
.scale(x)
.orient("top")
.ticks(5)
.innerTickSize(-6)
.tickPadding(-20)
.outerTickSize(0)
.tickFormat("");
var yAxis2 = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.innerTickSize(6)
.tickPadding(-20)
.outerTickSize(0)
.tickFormat("");
var xGrid = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5)
.tickSize(-height, -height, 0)
.tickFormat("");
var yGrid = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickSize(-width, -width, 0)
.tickFormat("");
var line = d3.svg.line()
.x(function(d) {
return x(d.x);
})
.y(function(d) {
return y(d.y);
})
.interpolate("linear");
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 1])
.on("zoom",redraw);
var plotMagnitude = d3.select("#plotmagnitude").append("svg")
.attr("width",width + margin.left + margin.right)
.attr("height",height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
// Add x grid
plotMagnitude.append("g")
.attr("class","x grid")
.attr("transform","translate(0," + height + ")")
.call(xGrid);
// Add y grid
plotMagnitude.append("g")
.attr("class","y grid")
.call(yGrid);
plotMagnitude.append("g")
.attr("class","x1 axis")
.attr("transform","translate(0," + height + ")")
.call(xAxis1);
plotMagnitude.append("g")
.attr("class","y1 axis")
.call(yAxis1);
/* append additional X axis */
plotMagnitude.append("g")
.attr("class","x2 axis")
.attr("transform","translate(" + [0, 0] + ")")
.call(xAxis2);
/* append additional y axis */
plotMagnitude.append("g")
.attr("class","y2 axis")
.attr("transform","translate(" + [width, 0] + ")")
.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")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
plotMagnitude.append("rect")
.attr("width", width)
.attr("height", height);
function redraw() {
plotMagnitude.select(".x1.axis").call(xAxis1);
plotMagnitude.select(".y1.axis").call(yAxis1);
plotMagnitude.select(".x2.axis").call(xAxis2);
plotMagnitude.select(".y2.axis").call(yAxis2);
plotMagnitude.select(".x.grid").call(xGrid);
plotMagnitude.select(".y.grid").call(yGrid);
var series = [];
var data1 = [];
var data2 = [];
var data3 = [];
for (var i = 0; i < range.length; i++) {
data1.push({
x: range[i],
y: leadlag(range[i])
});
data2.push({
x: range[i],
y: mag2db(math.abs(leadlag(range[i])))
});
data3.push({
x: range[i],
y: rad2deg(angle(leadlag(range[i])))
});
}
series.push({data: data2, width: 1, color: 'blue', stroke: "0,0", legend: "MAG" });
var series = plotMagnitude.selectAll(".line").data(series);
series.enter().append('path');
series.attr("class","line")
.attr("d",function(d) { return line(d.data); })
.attr("stroke-width", function(d) { return d.width; })
.style("stroke", function(d) { return d.color; })
.style("stroke-dasharray", function(d) { return d.stroke; });
}
$(function() {
redraw();
});
</script>
</body>
</html>
答案 0 :(得分:1)
似乎您的“主要”刻度被定义为具有标签的刻度,因此难以找到它们然后找到相应的网格线。
怎么样:
d3.selectAll('.x1.axis>.tick') // find all the x axis ticks and loop
.each(function(d,i){
if (d3.select(this).select('text').text() === ""){ // if they have no label
d3.select('.x.grid>.tick:nth-child(' + (i + 1) + ')') // get the corresponding grid line
.style("stroke-dasharray", "3,3"); // and make it dashed
}
});
完整代码:
<!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">
function linspace(a,b,n) {
var every = (b-a)/(n-1),
range = [];
for (i = a; i < b; i += every)
range.push(i);
return range.length == n ? range : range.concat(b);
}
function logspace(a,b,n) {
return linspace(a,b,n).map(function(x) { return Math.pow(10,x); });
}
function isInteger(value) {
return typeof value === "number" &&
isFinite(value) &&
Math.floor(value) === value;
};
function leadlag(f) {
w = 2*math.pi*f;
s = math.complex(0,w);
K = 1;
fz = 20;
fp = 40;
wz = 2*math.pi*fz;
wp = 2*math.pi*fp;
return math.multiply(K,math.multiply(math.divide(wp,wz),math.divide(math.add(s,wz),(math.add(s,wp)))));
};
function angle(f) {
return math.atan2(f.im,f.re);
};
function deg2rad(deg) {
return deg * math.pi / 180;
};
function rad2deg(rad) {
return rad * 180 / math.pi;
};
function mag2db(mag) {
return 20 * Math.log10(mag);
}
function db2mag(db) {
return math.pow(10,db / 20);
}
</script>
</head>
<body>
<div id="plotmagnitude"></div>
<div id="plotphase"></div>
<script type="text/javascript">
var margin = {
top: 20,
right: 20,
bottom: 35,
left: 50
};
var width = 450 - margin.left - margin.right;
var height = 250 - margin.top - margin.bottom;
var range = logspace(0,3,1000);
var x = d3.scale.log()
.domain([1, range[range.length-1].toFixed()])
.range([0, width]);
var y = d3.scale.linear()
.domain([-10, 2])
.range([height, 0]);
var xAxis1 = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(1,"0.1s")
.innerTickSize(-6)
.outerTickSize(0)
.tickPadding(7);
var yAxis1 = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.innerTickSize(-6)
.outerTickSize(0)
.tickPadding(7);
var xAxis2 = d3.svg.axis()
.scale(x)
.orient("top")
.ticks(5)
.innerTickSize(-6)
.tickPadding(-20)
.outerTickSize(0)
.tickFormat("");
var yAxis2 = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.innerTickSize(6)
.tickPadding(-20)
.outerTickSize(0)
.tickFormat("");
var xGrid = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5)
.tickSize(-height, -height, 0)
.tickFormat("");
var yGrid = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5)
.tickSize(-width, -width, 0)
.tickFormat("");
var line = d3.svg.line()
.x(function(d) {
return x(d.x);
})
.y(function(d) {
return y(d.y);
})
.interpolate("linear");
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 1])
.on("zoom",redraw);
var plotMagnitude = d3.select("#plotmagnitude").append("svg")
.attr("width",width + margin.left + margin.right)
.attr("height",height + margin.top + margin.bottom)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
// Add x grid
plotMagnitude.append("g")
.attr("class","x grid")
.attr("transform","translate(0," + height + ")")
.call(xGrid);
// Add y grid
plotMagnitude.append("g")
.attr("class","y grid")
.call(yGrid);
plotMagnitude.append("g")
.attr("class","x1 axis")
.attr("transform","translate(0," + height + ")")
.call(xAxis1);
plotMagnitude.append("g")
.attr("class","y1 axis")
.call(yAxis1);
/* append additional X axis */
plotMagnitude.append("g")
.attr("class","x2 axis")
.attr("transform","translate(" + [0, 0] + ")")
.call(xAxis2);
/* append additional y axis */
plotMagnitude.append("g")
.attr("class","y2 axis")
.attr("transform","translate(" + [width, 0] + ")")
.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")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
plotMagnitude.append("rect")
.attr("width", width)
.attr("height", height);
function redraw() {
plotMagnitude.select(".x1.axis").call(xAxis1);
plotMagnitude.select(".y1.axis").call(yAxis1);
plotMagnitude.select(".x2.axis").call(xAxis2);
plotMagnitude.select(".y2.axis").call(yAxis2);
plotMagnitude.select(".x.grid").call(xGrid);
plotMagnitude.select(".y.grid").call(yGrid);
var series = [];
var data1 = [];
var data2 = [];
var data3 = [];
for (var i = 0; i < range.length; i++) {
data1.push({
x: range[i],
y: leadlag(range[i])
});
data2.push({
x: range[i],
y: mag2db(math.abs(leadlag(range[i])))
});
data3.push({
x: range[i],
y: rad2deg(angle(leadlag(range[i])))
});
}
series.push({data: data2, width: 1, color: 'blue', stroke: "0,0", legend: "MAG" });
var series = plotMagnitude.selectAll(".line").data(series);
series.enter().append('path');
series.attr("class","line")
.attr("d",function(d) { return line(d.data); })
.attr("stroke-width", function(d) { return d.width; })
.style("stroke", function(d) { return d.color; })
.style("stroke-dasharray", function(d) { return d.stroke; });
d3.selectAll('.x1.axis>.tick')
.each(function(d,i){
if (d3.select(this).select('text').text() === ""){
d3.select('.x.grid>.tick:nth-child(' + (i + 1) + ')')
.style("stroke-dasharray", "3,3");
}
});
}
$(function() {
redraw();
});
</script>
</body>
</html>