У меня есть проект, где мне нужно увеличить 3 оси независимо. Я использую полосы прокрутки для достижения этого, но оси не перерисовываются, когда происходит масштабирование.D3.js масштабирование с осью
Кроме того, путь клипа, похоже, не работает должным образом.
В конце концов, я хочу добавить функциональность панорамирования на диаграмму, но я не уверен, с чего начать.
Заранее спасибо за помощь.
// cases vs deaths of a disease over time
var data = [
{"year": "1960", "cases":"887", "deaths": "199"},
{"year": "1965", "cases":"218", "deaths": "55"},
{"year": "1993", "cases":"37046", "deaths": "931"},
{"year": "1994", "cases":"38735", "deaths": "118"},
{"year": "1995", "cases":"19903", "deaths": "624"},
{"year": "1997", "cases":"4170", "deaths": "125"},
{"year": "1998", "cases":"10000", "deaths": "0"}
];
data.forEach(function (d) {
d.year = d3.time.format("%Y").parse(d.year.toString());
d.cases = +d.cases;
d.deaths = +d.deaths;
});
var margin = { top: 30, right: 40, bottom: 30, left: 50 },
width = 500 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
var xScale = d3.time.scale()
.domain(d3.extent(data, function (d) { return d.year; }))
.range([0, width]);
var yScaleLeft = d3.scale.linear()
.domain([0, d3.max(data, function (d) { return d.cases; })])
.range([height, 0]);
var yScaleRight = d3.scale.linear()
.domain([0, d3.max(data, function (d) { return d.deaths; })])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom").ticks(5);
var yAxisLeft = d3.svg.axis()
.scale(yScaleLeft)
.orient("left").ticks(5);
var yAxisRight = d3.svg.axis()
.scale(yScaleRight)
.orient("right").ticks(5);
var lineCases = d3.svg.line()
.x(function (d) { return xScale(d.year); })
.y(function (d) { return yScaleLeft(d.cases); });
var lineDeaths = d3.svg.line()
.x(function (d) { return xScale(d.year); })
.y(function (d) { return yScaleRight(d.deaths); });
var svg = d3.select("#chart").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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis yleft")
.call(yAxisLeft);
svg.append("g")
.attr("class", "y axis yright")
.call(yAxisRight)
.attr('transform', 'translate(' + width + ',0)');
svg.append("path")
.datum(data)
.attr("class", "line lineLeft")
.style("stroke", "red")
.attr("d", lineCases(data))
.attr("clip", "url(#clip)");
svg.append("path")
.datum(data)
.attr("class", "line lineRight")
.attr("d", lineDeaths(data))
.attr("clip", "url(#clip)");
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
$("#slider-x").slider({
orientation: "horizontal",
range: "min",
min: 1000,
max: 10000, // make max be (maxDate-minDate).Days*1000, so you can zoom to one day
value: 1000,
slide: function(event, ui) {
zoomXWithSlider(ui.value/1000);
}
});
$("#slider-y-left").slider({
orientation: "vertical",
range: "min",
min: 1000,
max: 10000,
value: 1000,
slide: function(event, ui) {
zoomLeftWithSlider(ui.value/1000);
}
});
$("#slider-y-right").slider({
orientation: "vertical",
range: "min",
min: 1000,
max: 10000,
value: 1000,
slide: function(event, ui) {
zoomRightWithSlider(ui.value/1000);
}
});
function zoomXWithSlider(scale) {
// Note: works only on the <g> element and not on the <svg> element
// which is a common mistake
svg.selectAll("path.line").attr("transform", "scale("+scale+", 1)");
svg.select(".x.axis").call(xAxis);
}
function zoomLeftWithSlider(scale) {
svg.select("path.line.lineLeft").attr("transform", "scale(1, "+scale+")");
svg.select(".y.axis.yleft").call(yAxisLeft);
}
function zoomRightWithSlider(scale) {
svg.select("path.line.lineRight").attr("transform", "scale(1, "+scale+")");
svg.select(".y.axis.yright").call(yAxisRight);
}
Есть много проблем. Больше, чем я могу сейчас войти, чтобы написать полный ответ. Во-первых, когда вы реагируете на ползунок, меняете и перерисовываете оси, вы также должны изменять масштаб, на котором основаны оси, иначе они просто перерисовывают одно и то же (как вы видите). Например, на X вы можете сделать что-то вроде 'xScale.range ([0, width * scale])' перед перерисованием оси. Возможно, вам захочется реорганизовать такие вещи, чтобы при изменении значения ползунка вы записывали только новое значение шкалы, а затем перерисовывали всю или большую часть диаграммы, чтобы избежать повторения кода. – meetamit
После того, как вы перейдете в панорамирование, вам также понадобится изменить первый элемент ('0', выше) затронутого диапазона, что является еще одной причиной для реорганизации объектов. – meetamit
Существует несколько причин, по которым clipPath не работает. Во-первых, 'clipPath' должен быть дочерним элементом раздела' '. И вместо атрибута 'clip' вам нужно указать' clip-path' (как в '.attr (" clip-path "," url (#clip) ");'). Но по-прежнему существует проблема, которая, масштабируя '' при перемещении слайдера, также неявно масштабируется клиппат, а это означает, что он не продолжает обрезать на основе постоянной ширины диаграммы. Чтобы понять, что я имею в виду, я намеренно устанавливаю ширину маски 'width/2', чтобы обрезать половину графика. Посмотрите, как он растет при слайдере x: http://jsfiddle.net/tvvcbrob/ –
meetamit