Added test page for lineChart. Continued work on making the interactive line layer.

master
Robin Hu 11 years ago
parent dbe826943f
commit 0b3ef24e0b

@ -1,6 +1,7 @@
JS_FILES = \
src/intro.js \
src/core.js \
src/interactiveLayer.js \
src/tooltip.js \
src/utils.js \
src/models/axis.js \

@ -93,14 +93,16 @@ nv.addGraph(function() {
function sinAndCos() {
var sin = [],
cos = []
rand = []
cos = [],
rand = [],
rand2 = []
;
for (var i = 0; i < 100; i++) {
sin.push({x: i, y: i % 10 == 5 ? null : Math.sin(i/10) }); //the nulls are to show how defined works
cos.push({x: i, y: .5 * Math.cos(i/10)});
rand.push({x:i, y: Math.random() / 10});
rand2.push({x: i, y: Math.cos(i/10) + Math.random() / 10 })
}
return [
@ -120,6 +122,12 @@ function sinAndCos() {
key: "Random Points",
color: "#2222ff"
}
,
{
values: rand2,
key: "Random Cosine",
color: "#667711"
}
];
}

@ -23,15 +23,15 @@ nv.interactiveLineLayer = function() {
var availableWidth = (width || 960), availableHeight = (height || 400);
var wrap = container.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([data]);
var gEnter = wrap.enter()
.append("g").attr("class", " nv-wrap nv-interactiveLineLayer")
.append("g");
var wrapEnter = wrap.enter()
.append("g").attr("class", " nv-wrap nv-interactiveLineLayer");
var guideLine = gEnter.append("g").attr("class","nv-interactiveGuideLine");
var mouseMoveLayer = gEnter.append("rect").attr("class", "nv-mouseMoveLayer");
wrapEnter.append("g").attr("class","nv-interactiveGuideLine");
wrapEnter.append("rect").attr("class", "nv-mouseMoveLayer");
mouseMoveLayer
wrap.select(".nv-mouseMoveLayer")
.attr("width",availableWidth)
.attr("height",availableHeight)
.attr("opacity", 0)
@ -40,16 +40,17 @@ nv.interactiveLineLayer = function() {
var mouseX = d3.mouse(this)[0];
var mouseY = d3.mouse(this)[1];
var pointIndex = Math.floor(xScale.invert(mouseX + padding));
if (pointIndex !== previousXCoordinate) {
previousXCoordinate = pointIndex;
dispatch.elementMousemove({
mouseX: mouseX,
mouseY: mouseY,
pointIndex: pointIndex
});
var pointLocation = xScale(pointIndex);
dispatch.elementMousemove({
mouseX: mouseX,
mouseY: mouseY,
pointIndex: pointIndex,
pointLocation: pointLocation
});
showGuideLine(pointLocation);
showGuideLine(xScale(pointIndex));
}
})
.on("mouseout",function() {
var padding = Math.floor(xScale(1)) /2;
@ -75,7 +76,7 @@ nv.interactiveLineLayer = function() {
line.enter()
.append("line")
.attr("stroke", "#00f")
.attr("stroke", "#ccc")
.attr("x1", function(d) { return d;})
.attr("x2", function(d) { return d;})
.attr("y1", availableHeight)

@ -10,6 +10,7 @@ nv.models.lineChart = function() {
, yAxis = nv.models.axis()
, legend = nv.models.legend()
, interactiveLayer = nv.interactiveLineLayer()
, tooltip = nv.models.tooltip()
;
//set margin.right to 23 to fit dates on the x-axis within the chart
@ -55,7 +56,9 @@ nv.models.lineChart = function() {
var tip = nv.models.tooltip()
.position(e.position)
.chartContainer(offsetElement)
.fixedTop(30)
.gravity('w')
.distance(50)
.snapDistance(25)
.enabled(tooltips)
.valueFormatter(function(d,i) {
return yAxis.tickFormat()(d);
@ -191,6 +194,7 @@ nv.models.lineChart = function() {
lines
.width(availableWidth)
.height(availableHeight)
.interactive(false)
.color(data.map(function(d,i) {
return d.color || color(d, i);
}).filter(function(d,i) { return !data[i].disabled }));
@ -268,18 +272,24 @@ nv.models.lineChart = function() {
interactiveLayer.dispatch.on('elementMousemove', function(e) {
lines.dispatch.clearHighlights();
var xValue, allData = [];
data.forEach(function(series,i) {
data
.filter(function(series, i) {
series.seriesIndex = i;
return !series.disabled;
})
.forEach(function(series,i) {
lines.dispatch.highlightPoint(i, e.pointIndex, true);
var point = series.values[e.pointIndex];
if (typeof point === 'undefined') return;
allData.push({
key: series.key,
value: lines.y()(series.values[e.pointIndex], e.pointIndex),
color: color(series)
color: color(series,series.seriesIndex)
});
});
showTooltip({
position: {left: e.mouseX + margin.left, top: e.mouseY + margin.top},
position: {left: e.pointLocation + margin.left, top: e.mouseY + margin.top},
pointIndex: e.pointIndex,
allSeriesData: allData
@ -409,11 +419,6 @@ nv.models.lineChart = function() {
return chart;
};
chart.tooltipContent = function(_) {
if (!arguments.length) return tooltip;
tooltip = _;
return chart;
};
chart.state = function(_) {
if (!arguments.length) return state;

@ -445,17 +445,16 @@ nv.models.scatter = function() {
});
dispatch.on('highlightPoint', function(seriesIndex, pointIndex, isHoverOver) {
if (interactive) {
d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex)
.classed("hover",isHoverOver);
}
d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex)
.classed("hover",isHoverOver);
});
dispatch.on('elementMouseover.point', function(d) {
dispatch.highlightPoint(d.seriesIndex,d.pointIndex,true);
if (interactive) dispatch.highlightPoint(d.seriesIndex,d.pointIndex,true);
});
dispatch.on('elementMouseout.point', function(d) {
dispatch.highlightPoint(d.seriesIndex,d.pointIndex,false);
if (interactive) dispatch.highlightPoint(d.seriesIndex,d.pointIndex,false);
});
//============================================================

@ -17,7 +17,7 @@
.nvtooltip {
position: absolute;
background-color: rgba(255,255,255,0.75);
background-color: rgba(255,255,255,1.0);
padding: 1px;
border: 1px solid rgba(0,0,0,.2);
z-index: 10000;
@ -392,7 +392,7 @@ svg .title {
.nvd3 .nv-groups .nv-point {
transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
-webkit-transition: stroke-width 0ms linear, stroke-opacity 0ms linear;
}

@ -38,6 +38,7 @@
*/
, gravity = 's' //Can be 'n','s','e','w'. Determines how tooltip is positioned.
, distance = 20 //Distance to offset tooltip from the mouse location.
, snapDistance = 30
, fixedTop = null //If not null, this fixes the top position of the tooltip.
, classes = null //Attaches additional CSS classes to the tooltip DIV that is created.
, chartContainer = null //Parent container that holds the chart.
@ -68,6 +69,12 @@
return html;
};
var dataSeriesExists = function(d) {
if (d && d.series && d.series.length > 0) return true;
return false;
};
//In situations where the chart is in a 'viewBox', re-position the tooltip based on how far chart is zoomed.
function convertViewBoxRatio() {
if (chartContainer) {
@ -87,6 +94,7 @@
//Draw the tooltip onto the DOM.
nvtooltip.render = function() {
if (!enabled) return;
if (!dataSeriesExists(data)) return;
convertViewBoxRatio();
@ -98,6 +106,11 @@
top += (chartContainer.offsetTop || 0);
}
if (snapDistance && snapDistance > 0) {
// left = Math.floor(left/snapDistance) * snapDistance;
top = Math.floor(top/snapDistance) * snapDistance;
}
nv.tooltip.show([left, top],
contentGenerator(data),
gravity,
@ -138,6 +151,12 @@
return nvtooltip;
};
nvtooltip.snapDistance = function(_) {
if (!arguments.length) return snapDistance;
snapDistance = _;
return nvtooltip;
};
nvtooltip.classes = function(_) {
if (!arguments.length) return classes;
classes = _;
@ -264,6 +283,8 @@
case 'w':
left = pos[0] + dist;
top = pos[1] - (height / 2);
var tLeft = tooltipLeft(container);
var tTop = tooltipTop(container);
if (tLeft + width > windowWidth) left = pos[0] - width - dist;
if (tTop < scrollTop) top = scrollTop + 5;
if (tTop + height > scrollTop + windowHeight) top = scrollTop - height - 5;

@ -0,0 +1,231 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link href="../src/nv.d3.css" rel="stylesheet" type="text/css">
<style>
body {
overflow-y:scroll;
}
text {
font: 12px sans-serif;
}
.chart {
float: left;
width: 50%;
}
.chart svg {
height: 500px;
width: 100%;
}
</style>
<body>
<div class='chart' id='chart1'>
<svg></svg>
</div>
<div class='chart' id='chart2'>
<svg></svg>
</div>
<div class='chart' id='chart3'>
<svg></svg>
</div>
<div class='chart' id='chart4'>
<svg></svg>
</div>
<div class='chart' id='chart5'>
<svg></svg>
</div>
<div class='chart' id='chart6'>
<svg></svg>
</div>
<script src="../lib/d3.v3.js"></script>
<script src="../nv.d3.js"></script>
<script src="../src/tooltip.js"></script>
<script src="../src/utils.js"></script>
<script src="../src/interactiveLayer.js"></script>
<script src="../src/models/legend.js"></script>
<script src="../src/models/axis.js"></script>
<script src="../src/models/scatter.js"></script>
<script src="../src/models/line.js"></script>
<script src="../src/models/lineChart.js"></script>
<script>
//------------ CHART 1
defaultChartConfig("chart1", sinAndCos(), true);
//-------------- CHART 2
nv.addGraph(function() {
var chart;
chart = nv.models.lineChart();
chart
.x(function(d,i) { return i });
chart.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
.tickFormat(d3.format(',.1f'));
chart.yAxis
.axisLabel('Voltage (v)')
.tickFormat(d3.format(',.4f'));
chart.showXAxis(true).showYAxis(true).rightAlignYAxis(true).margin({right: 90});
d3.select('#chart2 svg')
//.datum([]) //for testing noData
.datum(hyperbole())
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
defaultChartConfig("chart3", smallDataSet(3));
defaultChartConfig("chart4", badDataSet());
defaultChartConfig("chart5", smallDataSet(1));
defaultChartConfig("chart6", normalDist());
function defaultChartConfig(containerid, data, useDates) {
nv.addGraph(function() {
var chart;
chart = nv.models.lineChart();
chart
.x(function(d,i) { return i });
var formatter;
if (useDates !== undefined) {
formatter = function(d,i) {
var now = (new Date()).getTime() - 86400 * 1000 * 365;
now = new Date(now + d * 86400 * 1000);
return d3.time.format('%b %d %Y')(now );
}
}
else {
formatter = d3.format(",.1f");
}
chart.margin({right: 40});
chart.xAxis // chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
.tickFormat(
formatter
);
chart.yAxis
.axisLabel('Voltage (v)')
.tickFormat(d3.format(',.2f'));
d3.select('#' + containerid + ' svg')
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
}
function sinAndCos() {
var sin = [],
cos = [],
rand = [],
rand2 = []
;
var now = (new Date()).getTime();
for (var i = 0; i < 100; i++) {
sin.push({x: i, y: i % 10 == 5 ? null : Math.sin(i/10) }); //the nulls are to show how defined works
cos.push({x: i, y: .5 * Math.cos(i/10)});
rand.push({x:i, y: Math.random() / 10});
rand2.push({x: i, y: Math.cos(i/10) + Math.random() / 10 })
}
return [
{
area: true,
values: sin,
key: "Sine Wave",
color: "#ff7f0e"
},
{
values: cos,
key: "Cosine Wave",
color: "#2ca02c"
},
{
values: rand,
key: "Random Points",
color: "#2222ff"
}
,
{
values: rand2,
key: "Random Cosine",
color: "#667711"
}
];
}
function hyperbole() {
var series1 = [], series2 = [], series3 = [];
for(var i = 1; i < 100; i++) {
series1.push({x: i, y: 1 / i});
series2.push({x: i, y: 5 / i});
series3.push({x: i, y: -8 / i});
}
return [
{values: series1, key: "Series 1"},
{values: series2, key: "Series 2"},
{values: series3, key: "Series 3"}
];
}
function smallDataSet(n) {
var series = [];
for(var i = 0; i < n; i++) {
series.push({x: i, y: i * 0.3 + 2})
}
return [
{values: series, key: "Line 1"}
];
}
function badDataSet() {
var series1 = [], series2 = [];
for(var i =0; i < 30; i++) {
series1.push({x:i, y: i*0.3 + 12});
}
for(i = 0; i < 30; i += 5) {
series2.push({x:i, y: i*0.7 + 8});
}
return [
{values: series1, key:"Series 1"},
{values: series2, key:"Series 2"}
];
}
function normalDist() {
var series1 = [], series2 = [];
for(var i = -500; i < 500; i += 1) {
var x = i / 100;
var y = 0.3989 * Math.pow(2.71, -0.5*x*x);
series1.push({x:i, y:y});
series2.push({x:i, y:y*2});
}
return [
{values: series1, key:"Normal 1"},
{values: series2, key:"Normal 2"}];
}
</script>
Loading…
Cancel
Save