Я делаю многострочный график и используя кисть для выбора периодов времени. Он широко основан на примере Майка Босток по адресу http://bl.ocks.org/mbostock/1667367d3.js кисть с многострочной диаграммой
Мой график на http://lowercasen.com/dev/d3/general/piezobrush.html
Моя проблема заключается в выборе нескольких строк в моей области «фокус», чтобы применить щетку. Я вложил данные на основе ключа, поэтому данные находятся в пределах функции. Поскольку функция, вызывающая мою кисть, находится вне этой функции, она не может получить доступ к данным, и я получаю TypeError: undefined не является объектом (оценка «data.length»)
Вот код, который гнездится данные:
dataNest.forEach(function(d, i) {
focus.append("path")
.attr("class", "line")
.attr("id", d.key.replace(/\s+/g, '')) //the replace stuff is getting rid of spaces
.attr("d", levelFocus(d.values));
context.append("path")
.attr("class", "line")
.attr("id", d.key.replace(/\s+/g, '')) //the replace stuff is getting rid of spaces
.attr("d", levelContext(d.values));
и на дне у меня есть функция для кисти:
function brushed() {
xFocus.domain(brush.empty() ? xContext.domain() : brush.extent());
focus.selectAll(".line").attr("d", levelFocus(d.values));
focus.select(".x.axis").call(xAxisFocus);
}
Он отлично работает на оси х (если я закомментировать строку, в которой я пытаюсь выбрать строки), но я не знаю, как правильно выбрать строки.
Извинения за любой искаженный синтаксис или запутанный язык, мои навыки кодирования в лучшем случае являются основными.
Любая помощь очень признательна, я искал часы для решения.
Вот полный код по просьбе Lars
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Multiline with brush</title>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="d3/tooltip.js"></script>
<link href="styles/evidentlySoCharts.css" rel="stylesheet">
<meta name="viewport" content="initial-scale=1">
<style>
svg {
font: 10px sans-serif;
}
path {
stroke-width: 1;
fill: none;
}
#Stream1, #Nebo1D {
stroke: #009390;
}
#Stream1Legend, #Nebo1DLegend {
fill: #009390;
}
#Stream2, #Nebo2D {
stroke: #8dc63f;
}
#Stream2Legend, #Nebo2DLegend {
fill: #8dc63f;
}
#Stream3, #Nebo1S {
stroke: #132d46;
}
#Stream3Legend, #Nebo1SLegend {
fill: #132d46;
}
#Stream4, #Nebo2S {
stroke: #aaa813;
}
#Stream4Legend, #Nebo2SLegend {
fill: #aaa813;
}
#Stream5, #Nebo3 {
stroke: #619dd4;
}
#Stream5Legend, #Nebo3Legend {
fill: #619dd4;
}
.pn1d, .pn2d {
fill: none;
clip-path: url(#clip);
}
.pn1d {
stroke: #009390;
}
.pn2d {
stroke: #1b4164;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
stroke-width: 1px;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script>
var marginFocus = {top: 10, right: 10, bottom: 250, left: 40},
marginContext = {top: 430, right: 10, bottom: 170, left: 40},
width = 960 - marginFocus.left - marginFocus.right,
heightFocus = 650 - marginFocus.top - marginFocus.bottom,
heightContext = 650 - marginContext.top - marginContext.bottom;
legendOffset = 550;
var parseDate = d3.time.format("%d/%m/%y %H:%M").parse;
var xFocus = d3.time.scale().range([0, width]),
xContext = d3.time.scale().range([0, width]),
yFocus = d3.scale.linear().range([heightFocus, 0]),
yContext = d3.scale.linear().range([heightContext, 0]);
var xAxisFocus = d3.svg.axis().scale(xFocus).orient("bottom"),
xAxisContext = d3.svg.axis().scale(xContext).orient("bottom"),
yAxisFocus = d3.svg.axis().scale(yFocus).orient("left");
var levelFocus = d3.svg.line()
.interpolate("linear")
.x(function(d) { return xFocus(d.date); })
.y(function(d) { return yFocus(d.level); });
var levelContext = d3.svg.line()
.interpolate("linear")
.x(function(d) { return xContext(d.date); })
.y(function(d) { return yContext(d.level); });
var svg = d3.select("body").append("svg")
.attr("width", width + marginFocus.left + marginFocus.right)
.attr("height", heightFocus + marginFocus.top + marginFocus.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", heightFocus);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + marginFocus.left + "," + marginFocus.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + marginContext.left + "," + marginContext.top + ")");
d3.csv("data/PiezoNeboNestSimple.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.level = +d.level;
});
xFocus.domain(d3.extent(data.map(function(d) { return d.date; })));
yFocus.domain([d3.min(data.map(function(d) { return d.level; })) -2,0]);
xContext.domain(xFocus.domain());
yContext.domain(yFocus.domain());
// Nest the entries by piezo
var dataNest = d3.nest()
.key(function(d) {return d.piezo;})
.entries(data);
legendSpace = width/dataNest.length; // spacing for legend // ******
var brush = d3.svg.brush()
.x(xContext)
.on("brush", brushed);
focus.selectAll("g").data(dataNest)
.enter()
.append("g")
.attr("class", "line")
.attr("id", function(d) { return d.key.replace(/\s+/g, '') }) //the replace stuff is getting rid of spaces
.append("path")
.attr("d", function(d) { return levelFocus(d.values); });
context.selectAll("g").data(dataNest)
.enter()
.append("g")
.attr("class", "line")
.attr("id", function(d) { return d.key.replace(/\s+/g, '') }) //the replace stuff is getting rid of spaces
.append("path")
.attr("d", function(d) { return levelContext(d.values); });
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + heightFocus + ")")
.call(xAxisFocus);
focus.append("g")
.attr("class", "y axis")
.call(yAxisFocus);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + heightContext + ")")
.call(xAxisContext);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", heightContext + 7);
function brushed() {
xFocus.domain(brush.empty() ? xContext.domain() : brush.extent());
focus.selectAll(".line").attr("d", levelFocus(dataNest.values));
focus.select(".x.axis").call(xAxisFocus);
}
});
</script>
</body>
</html>
Не могли бы вы определить функцию «brushed» в той же области, что и «данные»? –
Ларс, я пробовал свой неопытный путь, но безуспешно. Я почти уверен, что им нужно как-то оказаться в той же области, но мне не хватает навыков. Имейте в виду, что другие примеры (с одной строкой или областью, а не моими несколькими) определяют ее за пределами области данных. Тем не менее, я думаю, вы на правильном пути. Можете ли вы дать мне представление о том, как это сделать? – tgerard
@LarsKotthoff Я обновил его, чтобы иметь чистую функцию в той же области, что и данные, но все же без радости. Проблема заключается в этой строке «focus.selectAll («. Line »). Attr (« d », levelFocus (d.values)); и ошибка, которую я получаю, заключается в том, что она не может найти переменную d. В принципе, я не знаю, как ссылаться на строки, которые я добавил в диаграмму. – tgerard