From e182e081bf595e783632aa3c225e3d9c5a756792 Mon Sep 17 00:00:00 2001 From: Robin Hu Date: Thu, 25 Jul 2013 14:23:51 -0400 Subject: [PATCH] Major change to interactiveLayer.js. Instead of creating a svg element to process mousemove events, we are attaching the mousemove event to the bounding container. This allows stackedAreaChart to maintain some previous interactivity. --- src/interactiveLayer.js | 53 +++++++++++++++++++++++++--------- src/models/stackedAreaChart.js | 7 ++++- test/stackedAreaChartTest.html | 4 ++- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/interactiveLayer.js b/src/interactiveLayer.js index 86e51bf..a00c80c 100644 --- a/src/interactiveLayer.js +++ b/src/interactiveLayer.js @@ -11,10 +11,16 @@ nv.interactiveGuideline = function() { //Public settings var width = null , height = null + //Please pass in the bounding chart's top and left margins + //This is important for calculating the correct mouseX/Y positions. + , margin = {left: 0, top: 0} , xScale = d3.scale.linear() , yScale = d3.scale.linear() , dispatch = d3.dispatch('elementMousemove', 'elementMouseout') , showGuideLine = true + , svgContainer = null + //Must pass in the bounding chart's container. + //The mousemove event is attached to this container. ; //Private variables @@ -23,17 +29,9 @@ nv.interactiveGuideline = function() { ; - function findFirstSVGParent(Elem) { - while(Elem.tagName.match(/^svg$/i) === null) { - Elem = Elem.parentNode; - } - return Elem; - } - function layer(selection) { selection.each(function(data) { var container = d3.select(this); - var offsetParent = findFirstSVGParent(this); var availableWidth = (width || 960), availableHeight = (height || 400); @@ -42,14 +40,13 @@ nv.interactiveGuideline = function() { .append("g").attr("class", " nv-wrap nv-interactiveLineLayer"); - wrapEnter.append("g").attr("class","nv-interactiveGuideLine"); - wrapEnter.append("rect").attr("class", "nv-mouseMoveLayer"); + wrapEnter.append("g").attr("class","nv-interactiveGuideLine").style("pointer-events","none"); + if (!svgContainer) { + return; + } - wrap.select(".nv-mouseMoveLayer") - .attr("width",availableWidth) - .attr("height",availableHeight) - .attr("opacity", 0) + svgContainer .on("mousemove",function() { var d3mouse = d3.mouse(this); var mouseX = d3mouse[0]; @@ -66,6 +63,17 @@ nv.interactiveGuideline = function() { mouseX = d3.event.offsetX; mouseY = d3.event.offsetY; } + + mouseX -= margin.left; + mouseY -= margin.top; + if (mouseX < 0 || mouseY < 0 + || mouseX > availableWidth || mouseY > availableHeight) { + dispatch.elementMouseout({ + mouseX: mouseX, + mouseY: mouseY + }); + return; + } var pointXValue = xScale.invert(mouseX); dispatch.elementMousemove({ @@ -99,6 +107,10 @@ nv.interactiveGuideline = function() { } } } + + mouseX -= margin.left; + mouseY -= margin.top; + dispatch.elementMouseout({ mouseX: mouseX, mouseY: mouseY @@ -133,6 +145,13 @@ nv.interactiveGuideline = function() { layer.dispatch = dispatch; layer.tooltip = tooltip; + layer.margin = function(_) { + if (!arguments.length) return margin; + margin.top = typeof _.top != 'undefined' ? _.top : margin.top; + margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + return layer; + }; + layer.width = function(_) { if (!arguments.length) return width; width = _; @@ -157,6 +176,12 @@ nv.interactiveGuideline = function() { return layer; }; + layer.svgContainer = function(_) { + if (!arguments.length) return svgContainer; + svgContainer = _; + return layer; + }; + return layer; }; diff --git a/src/models/stackedAreaChart.js b/src/models/stackedAreaChart.js index b3fb135..9570ea4 100644 --- a/src/models/stackedAreaChart.js +++ b/src/models/stackedAreaChart.js @@ -210,7 +210,12 @@ nv.models.stackedAreaChart = function() { //------------------------------------------------------------ //Set up interactive layer if (useInteractiveGuideline) { - interactiveLayer.width(availableWidth).height(availableHeight).xScale(x); + interactiveLayer + .width(availableWidth) + .height(availableHeight) + .margin({left: margin.left, top: margin.top}) + .svgContainer(container) + .xScale(x); wrap.select(".nv-interactive").call(interactiveLayer); } diff --git a/test/stackedAreaChartTest.html b/test/stackedAreaChartTest.html index 234ea26..68af2ca 100644 --- a/test/stackedAreaChartTest.html +++ b/test/stackedAreaChartTest.html @@ -258,7 +258,7 @@ function defaultChartConfig(container, data, useGuideline) { .tickFormat(d3.format(',.2f')); d3.select('#' + container + ' svg') - .datum(data) + .datum(data) .transition().duration(500).call(chart); nv.utils.windowResize(chart.update); @@ -287,6 +287,8 @@ nv.addGraph(function() { .datum(histcatexpshort) .call(chart); + + nv.utils.windowResize(chart.update); return chart;