Lots of enahncements to scatter and stacked are, useVoronoi(false) now functions correctly. IE9 fixes.

master-patched
Bob Monteverde 12 years ago
parent 353f4354fd
commit 99329c6fc9

@ -31,6 +31,7 @@ nv.addGraph({
.height(height)
.margin({top: 20, right: 20, bottom: 20, left: 20})
.size(function(d) { return d.z })
.useVoronoi(false)
//.interactive(false)
@ -38,6 +39,7 @@ nv.addGraph({
.attr('width', width)
.attr('height', height)
.datum(randomData())
.transition().duration(500)
.call(chart);
return chart;

@ -47,7 +47,7 @@ div {
</div>
<script src="../lib/d3.v2.js"></script>
<script src="../lib/fisheye.js"></script>
<!--<script src="../lib/fisheye.js"></script>-->
<script src="../nv.d3.js"></script>
<script src="../src/tooltip.js"></script>
<script src="../src/utils.js"></script>
@ -66,6 +66,7 @@ nv.addGraph(function() {
.showDistX(true)
.showDistY(true)
//.height(500)
.useVoronoi(true)
.color(d3.scale.category10().range());
chart.xAxis.tickFormat(d3.format('.02f'))

@ -25,7 +25,7 @@ text {
</div>
<div>
<svg id="chart2"></svg>
<!--<svg id="chart2"></svg>-->
</div>
<script src="../lib/d3.v2.js"></script>
@ -197,6 +197,10 @@ nv.addGraph(function() {
.color(keyColor)
//.clipEdge(true);
chart.stacked.scatter
.sizeRange([64,64])
.useVoronoi(false);
chart.xAxis
.tickFormat(function(d) { return d3.time.format('%x')(new Date(d)) });

@ -34,6 +34,9 @@ if (nv.dev) {
// ********************************************
// Public Core NV functions
// Make console.log a FUNCTION in IE9 (https://gist.github.com/1466437)
(function(){var a=this.console,b=a&&a.log,c=!b||b.call?0:a.log=function(){c.apply.call(b,a,arguments)}})();
// Logs all arguments, and returns the last so you can test things in place
nv.log = function() {
if (nv.dev && console.log && console.log.apply) console.log.apply(console, arguments);
@ -7920,6 +7923,7 @@ nv.models.scatter = function() {
, getY = function(d) { return d.y } // accessor to get the y value
, getSize = function(d) { return d.size || 1} // accessor to get the point size
, getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
, onlyCircles = true // Set to false to use shapes
, forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
, forceY = [] // List of numbers to Force into the Y scale
, forceSize = [] // List of numbers to Force into the Size scale
@ -8057,31 +8061,33 @@ nv.models.scatter = function() {
);
if (clipVoronoi) {
var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')
.data([id])
.enter();
pointClipsEnter.append('clipPath')
.attr('class', 'nv-point-clips')
.attr('id', 'nv-points-clip-' + id);
var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
.data(vertices);
pointClips.enter().append('circle')
.attr('r', clipRadius);
pointClips.exit().remove();
pointClips
.attr('cx', function(d) { return d[0] })
.attr('cy', function(d) { return d[1] });
//inject series and point index for reference into voronoi
if (useVoronoi === true) {
wrap.select('.nv-point-paths')
.attr('clip-path', 'url(#nv-points-clip-' + id + ')');
}
if (clipVoronoi) {
var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')
.data([id])
.enter();
pointClipsEnter.append('clipPath')
.attr('class', 'nv-point-clips')
.attr('id', 'nv-points-clip-' + id);
var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
.data(vertices);
pointClips.enter().append('circle')
.attr('r', clipRadius);
pointClips.exit().remove();
pointClips
.attr('cx', function(d) { return d[0] })
.attr('cy', function(d) { return d[1] });
wrap.select('.nv-point-paths')
.attr('clip-path', 'url(#nv-points-clip-' + id + ')');
}
//inject series and point index for reference into voronoi
if (useVoronoi === true) {
if(vertices.length < 3) {
// Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work
vertices.push([x.range()[0] - 2000, y.range()[0] - 2000, null, null]);
@ -8106,9 +8112,49 @@ nv.models.scatter = function() {
pointPaths
.attr('d', function(d) { return 'M' + d.data.join('L') + 'Z'; });
eventElements = pointPaths;
pointPaths
.on('click', function(d) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementClick({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point
});
})
.on('mouseover', function(d) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementMouseover({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point
});
})
.on('mouseout', function(d, i) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementMouseout({
point: point,
series: series,
seriesIndex: d.series,
pointIndex: d.point
});
});
} else {
/*
// bring data in form needed for click handlers
var dataWithPoints = vertices.map(function(d, i) {
return {
@ -8117,55 +8163,55 @@ nv.models.scatter = function() {
'point': vertices[i][3]
}
});
*/
// add event handlers to points instead voronoi paths
eventElements = wrap.select('.nv-groups').selectAll('.nv-group')
.selectAll('path.nv-point')
.data(dataWithPoints)
.style('pointer-events', 'auto'); // recativate events, disabled by css
}
wrap.select('.nv-groups').selectAll('.nv-group')
.selectAll('.nv-point')
//.data(dataWithPoints)
//.style('pointer-events', 'auto') // recativate events, disabled by css
.on('click', function(d,i) {
//nv.log('test', d, i);
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[i];
eventElements
.on('click', function(d) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementClick({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point
});
})
.on('mouseover', function(d) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementClick({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: i
});
})
.on('mouseover', function(d,i) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[i];
dispatch.elementMouseover({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point
});
})
.on('mouseout', function(d, i) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementMouseover({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: i
});
})
.on('mouseout', function(d,i) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[i];
dispatch.elementMouseout({
point: point,
series: series,
seriesIndex: d.series,
pointIndex: d.point
dispatch.elementMouseout({
point: point,
series: series,
seriesIndex: d.series,
pointIndex: i
});
});
});
}
needsUpdate = false;
needsUpdate = false;
}
needsUpdate = true;
@ -8189,38 +8235,62 @@ nv.models.scatter = function() {
.style('fill-opacity', .5);
var points = groups.selectAll('path.nv-point')
.data(function(d) { return d.values });
points.enter().append('path')
.attr('transform', function(d,i) {
return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
})
.attr('d',
d3.svg.symbol()
.type(getShape)
.size(function(d,i) { return z(getSize(d,i)) })
);
points.exit().remove();
d3.transition(groups.exit().selectAll('path.nv-point'))
.attr('transform', function(d,i) {
return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
})
.remove();
points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
d3.transition(points)
.attr('transform', function(d,i) {
return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
})
.attr('d',
d3.svg.symbol()
.type(getShape)
.size(function(d,i) { return z(getSize(d,i)) })
);
if (onlyCircles) {
var points = groups.selectAll('circle.nv-point')
.data(function(d) { return d.values });
points.enter().append('circle')
.attr('cx', function(d,i) { return x0(getX(d,i)) })
.attr('cy', function(d,i) { return y0(getY(d,i)) })
.attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
points.exit().remove();
d3.transition(groups.exit().selectAll('path.nv-point'))
.attr('cx', function(d,i) { return x(getX(d,i)) })
.attr('cy', function(d,i) { return y(getY(d,i)) })
.remove();
points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
d3.transition(points)
.attr('cx', function(d,i) { return x(getX(d,i)) })
.attr('cy', function(d,i) { return y(getY(d,i)) })
.attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
} else {
var points = groups.selectAll('path.nv-point')
.data(function(d) { return d.values });
points.enter().append('path')
.attr('transform', function(d,i) {
return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
})
.attr('d',
d3.svg.symbol()
.type(getShape)
.size(function(d,i) { return z(getSize(d,i)) })
);
points.exit().remove();
d3.transition(groups.exit().selectAll('path.nv-point'))
.attr('transform', function(d,i) {
return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
})
.remove();
points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
d3.transition(points)
.attr('transform', function(d,i) {
//nv.log(d,i,getX(d,i), x(getX(d,i)));
return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
})
.attr('d',
d3.svg.symbol()
.type(getShape)
.size(function(d,i) { return z(getSize(d,i)) })
);
}
// Delay updating the invisible interactive layer for smoother animation
clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
timeoutID = setTimeout(updateInteractiveLayer, 1000);
//clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
//timeoutID = setTimeout(updateInteractiveLayer, 1000);
updateInteractiveLayer();
//store old scales for use in transitions on update
x0 = x.copy();
@ -8408,6 +8478,12 @@ nv.models.scatter = function() {
return chart;
};
chart.onlyCircles = function(_) {
if (!arguments.length) return onlyCircles;
onlyCircles = _;
return chart;
};
chart.id = function(_) {
if (!arguments.length) return id;
id = _;

10
nv.d3.min.js vendored

File diff suppressed because one or more lines are too long

@ -33,6 +33,9 @@ if (nv.dev) {
// ********************************************
// Public Core NV functions
// Make console.log a FUNCTION in IE9 (https://gist.github.com/1466437)
(function(){var a=this.console,b=a&&a.log,c=!b||b.call?0:a.log=function(){c.apply.call(b,a,arguments)}})();
// Logs all arguments, and returns the last so you can test things in place
nv.log = function() {
if (nv.dev && console.log && console.log.apply) console.log.apply(console, arguments);

@ -17,6 +17,7 @@ nv.models.scatter = function() {
, getY = function(d) { return d.y } // accessor to get the y value
, getSize = function(d) { return d.size || 1} // accessor to get the point size
, getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
, onlyCircles = true // Set to false to use shapes
, forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
, forceY = [] // List of numbers to Force into the Y scale
, forceSize = [] // List of numbers to Force into the Size scale
@ -154,31 +155,33 @@ nv.models.scatter = function() {
);
if (clipVoronoi) {
var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')
.data([id])
.enter();
pointClipsEnter.append('clipPath')
.attr('class', 'nv-point-clips')
.attr('id', 'nv-points-clip-' + id);
var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
.data(vertices);
pointClips.enter().append('circle')
.attr('r', clipRadius);
pointClips.exit().remove();
pointClips
.attr('cx', function(d) { return d[0] })
.attr('cy', function(d) { return d[1] });
//inject series and point index for reference into voronoi
if (useVoronoi === true) {
wrap.select('.nv-point-paths')
.attr('clip-path', 'url(#nv-points-clip-' + id + ')');
}
if (clipVoronoi) {
var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')
.data([id])
.enter();
pointClipsEnter.append('clipPath')
.attr('class', 'nv-point-clips')
.attr('id', 'nv-points-clip-' + id);
var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
.data(vertices);
pointClips.enter().append('circle')
.attr('r', clipRadius);
pointClips.exit().remove();
pointClips
.attr('cx', function(d) { return d[0] })
.attr('cy', function(d) { return d[1] });
wrap.select('.nv-point-paths')
.attr('clip-path', 'url(#nv-points-clip-' + id + ')');
}
//inject series and point index for reference into voronoi
if (useVoronoi === true) {
if(vertices.length < 3) {
// Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work
vertices.push([x.range()[0] - 2000, y.range()[0] - 2000, null, null]);
@ -203,9 +206,49 @@ nv.models.scatter = function() {
pointPaths
.attr('d', function(d) { return 'M' + d.data.join('L') + 'Z'; });
eventElements = pointPaths;
pointPaths
.on('click', function(d) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementClick({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point
});
})
.on('mouseover', function(d) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementMouseover({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point
});
})
.on('mouseout', function(d, i) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementMouseout({
point: point,
series: series,
seriesIndex: d.series,
pointIndex: d.point
});
});
} else {
/*
// bring data in form needed for click handlers
var dataWithPoints = vertices.map(function(d, i) {
return {
@ -214,55 +257,55 @@ nv.models.scatter = function() {
'point': vertices[i][3]
}
});
*/
// add event handlers to points instead voronoi paths
eventElements = wrap.select('.nv-groups').selectAll('.nv-group')
.selectAll('path.nv-point')
.data(dataWithPoints)
.style('pointer-events', 'auto'); // recativate events, disabled by css
}
eventElements
.on('click', function(d) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementClick({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point
});
})
.on('mouseover', function(d) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementMouseover({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: d.point
});
})
.on('mouseout', function(d, i) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[d.point];
dispatch.elementMouseout({
point: point,
series: series,
seriesIndex: d.series,
pointIndex: d.point
wrap.select('.nv-groups').selectAll('.nv-group')
.selectAll('.nv-point')
//.data(dataWithPoints)
//.style('pointer-events', 'auto') // recativate events, disabled by css
.on('click', function(d,i) {
//nv.log('test', d, i);
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[i];
dispatch.elementClick({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: i
});
})
.on('mouseover', function(d,i) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[i];
dispatch.elementMouseover({
point: point,
series: series,
pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
seriesIndex: d.series,
pointIndex: i
});
})
.on('mouseout', function(d,i) {
if (needsUpdate) return 0;
var series = data[d.series],
point = series.values[i];
dispatch.elementMouseout({
point: point,
series: series,
seriesIndex: d.series,
pointIndex: i
});
});
});
}
needsUpdate = false;
needsUpdate = false;
}
needsUpdate = true;
@ -286,38 +329,62 @@ nv.models.scatter = function() {
.style('fill-opacity', .5);
var points = groups.selectAll('path.nv-point')
.data(function(d) { return d.values });
points.enter().append('path')
.attr('transform', function(d,i) {
return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
})
.attr('d',
d3.svg.symbol()
.type(getShape)
.size(function(d,i) { return z(getSize(d,i)) })
);
points.exit().remove();
d3.transition(groups.exit().selectAll('path.nv-point'))
.attr('transform', function(d,i) {
return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
})
.remove();
points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
d3.transition(points)
.attr('transform', function(d,i) {
return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
})
.attr('d',
d3.svg.symbol()
.type(getShape)
.size(function(d,i) { return z(getSize(d,i)) })
);
if (onlyCircles) {
var points = groups.selectAll('circle.nv-point')
.data(function(d) { return d.values });
points.enter().append('circle')
.attr('cx', function(d,i) { return x0(getX(d,i)) })
.attr('cy', function(d,i) { return y0(getY(d,i)) })
.attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
points.exit().remove();
d3.transition(groups.exit().selectAll('path.nv-point'))
.attr('cx', function(d,i) { return x(getX(d,i)) })
.attr('cy', function(d,i) { return y(getY(d,i)) })
.remove();
points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
d3.transition(points)
.attr('cx', function(d,i) { return x(getX(d,i)) })
.attr('cy', function(d,i) { return y(getY(d,i)) })
.attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
} else {
var points = groups.selectAll('path.nv-point')
.data(function(d) { return d.values });
points.enter().append('path')
.attr('transform', function(d,i) {
return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
})
.attr('d',
d3.svg.symbol()
.type(getShape)
.size(function(d,i) { return z(getSize(d,i)) })
);
points.exit().remove();
d3.transition(groups.exit().selectAll('path.nv-point'))
.attr('transform', function(d,i) {
return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
})
.remove();
points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
d3.transition(points)
.attr('transform', function(d,i) {
//nv.log(d,i,getX(d,i), x(getX(d,i)));
return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
})
.attr('d',
d3.svg.symbol()
.type(getShape)
.size(function(d,i) { return z(getSize(d,i)) })
);
}
// Delay updating the invisible interactive layer for smoother animation
clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
timeoutID = setTimeout(updateInteractiveLayer, 1000);
//clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
//timeoutID = setTimeout(updateInteractiveLayer, 1000);
updateInteractiveLayer();
//store old scales for use in transitions on update
x0 = x.copy();
@ -505,6 +572,12 @@ nv.models.scatter = function() {
return chart;
};
chart.onlyCircles = function(_) {
if (!arguments.length) return onlyCircles;
onlyCircles = _;
return chart;
};
chart.id = function(_) {
if (!arguments.length) return id;
id = _;

@ -297,10 +297,10 @@ svg .title {
.nvd3 .nv-groups path.nv-line {
fill: none;
stroke-width: 2.5px;
/*
stroke-linecap: round;
shape-rendering: geometricPrecision;
/*
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
-webkit-transition: stroke-width 250ms linear;
@ -313,10 +313,10 @@ svg .title {
.nvd3 .nv-groups path.nv-area {
stroke: none;
/*
stroke-linecap: round;
shape-rendering: geometricPrecision;
/*
stroke-width: 2.5px;
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
@ -392,9 +392,11 @@ svg .title {
* Scatter
*/
/* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere
.nvd3 .nv-groups .nv-point {
pointer-events: none;
}
*/
.nvd3 .nv-groups .nv-point.hover {
stroke-width: 20px;

Loading…
Cancel
Save