Javascript 在交互式多系列折线图中使用brushed()时,为什么只有一条线被延长
我正在使用d3.js制作一个多系列的折线图,并试图实现如中所示的焦点和上下文缩放。我已将示例中的面积图转换为一个单一系列的折线图,但我无法理解为什么在使用笔刷扩展x域时,我的所有线都没有得到扩展x域和一行将根据新的x域范围进行扩展 这是我正在使用的代码Javascript 在交互式多系列折线图中使用brushed()时,为什么只有一条线被延长,javascript,svg,d3.js,Javascript,Svg,D3.js,我正在使用d3.js制作一个多系列的折线图,并试图实现如中所示的焦点和上下文缩放。我已将示例中的面积图转换为一个单一系列的折线图,但我无法理解为什么在使用笔刷扩展x域时,我的所有线都没有得到扩展x域和一行将根据新的x域范围进行扩展 这是我正在使用的代码 var margin = { top: 20, right: 200, bottom: 100, left: 100 }, margin2 = { t
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))
});
}
我认为这里有一些问题 首先,使用两种不同的线方法创建两种类型的线(虚线和实线)。那很好。但是,在最后的更新方法中,您选择了所有这些方法,并仅使用一种绘图方法(
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));
});
// 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.
});
及
tickFormat
方法,如下所示:
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));
});
// 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.
});
希望这有帮助这是我的JSFIDLE链接我还有一个疑问..这里我用时间刻度()表示x轴。所以我在x轴上得到“2000年4月至7月…”但我的要求是在x轴上得到“2000 F M A M J A S O N D 2001 F”…如此以此类推..那么我如何才能得到x轴上每个月名字的第一个字母呢???嗨,我已经调整了我的答案。谢谢Nikos…但我真正想要的是月份的第一个字母,带有年边界,如“2000 F M A M J A S O N D 2001 F…等等”…但是如果我使用xaxis的tickFormat()中的任何函数,我不会得到“J F M A M J A S O N D…”这样的年边界…只有我得到的是月份名称。有人能帮我在x轴上获得上述格式(月份名称的第一个字母和年份边界)的代码吗…我已经尽了最大努力,但无法获得此格式…我认为这是不可行的。