我正在使用d3.js处理多系列折线图,我正在尝试实现焦点和上下文缩放,如http://bl.ocks.org/mbostock/1667367所示。我已将示例中的面积图转换为折线图有一个单一的系列,但我无法弄清楚为什么我的所有行都没有进行扩展,同时使用brush..only x-domain扩展x域,并且根据新的x域范围扩展了一行....
这是我正在使用的代码......
var margin = {
top: 20,
right: 200,
bottom: 100,
left: 100
},
margin2 = {
top: 430,
right: 10,
bottom: 20,
left: 100
},
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom,
legendPanel = {
width: 80
},
width = 960 - margin.left - margin.right - legendPanel.width;
var data = [{
"symbol": "Banker",
"date": "20000112",
"earnedpts": "30",
"redeemedpts": "15"
}, {
"symbol": "Banker",
"date": "20000810",
"earnedpts": "10",
"redeemedpts": "8"
}, {
"symbol": "Banker",
"date": "20010618",
"earnedpts": "50",
"redeemedpts": "20"
}, {
"symbol": "Banker",
"date": "20011220",
"earnedpts": "40",
"redeemedpts": "20"
}, {
"symbol": "Banker",
"date": "20020220",
"earnedpts": "30",
"redeemedpts": "20"
}, {
"symbol": "Banker",
"date": "20021130",
"earnedpts": "10",
"redeemedpts": "5"
}, {
"symbol": "Health",
"date": "20000112",
"earnedpts": "20",
"redeemedpts": "15"
}, {
"symbol": "Health",
"date": "20000810",
"earnedpts": "40",
"redeemedpts": "28"
}, {
"symbol": "Health",
"date": "20010618",
"earnedpts": "30",
"redeemedpts": "20"
}, {
"symbol": "Health",
"date": "20011220",
"earnedpts": "60",
"redeemedpts": "35"
}, {
"symbol": "Health",
"date": "20020220",
"earnedpts": "30",
"redeemedpts": "25"
}, {
"symbol": "Health",
"date": "20021130",
"earnedpts": "20",
"redeemedpts": "15"
}, {
"symbol": "Govt",
"date": "20000112",
"earnedpts": "80",
"redeemedpts": "65"
}, {
"symbol": "Govt",
"date": "20000810",
"earnedpts": "60",
"redeemedpts": "48"
}, {
"symbol": "Govt",
"date": "20010618",
"earnedpts": "60",
"redeemedpts": "40"
}, {
"symbol": "Govt",
"date": "20011220",
"earnedpts": "30",
"redeemedpts": "15"
}, {
"symbol": "Govt",
"date": "20020220",
"earnedpts": "40",
"redeemedpts": "25"
}, {
"symbol": "Govt",
"date": "20021130",
"earnedpts": "30",
"redeemedpts": "5"
}, {
"symbol": "BPO",
"date": "20000112",
"earnedpts": "70",
"redeemedpts": "45"
}, {
"symbol": "BPO",
"date": "20000810",
"earnedpts": "60",
"redeemedpts": "30"
}, {
"symbol": "BPO",
"date": "20010618",
"earnedpts": "40",
"redeemedpts": "25"
}, {
"symbol": "BPO",
"date": "20011220",
"earnedpts": "70",
"redeemedpts": "50"
}, {
"symbol": "BPO",
"date": "20020220",
"earnedpts": "40",
"redeemedpts": "25"
}, {
"symbol": "BPO",
"date": "20021130",
"earnedpts": "50",
"redeemedpts": "30"
}];
var parsedate = d3.time.format("%Y%m%d").parse;
var x = d3.time.scale().range([0, width]);
x2 = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear().range([height, 0]);
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom");
var xAxis2 = d3.svg.axis()
.scale(x2)
.orient("bottom");
var yAxis = d3.svg.axis().scale(y)
.orient("left");
var color = d3.scale.ordinal()
.range(["#04b0ff", "#04ffa8", "#ff5404", "#8a89a6", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
var extent = brush.extent();
var rangeExtent = [x2(extent[0]), x2(extent[1])];
var rangeWidth = rangeExtent[1] - rangeExtent[0];
var priceline1 = d3.svg.line()
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.earnedpts);
})
.interpolate("linear");
var priceline2 = d3.svg.line()
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.redeemedpts);
})
.interpolate("linear");
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right + legendPanel.width)
.attr("height", height + margin.top + margin.bottom);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")")
.attr("class", "context");
svg.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
data.forEach(function(d) {
d.date = parsedate(d.date);
d.earnedpts = +d.earnedpts;
d.redeemedpts = +d.redeemedpts;
});
x.domain(d3.extent(data, function(d) {
return d.date;
}));
x2.domain(x.domain());
y.domain([0, d3.max(data, function(d) {
return Math.max(d.earnedpts, d.redeemedpts);
})]);
y2.domain(y.domain());
var dataNest = d3.nest()
.key(function(d) {
return d.symbol;
})
.entries(data);
dataNest.forEach(function(d) {
focus.append("path")
.attr("class", "line")
.style("stroke", function() {
return d.color = color(d.key);
})
.attr("d", priceline1(d.values))
});
dataNest.forEach(function(d) {
focus.append("path")
.attr("class", "line")
.style("stroke", function() {
return d.color = color(d.key);
})
.style("stroke-dasharray", ("3, 3"))
.attr("d", priceline2(d.values))
});
context.append("g")
.attr("class", "x axis1")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
var contextArea = d3.svg.area()
.interpolate("monotone")
.x(function(d) {
return x2(d.date);
})
.y0(height2)
.y1(0);
context.append("path")
.attr("class", "area")
.attr("d", contextArea(dataNest[0].values))
.attr("fill", "#F1F1F2");
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("height", height2)
.attr("fill", "#E6E7E8");
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", -30)
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Days");
focus.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("x", 0)
.attr("y", -40)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Average points Earned & Redeemed");
dataNest.forEach(function(d, i) {
focus.append("text")
.attr("transform", "translate(" + width + "," + y(data[dataNest[i].values.length + i * 6 - 1].earnedpts) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.style("fill", function() {
return d.color = color(d.key);
})
.text(d.key);
});
focus.append("text")
.attr("transform", "translate(" + (width - 20) + ",5)")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.style("fill", "black")
.text("Points Earned");
focus.append("text")
.attr("transform", "translate(" + (width - 20) + "," + (y(data[0].redeemedpts) - 245) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.style("fill", "black")
.text("Points Redeemed");
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select(".x.axis").transition().call(xAxis);
focus.select(".y.axis").transition().call(yAxis);
dataNest.forEach(function(d) {
focus.selectAll("path")
.style("stroke", function() {
return d.color = color(d.key);
})
.transition()
.attr("d", priceline1(d.values))
});
}
答案 0 :(得分:0)
我认为这里有一些问题。
首先,使用两种不同的线方法创建两种类型的线(虚线和实线)。那样就好。但是,在最后的更新方法中,您选择所有这些方法并仅使用一种绘图方法(priceline
)。我建议进行以下更改:
为每一行添加一个类标识符,例如line1
或line2
,如下所示:
dataNest.forEach(function (d) {
focus.append("path")
.attr("class", "line line1-" + d.key)
.style("stroke", function () {
return color(d.key);
})
.attr("d", priceline1(d.values));
});
和
dataNest.forEach(function (d) {
focus.append("path")
.attr("class", "line line2-" + d.key)
.style("stroke", function () {
return color(d.key);
})
.style("stroke-dasharray", ("3, 3"))
.attr("d", priceline2(d.values));
});
然后,在您的画笔事件中,选择适当的一个并更新该行。 (道歉,我不知道你要更新哪一个,所以我把它们都包括在内)
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select(".x.axis").transition().call(xAxis);
focus.select(".y.axis").transition().call(yAxis);
dataNest.forEach(function (d) {
focus.selectAll(".line1-" + d.key)
.transition().duration(200)
.attr("d", priceline1(d.values));
focus.selectAll(".line2-" + d.key)
.transition().duration(200)
.attr("d", priceline2(d.values));
});
}
小提琴是here。
关于您的比例格式,您可以使用tickFormat
方法,如下所示:
// First define a formatting method such as
var axisFormat = d3.time.format("%b")
// Then apply your tickFormat to your scale
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(function(d) {
v=axisFormat(d);
return v.substr(0,1) // you can adjust this.
});
希望这有帮助