0
我最近開始研究d3.js.我正在嘗試開發一個交互式多線圖。請看看我的工作至今:http://jsfiddle.net/dalapati/cdkn14j3/6/D3.js-動態更新線圖中的軸
data1 = [
{"date": 1357717800000,"value": "5.6"},
{"date": 1357718400000,"value": "5.6"},
{"date": 1357719000000,"value": "6"},
{"date": 1357719600000,"value": "5.1"},
{"date": 1357720200000,"value": "5.3"},
// {"date": 1357720800000,"value": "5.4"}
];
data2 = [
{"date": 1357714800000,"value": "5.2"},
{"date": 1357715400000,"value": "5.2"},
{"date": 1357716000000,"value": "5.2"},
{"date": 1357716600000,"value": "5.1"},
{"date": 1357717200000,"value": "5.5"},
];
// date manipulation to format UTC to js Date obj
data1.forEach(function(d){ d.time = new Date(d.time * 1000);});
data2.forEach(function(d){ d.time = new Date(d.time * 1000);});
// helpers and constants
var margin = {"top": 50, "right": 50, "bottom": 50, "left": 100, "axis": 55};
var width = 1500 - margin.left - margin.right;
var height = 580 - margin.top - margin.bottom;
var timeFormat = d3.time.format("%X");
// find data range
var findXMin = function(_data){
return d3.min(_data, function(d){
return Math.min(d.date);
});
}
var findXMax = function(_data){
return d3.max(_data, function(d){
return Math.max(d.date);
});
}
var findYMin = function(_data){
return d3.min(_data, function(d){
return Math.min(d.value);
});
}
var findYMax = function(_data){
return d3.max(_data, function(d){
return Math.max(d.value);
});
}
var x1Min = findXMin(data1);
var x1Max = findXMax(data1);
var x2Min = findXMin(data2);
var x2Max = findXMax(data2);
var y1Min = findYMin(data1);
var y1Max = findYMax(data1);
var y2Min = findYMin(data2);
var y2Max = findYMax(data2);
var yMin = (y1Min < y2Min) ? y1Min:y2Min;
var yMax = (y1Max > y2Max) ? y1Max:y2Max;
// scales
var x1Scale = d3.time.scale()
.domain([x1Min,x1Max])
.range([0, width]);
var x2Scale = d3.time.scale()
.domain([x2Min,x2Max])
.range([0, width]);
var yScale = d3.scale.linear()
.domain([yMin,yMax]).range([height, 0]);
var renderXAxis = function(scale, className, tickFormat, index0, index1, orient){
var axis = d3.svg.axis()
.scale(scale)
.orient(orient)
.ticks(5)
.tickPadding(5)
.tickFormat(tickFormat);
svg.append("g")
.attr("class", className)
.attr("transform", function() {
return "translate(" +index0+", " +index1+ ")";})
.call(axis);
}
var renderYAxis = function(scale, className, tickFormat, index0, index1, orient){
var axis = d3.svg.axis()
.scale(scale)
.orient(orient)
.ticks(5)
.tickPadding(5)
.tickFormat(tickFormat);
svg.append("g")
.attr("class", className)
.attr("transform", function(){
return "translate(" +index0+", " +index1+ ")";})
.call(axis);
// grid plot
svg.append("g")
.attr("class", "y grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
}
var make_y_axis = function() {
return d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5)
.tickPadding(5);
};
// Set up chart type
// create a line function that can convert data into x and y points
var line1 = d3.svg.line().interpolate("basis")
.x(function (d) {
return x1Scale(d.date);
})
.y(function (d) {
return yScale(d.value);
});
var line2 = d3.svg.line().interpolate("basis")
.x(function (d) {
return x2Scale(d.date);
})
.y(function (d) {
return yScale(d.value);
});
// Create Zoom feature
var zoomBottom = d3.behavior.zoom()
.x(x1Scale)
.scaleExtent([1,10]);
var zoom = d3.behavior.zoom()
.x(x2Scale)
.scaleExtent([1,10])
.on("zoom",zoomed);
// Create Drag behaviour
var drag = d3.behavior.drag()
.origin(function(d){
var t = d3.select(this);
return {
x: t.attr("x"),
y: t.attr("y")
};
})
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
// create svg container
var svg = d3.select('#chart')
.append("svg:svg")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var plot = svg.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("class", "plot")
.call(zoom);
//Draw Axes
var x1Axis = renderXAxis(x1Scale, "x1Axis", timeFormat, 0, height, "bottom");
var x2Axis = renderXAxis(x2Scale, "x2Axis", timeFormat, 0, 0, "top");
var yAxis = renderYAxis(yScale, "yAxis", function(d){return d;}, 0, 0, "left");
// add lines
// do this AFTER the axes above so that the line is above the tick-lines
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x1Scale", 0)
.attr("x2Scale", 0)
.attr("yScale", 0)
.attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)");
chartBody.append("svg:path")
.datum(data1)
.attr("class", "data1")
.attr("d", line1(data1))
.attr("cursor", "move")
.call(drag);
chartBody.append("svg:path")
.datum(data2)
.attr("class", "data2")
.attr("d", line2(data2))
.attr("cursor", "move")
.call(drag);
/************************** ADDING ZOOMING FEATURE****************************************/
function zoomed() {
zoomBottom.scale(zoom.scale()).translate(zoom.translate());
d3.select(".x1Axis").remove();
renderXAxis(x1Scale, "x1Axis", timeFormat, 0, height, "bottom");
d3.select(".x2Axis").remove();
renderXAxis(x2Scale, "x2Axis", timeFormat, 0, 0, "top");
d3.select(".yAxis").remove();
renderYAxis(yScale, "yAxis", function(d){return d;}, 0, 0, "left");
svg.select(".data1").attr("d",line1(data1));
svg.select(".data2").attr("d",line2(data2));
}
/***************** Adding Dragging feature*****************************************************/
function dragstarted(d){
d3.event.sourceEvent.stopPropagation();
//d3.event.preventDefault();
//d3.select(this).attr('pointer-events', 'none');
d3.select(this).classed("dragging", true);
console.log(d);
}
function dragged(d){
var lineToMove = d3.event.x;
d3.select(this)
.transition()
.ease("linear")
.attr("transform", "translate(" +lineToMove+ ",0)");
d3.select(".x1Axis").remove();
renderXAxis(x1Scale, "x1Axis", timeFormat, lineToMove, height, "bottom");
d3.select(".x2Axis").remove();
renderXAxis(x2Scale, "x2Axis", timeFormat, lineToMove, 0, "top");
d3.select(".yAxis").remove();
renderYAxis(yScale, "yAxis", function(d){return d;}, 0, 0, "left");}
function dragended(d){
d3.select(this).classed("dragging", false);
}
我試圖實現相對於它的軸拖動行爲各線圖。我可以實現拖動行爲到一個特定的線圖,但是,我不知道如何動態更新其各自的軸。任何人都可以請分享你的想法來解決這個問題。 預先感謝您。
作爲一般性評論,我不會用更新函數完全重新渲染每個軸。相反,根據需要更新其現有屬性並一次繪製軸。您可以通過使用像axis.scale(scale).tickFormat(tickFormat)這樣的方法來訪問它們。這增加了效率。然後,您可以執行如下操作:d3.select(「。x.axis」)。transition()。duration(1600).call(xAxis) – 2014-10-03 18:57:25
嗨,感謝您的回覆。你給出的想法很好。但我在這裏看到了一個錯誤。最初,當我拖動一個特定的圖形時,它可以通過更新其各自的軸來正常工作。稍後當我在整個繪圖上應用變焦時,軸會重置回原來的位置。這裏是更新的Jsfiddle:http://jsfiddle.net/dalapati/cdkn14j3/8/ – Dinesh 2014-10-03 20:12:04
我會爲這個問題開一個新的問題。我不知道這個問題。 – 2014-10-03 20:14:42