Added new interactive sparklinePlus example, updated sparkline model and bullet model

master-patched
Bob Monteverde 12 years ago
parent fd585afc17
commit 648306aede

@ -16,6 +16,7 @@ JS_FILES = \
src/models/scatter.js \
src/models/scatterWithLegend.js \
src/models/sparkline.js \
src/models/sparklinePlus.js \
src/models/stackedArea.js \
src/models/stackedAreaWithLegend.js \
src/charts/cumulativeLineChartDaily.js \

@ -31,6 +31,7 @@ var chart = nv.models.bullet()
data = [
{"title":"Revenue","subtitle":"US$, in thousands","ranges":[150,225,300],"measures":[220],"markers":[250]}
/*
//TODO: fix the tooltip offset if multiple
,
{"title":"Profit","subtitle":"%","ranges":[20,25,30],"measures":[21],"markers":[26]},
{"title":"Order Size","subtitle":"US$, average","ranges":[350,500,600],"measures":[100],"markers":[550]},

@ -12,10 +12,15 @@ text {
font: 10px sans-serif;
}
#chart1 {
width: 300px;
height: 32px;
}
</style>
<body>
<h2>Sparkline: <span id="test1" class="sparkline"></span></h2>
<h2>Sparkline: <svg id="chart1" class="sparkline"></svg></h2>
<script src="../lib/d3.v2.js"></script>
<script src="../nv.d3.js"></script>
@ -27,9 +32,9 @@ nv.addGraph({
generate: function() {
var chart = nv.models.sparkline()
.width(400)
.height(80)
.height(30)
d3.select("#test1")
d3.select("#chart1")
.datum(sine())
.call(chart);

@ -0,0 +1,62 @@
<!DOCTYPE html>
<meta charset="utf-8">
<link href="../src/d3.css" rel="stylesheet" type="text/css">
<style>
.sparkline path {
fill: none;
stroke: #444;
}
text {
font: 10px sans-serif;
}
#chart1 {
width: 400px;
height: 50px;
}
</style>
<body>
<h2>SparklinePlus: <svg id="chart1" class="sparkline"></svg></h2>
<script src="../lib/d3.v2.js"></script>
<script src="../nv.d3.js"></script>
<script src="../src/models/sparkline.js"></script>
<script src="../src/models/sparklinePlus.js"></script>
<script>
//Format A
nv.addGraph({
generate: function() {
var chart = nv.models.sparklinePlus()
.width(400)
.height(50)
d3.select("#chart1")
.datum(sine())
.call(chart);
return chart;
},
callback: function(graph) {
//log("Sparkline rendered");
}
});
function sine() {
var sin = [];
for (var i = 0; i < 100; i++) {
sin.push({x: i, y: Math.sin(i/10)});
}
return sin;
}
</script>

@ -635,7 +635,7 @@ nv.models.bullet = function() {
// Compute the new x-scale.
var x1 = d3.scale.linear()
.domain([0, Math.max(rangez[0], markerz[0], measurez[0])])
.domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain
.range(reverse ? [width, 0] : [0, width]);
// Retrieve the old x-scale, if this is an update.
@ -3279,36 +3279,43 @@ nv.models.scatterWithLegend = function() {
}
nv.models.sparkline = function() {
var margin = {top: 3, right: 3, bottom: 3, left: 3},
width = 200,
height = 20,
var margin = {top: 0, right: 0, bottom: 0, left: 0},
width = 400,
height = 32,
animate = true,
color = d3.scale.category20().range();
getX = function(d) { return d.x },
getY = function(d) { return d.y },
color = d3.scale.category20().range(),
xDomain, yDomain;
var x = d3.scale.linear(),
y = d3.scale.linear();
function chart(selection) {
selection.each(function(data) {
var availableWidth = width - margin.left - margin.right,
availableHeight = height - margin.top - margin.bottom;
x .domain(d3.extent(data, function(d) { return d.x } ))
.range([0, width - margin.left - margin.right]);
x .domain(xDomain || d3.extent(data, getX ))
.range([0, availableWidth]);
y .domain(d3.extent(data, function(d) { return d.y } ))
.range([height - margin.top - margin.bottom, 0]);
y .domain(yDomain || d3.extent(data,getY ))
.range([availableHeight, 0]);
var svg = d3.select(this).selectAll('svg').data([data]);
var wrap = d3.select(this).selectAll('g.sparkline').data([data]);
var gEnter = svg.enter().append('svg').append('g');
var gEnter = wrap.enter().append('g');
//var gEnter = svg.enter().append('svg').append('g');
gEnter.append('g').attr('class', 'sparkline')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
//.style('fill', function(d, i){ return d.color || color[i * 2 % 20] })
.style('stroke', function(d, i){ return d.color || color[i * 2 % 20] });
svg .attr('width', width)
d3.select(this)
.attr('width', width)
.attr('height', height);
@ -3318,18 +3325,19 @@ nv.models.sparkline = function() {
paths.exit().remove();
paths
.attr('d', d3.svg.line()
.x(function(d) { return x(d.x) })
.y(function(d) { return y(d.y) })
.x(function(d) { return x(getX(d)) })
.y(function(d) { return y(getY(d)) })
);
// TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)
var points = gEnter.select('.sparkline').selectAll('circle.point')
.data(function(d) { return d.filter(function(p) { return y.domain().indexOf(p.y) != -1 }) });
points.enter().append('circle').attr('class', 'point');
points.exit().remove();
points
.attr('cx', function(d) { return x(d.x) })
.attr('cy', function(d) { return y(d.y) })
.attr('cx', function(d) { return x(getX(d)) })
.attr('cy', function(d) { return y(getY(d)) })
.attr('r', 2)
.style('stroke', function(d, i){ return d.y == y.domain()[0] ? '#d62728' : '#2ca02c' })
.style('fill', function(d, i){ return d.y == y.domain()[0] ? '#d62728' : '#2ca02c' });
@ -3357,6 +3365,177 @@ nv.models.sparkline = function() {
return chart;
};
chart.x = function(_) {
if (!arguments.length) return getX;
getX = d3.functor(_);
return chart;
};
chart.y = function(_) {
if (!arguments.length) return getY;
getY = d3.functor(_);
return chart;
};
chart.xDomain = function(_) {
if (!arguments.length) return xDomain;
xDomain = _;
return chart;
};
chart.yDomain = function(_) {
if (!arguments.length) return yDomain;
yDomain = _;
return chart;
};
chart.animate = function(_) {
if (!arguments.length) return animate;
animate = _;
return chart;
};
return chart;
}
nv.models.sparklinePlus = function() {
var margin = {top: 15, right: 30, bottom: 3, left: 30},
width = 400,
height = 50,
animate = true,
getX = function(d) { return d.x },
getY = function(d) { return d.y },
color = d3.scale.category10().range(),
id = Math.floor(Math.random() * 100000), //Create semi-unique ID incase user doesn't selet one
xTickFormat = d3.format(',r'),
yTickFormat = d3.format(',.2f');
var x = d3.scale.linear(),
y = d3.scale.linear(),
sparkline = nv.models.sparkline();
function chart(selection) {
selection.each(function(data) {
var availableWidth = width - margin.left - margin.right,
availableHeight = height - margin.top - margin.bottom;
x .domain(d3.extent(data, getX ))
.range([0, availableWidth]);
y .domain(d3.extent(data, getY ))
.range([availableHeight, 0]);
var wrap = d3.select(this).selectAll('g.sparklineplus').data([data]);
var gEnter = wrap.enter().append('g')
//var gEnter = svg.enter().append('svg').append('g');
var sparklineWrap = gEnter.append('g').attr('class', 'sparklineplus')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
//.style('fill', function(d, i){ return d.color || color[i % 10] })
.style('stroke', function(d, i){ return d.color || color[i % 10] });
sparkline
.xDomain(x.domain())
.yDomain(y.domain());
sparklineWrap
//.attr('width', width)
//.attr('height', height)
.call(sparkline);
var hoverArea = sparklineWrap.append('rect').attr('class', 'hoverArea')
.attr('width', availableWidth)
.attr('height', availableHeight)
.on('mousemove', sparklineHover);
var hoverValue = sparklineWrap.append('g').attr('class', 'hoverValue');
var hoverLine = hoverValue.append('line')
.attr('x1', x.range()[1])
.attr('y1', -margin.top)
.attr('x2', x.range()[1])
.attr('y2', height)
var hoverX = hoverValue.append('text').attr('class', 'xValue')
.attr('transform', function(d) { return 'translate(' + x(d) + ',0)' })
.attr('text-anchor', 'end')
.attr('dy', '1em')
var hoverY = hoverValue.append('text').attr('class', 'yValue')
.attr('transform', function(d) { return 'translate(' + x(d) + ',0)' })
.attr('text-anchor', 'start')
.attr('dy', '1em')
function sparklineHover() {
var pos = d3.event.offsetX - margin.left;
//console.log(data.length, pos, x.invert(pos), x(pos) );
hoverLine
.attr('x1', pos)
.attr('x2', pos);
hoverX
.attr('transform', function(d) { return 'translate(' + (pos - 6) + ',' + (-margin.top) + ')' })
.text(xTickFormat(pos));
hoverY
.attr('transform', function(d) { return 'translate(' + (pos + 6) + ',' + (-margin.top) + ')' })
//.text(data[pos] && yTickFormat(data[pos].y));
.text(yTickFormat(getY(data[Math.round(x.invert(pos))])));
}
});
return chart;
}
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
sparkline.width(_ - margin.left - margin.right);
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
sparkline.height(_ - margin.top - margin.bottom);
return chart;
};
chart.x = function(_) {
if (!arguments.length) return getX;
getX = d3.functor(_);
sparkline.x(_);
return chart;
};
chart.y = function(_) {
if (!arguments.length) return getY;
getY = d3.functor(_);
sparkline.y(_);
return chart;
};
chart.id = function(_) {
if (!arguments.length) return id;
id = _;
return chart;
};
chart.animate = function(_) {
if (!arguments.length) return animate;
animate = _;

2
nv.d3.min.js vendored

File diff suppressed because one or more lines are too long

@ -316,3 +316,36 @@ svg .title {
.bullet .measure.s1 { fill: darkblue; }
.bullet .title { font-size: 14px; font-weight: bold; }
.bullet .subtitle { fill: #999; }
/**********
* Sparkline plus
*/
.sparklineplus .hoverValue line {
stroke: #f44;
stroke-width: 1px;
}
.sparklineplus,
.sparklineplus g {
pointer-events: all;
}
.sparklineplus .hoverArea {
fill-opacity: 0;
stroke-opacity: 0;
}
.sparklineplus .xValue,
.sparklineplus .yValue {
stroke: #666;
font-size: .4em;
font-weight: normal;
}
.sparklineplus .yValue {
stroke: #f66;
}

@ -25,7 +25,7 @@ nv.models.bullet = function() {
// Compute the new x-scale.
var x1 = d3.scale.linear()
.domain([0, Math.max(rangez[0], markerz[0], measurez[0])])
.domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain
.range(reverse ? [width, 0] : [0, width]);
// Retrieve the old x-scale, if this is an update.

@ -1,35 +1,42 @@
nv.models.sparkline = function() {
var margin = {top: 3, right: 3, bottom: 3, left: 3},
width = 200,
height = 20,
var margin = {top: 0, right: 0, bottom: 0, left: 0},
width = 400,
height = 32,
animate = true,
color = d3.scale.category20().range();
getX = function(d) { return d.x },
getY = function(d) { return d.y },
color = d3.scale.category20().range(),
xDomain, yDomain;
var x = d3.scale.linear(),
y = d3.scale.linear();
function chart(selection) {
selection.each(function(data) {
var availableWidth = width - margin.left - margin.right,
availableHeight = height - margin.top - margin.bottom;
x .domain(d3.extent(data, function(d) { return d.x } ))
.range([0, width - margin.left - margin.right]);
x .domain(xDomain || d3.extent(data, getX ))
.range([0, availableWidth]);
y .domain(d3.extent(data, function(d) { return d.y } ))
.range([height - margin.top - margin.bottom, 0]);
y .domain(yDomain || d3.extent(data,getY ))
.range([availableHeight, 0]);
var svg = d3.select(this).selectAll('svg').data([data]);
var wrap = d3.select(this).selectAll('g.sparkline').data([data]);
var gEnter = svg.enter().append('svg').append('g');
var gEnter = wrap.enter().append('g');
//var gEnter = svg.enter().append('svg').append('g');
gEnter.append('g').attr('class', 'sparkline')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
//.style('fill', function(d, i){ return d.color || color[i * 2 % 20] })
.style('stroke', function(d, i){ return d.color || color[i * 2 % 20] });
svg .attr('width', width)
d3.select(this)
.attr('width', width)
.attr('height', height);
@ -39,18 +46,19 @@ nv.models.sparkline = function() {
paths.exit().remove();
paths
.attr('d', d3.svg.line()
.x(function(d) { return x(d.x) })
.y(function(d) { return y(d.y) })
.x(function(d) { return x(getX(d)) })
.y(function(d) { return y(getY(d)) })
);
// TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)
var points = gEnter.select('.sparkline').selectAll('circle.point')
.data(function(d) { return d.filter(function(p) { return y.domain().indexOf(p.y) != -1 }) });
points.enter().append('circle').attr('class', 'point');
points.exit().remove();
points
.attr('cx', function(d) { return x(d.x) })
.attr('cy', function(d) { return y(d.y) })
.attr('cx', function(d) { return x(getX(d)) })
.attr('cy', function(d) { return y(getY(d)) })
.attr('r', 2)
.style('stroke', function(d, i){ return d.y == y.domain()[0] ? '#d62728' : '#2ca02c' })
.style('fill', function(d, i){ return d.y == y.domain()[0] ? '#d62728' : '#2ca02c' });
@ -78,6 +86,30 @@ nv.models.sparkline = function() {
return chart;
};
chart.x = function(_) {
if (!arguments.length) return getX;
getX = d3.functor(_);
return chart;
};
chart.y = function(_) {
if (!arguments.length) return getY;
getY = d3.functor(_);
return chart;
};
chart.xDomain = function(_) {
if (!arguments.length) return xDomain;
xDomain = _;
return chart;
};
chart.yDomain = function(_) {
if (!arguments.length) return yDomain;
yDomain = _;
return chart;
};
chart.animate = function(_) {
if (!arguments.length) return animate;
animate = _;

@ -0,0 +1,147 @@
nv.models.sparklinePlus = function() {
var margin = {top: 15, right: 30, bottom: 3, left: 30},
width = 400,
height = 50,
animate = true,
getX = function(d) { return d.x },
getY = function(d) { return d.y },
color = d3.scale.category10().range(),
id = Math.floor(Math.random() * 100000), //Create semi-unique ID incase user doesn't selet one
xTickFormat = d3.format(',r'),
yTickFormat = d3.format(',.2f');
var x = d3.scale.linear(),
y = d3.scale.linear(),
sparkline = nv.models.sparkline();
function chart(selection) {
selection.each(function(data) {
var availableWidth = width - margin.left - margin.right,
availableHeight = height - margin.top - margin.bottom;
x .domain(d3.extent(data, getX ))
.range([0, availableWidth]);
y .domain(d3.extent(data, getY ))
.range([availableHeight, 0]);
var wrap = d3.select(this).selectAll('g.sparklineplus').data([data]);
var gEnter = wrap.enter().append('g')
//var gEnter = svg.enter().append('svg').append('g');
var sparklineWrap = gEnter.append('g').attr('class', 'sparklineplus')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
//.style('fill', function(d, i){ return d.color || color[i % 10] })
.style('stroke', function(d, i){ return d.color || color[i % 10] });
sparkline
.xDomain(x.domain())
.yDomain(y.domain());
sparklineWrap
//.attr('width', width)
//.attr('height', height)
.call(sparkline);
var hoverArea = sparklineWrap.append('rect').attr('class', 'hoverArea')
.attr('width', availableWidth)
.attr('height', availableHeight)
.on('mousemove', sparklineHover);
var hoverValue = sparklineWrap.append('g').attr('class', 'hoverValue');
var hoverLine = hoverValue.append('line')
.attr('x1', x.range()[1])
.attr('y1', -margin.top)
.attr('x2', x.range()[1])
.attr('y2', height)
var hoverX = hoverValue.append('text').attr('class', 'xValue')
.attr('transform', function(d) { return 'translate(' + x(d) + ',0)' })
.attr('text-anchor', 'end')
.attr('dy', '1em')
var hoverY = hoverValue.append('text').attr('class', 'yValue')
.attr('transform', function(d) { return 'translate(' + x(d) + ',0)' })
.attr('text-anchor', 'start')
.attr('dy', '1em')
function sparklineHover() {
var pos = d3.event.offsetX - margin.left;
//console.log(data.length, pos, x.invert(pos), x(pos) );
hoverLine
.attr('x1', pos)
.attr('x2', pos);
hoverX
.attr('transform', function(d) { return 'translate(' + (pos - 6) + ',' + (-margin.top) + ')' })
.text(xTickFormat(pos));
hoverY
.attr('transform', function(d) { return 'translate(' + (pos + 6) + ',' + (-margin.top) + ')' })
//.text(data[pos] && yTickFormat(data[pos].y));
.text(yTickFormat(getY(data[Math.round(x.invert(pos))])));
}
});
return chart;
}
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
sparkline.width(_ - margin.left - margin.right);
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
sparkline.height(_ - margin.top - margin.bottom);
return chart;
};
chart.x = function(_) {
if (!arguments.length) return getX;
getX = d3.functor(_);
sparkline.x(_);
return chart;
};
chart.y = function(_) {
if (!arguments.length) return getY;
getY = d3.functor(_);
sparkline.y(_);
return chart;
};
chart.id = function(_) {
if (!arguments.length) return id;
id = _;
return chart;
};
chart.animate = function(_) {
if (!arguments.length) return animate;
animate = _;
return chart;
};
return chart;
}
Loading…
Cancel
Save