Added Initial nvd3 definitions

This commit is contained in:
PjMitchell
2015-12-20 20:51:20 +00:00
parent 16134c168d
commit 3aff56f232
9 changed files with 809 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
/// <reference path="../d3/d3.d.ts" />
/// <reference path="nvd3.d.ts" />
var width = 960,
height = 55,
margin = {top: 5, right: 40, bottom: 20, left: 120};
var chart = nv.models.bullet()
.width(width - margin.right - margin.left)
.height(height - margin.top - margin.bottom);
var data = [
{"title":"Revenue","subtitle":"US$, in thousands","ranges":[-150,-225,-300],"measures":[-220],"markers":[-250]}
];
//TODO: to be consistent with other models, should be appending a g to an already made svg, not creating the svg element
var vis = d3.select("#chart").selectAll("svg")
.data(data)
.enter().append("svg")
.attr("class", "bullet nvd3")
.attr("width", width)
.attr("height", height);
vis.transition().duration(1000).call(chart);
var transition = function() {
vis.datum(randomize);
vis.transition().duration(1000).call(chart);
};
function randomize(d) {
if (!d.randomizer) d.randomizer = randomizer(d);
d.ranges = d.ranges.map(d.randomizer);
d.markers = d.markers.map(d.randomizer);
d.measures = d.measures.map(d.randomizer);
return d;
}
function randomizer(d) {
var k = d3.max(d.ranges) * .2;
return function(d) {
return Math.max(0, d + k * (Math.random() - .5));
};
}
d3.select('body').on('click', transition);
+72
View File
@@ -0,0 +1,72 @@
/// <reference path="../d3/d3.d.ts" />
/// <reference path="nvd3.d.ts" />
var width = 960,
height = 80,
margin = {top: 5, right: 40, bottom: 20, left: 120};
var chart = nv.models.bulletChart()
.width(width - margin.right - margin.left)
.height(height - margin.top - margin.bottom);
var chart2 = nv.models.bulletChart()
.width(width - margin.right - margin.left)
.height(height - margin.top - margin.bottom);
var data = [
{"title":"Revenue","subtitle":"US$, in thousands","ranges":[150,225,300],"measures":[220],"markers":[250]},
{"title":"Order Size","subtitle":"US$, average","ranges":[350,500,600],"measures":[100],"markers":[550]},
{"title":"Satisfaction","subtitle":"out of 5","ranges":[3.5,4.25,5],"measures":[3.2,4.7],"markers":[4.4]}
];
var dataWithLabels = [{
"title":"Revenue",
"subtitle":"US$, in thousands",
"ranges":[150,225,300],
"measures":[220],
"markers":[250, 100],
"markerLabels":['Target Inventory', 'Low Inventory'],
"rangeLabels":['Maximum Inventory','Average Inventory','Minimum Inventory'],
"measureLabels":['Current Inventory']
}];
//TODO: to be consistent with other models, should be appending a g to an already made svg, not creating the svg element
var vis = d3.select("#chart").selectAll("svg")
.data(data)
.enter().append("svg")
.attr("class", "bullet nvd3")
.attr("width", width)
.attr("height", height);
vis.transition().duration(1000).call(chart);
var vis2 = d3.select("#chart2").selectAll("svg")
.data(dataWithLabels)
.enter().append('svg')
.attr('class',"bullet nvd3")
.attr("width",width)
.attr("height",height);
vis2.transition().duration(1000).call(chart2);
var transition = function() {
vis.datum(randomize).transition().duration(1000).call(chart);
vis2.datum(randomize).transition().duration(1000).call(chart2);
};
function randomize(d) {
if (!d.randomizer) d.randomizer = randomizer(d);
d.ranges = d.ranges.map(d.randomizer);
d.markers = d.markers.map(d.randomizer);
d.measures = d.measures.map(d.randomizer);
return d;
}
function randomizer(d) {
var k = d3.max(d.ranges) * .2;
return function(d) {
return Math.max(0, d + k * (Math.random() - .5));
};
}
d3.select('body').on('click', transition);
+57
View File
@@ -0,0 +1,57 @@
/// <reference path="../d3/d3.d.ts" />
/// <reference path="nvd3.d.ts" />
nv.addGraph(function() {
var chart = nv.models.boxPlotChart()
.x(function(d) { return d.label })
.y(function(d) { return d.values.Q3 })
.staggerLabels(true)
.maxBoxWidth(75) // prevent boxes from being incredibly wide
.yDomain([0, 500])
;
d3.select('#chart1 svg')
.datum(exampleData())
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
function exampleData() {
return [
{
label: "Sample A",
values: {
Q1: 120,
Q2: 150,
Q3: 200,
whisker_low: 115,
whisker_high: 210,
outliers: [50, 100, 225]
},
},
{
label: "Sample B",
values: {
Q1: 300,
Q2: 350,
Q3: 400,
whisker_low: 225,
whisker_high: 425,
outliers: [175]
},
},
{
label: "Sample C",
values: {
Q1: 50,
Q2: 100,
Q3: 125,
whisker_low: 25,
whisker_high: 175,
outliers: [0]
},
}
];
}
+59
View File
@@ -0,0 +1,59 @@
/// <reference path="../d3/d3.d.ts" />
/// <reference path="nvd3.d.ts" />
nv.addGraph({
generate: function() {
var chart = nv.models.historicalBar();
d3.select("#test1")
.datum(sinData())
.datum(sinData())
.transition()
.call(chart);
return chart;
},
callback: function(graph) {
graph.dispatch.on('elementMouseover', function(e) {
var offsetElement = document.getElementById("chart"),
left = e.pos[0],
top = e.pos[1];
var content = '<p>' + e.point.y + '</p>';
nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's');
});
graph.dispatch.on('elementMouseout', function(e) {
nv.tooltip.cleanup();
});
}
});
//Simple test data generators
function sinAndCos() {
var sin = [],
cos = [];
for (var i = 0; i < 100; i++) {
sin.push({x: i, y: Math.sin(i/10)});
cos.push({x: i, y: .5 * Math.cos(i/10)});
}
return [
{values: sin, key: "Sine Wave", color: "#ff7f0e"},
{values: cos, key: "Cosine Wave", color: "#2ca02c"}
];
}
function sinData() {
var sin = [];
for (var i = 0; i < 100; i++) {
sin.push({x: i, y: Math.sin(i/10)});
}
return [{
values: sin,
key: "Sine Wave",
color: "#ff7f0e"
}];
}
+165
View File
@@ -0,0 +1,165 @@
/// <reference path="../d3/d3.d.ts" />
/// <reference path="nvd3.d.ts" />
var data = [{
values : []
}];
var i, x;
var gap = false;
var prevVal = 3000;
var tickCount = 100;
var probEnterGap = 0.1;
var probExitGap = 0.2;
var barTimespan = 30 * 60; // thirty minutes in seconds
var startOfTime = 1425096000;
for (i = 0; i < tickCount; i++) {
x = startOfTime + i * barTimespan;
if (!gap) {
if (Math.random() > probEnterGap) {
prevVal += (Math.random() - 0.5) * 500;
if (prevVal <= 0) {
prevVal = Math.random() * 100;
}
data[0].values.push({x: x * 1000, y: prevVal});
}
else {
gap = true;
}
}
else {
if (Math.random() < probExitGap) {
gap = false;
}
}
}
var chart : nv.HistoricalBarChart;
var halfBarXMin = data[0].values[0].x - barTimespan / 2 * 1000;
var halfBarXMax = data[0].values[data[0].values.length-1].x + barTimespan / 2 * 1000;
function renderChart(location, meaning) {
nv.addGraph(function() {
chart = nv.models.historicalBarChart();
chart
.xScale(d3.time.scale()) // use a time scale instead of plain numbers in order to get nice round default values in the axis
.color(['#68c'])
.forceX([halfBarXMin, halfBarXMax]) // fix half-bar problem on the first and last bars
.useInteractiveGuideline(true) // check out the css that turns the guideline into this nice thing
.margin({"left": 80, "right": 50, "top": 20, "bottom": 30})
.duration(0)
;
var tickMultiFormat = d3.time.format.multi([
["%-I:%M%p", function(d) { return d.getMinutes(); }], // not the beginning of the hour
["%-I%p", function(d) { return d.getHours(); }], // not midnight
["%b %-d", function(d) { return d.getDate() != 1; }], // not the first of the month
["%b %-d", function(d) { return d.getMonth(); }], // not Jan 1st
["%Y", function() { return true; }]
]);
chart.xAxis
.showMaxMin(false)
.tickPadding(10)
.tickFormat(function (d) { return tickMultiFormat(new Date(d)); })
;
chart.yAxis
.showMaxMin(false)
.tickFormat(d3.format(",.0f"))
;
var svgElem = d3.select(location);
svgElem
.datum(data)
.transition()
.call(chart);
// make our own x-axis tick marks because NVD3 doesn't provide any
var tickY2 = chart.yAxis.scale().range()[1];
var lineElems = svgElem
.select('.nv-x.nv-axis.nvd3-svg')
.select('.nvd3.nv-wrap.nv-axis')
.select('g')
.selectAll('.tick')
.data(chart.xScale().ticks())
.append('line')
.attr('class', 'x-axis-tick-mark')
.attr('x2', 0)
.attr('y1', tickY2 + 4)
.attr('y2', tickY2)
.attr('stroke-width', 1)
;
// set up the tooltip to display full dates
var tsFormat = d3.time.format('%b %-d, %Y %I:%M%p');
var contentGenerator = chart.interactiveLayer.tooltip.contentGenerator();
var tooltip = chart.interactiveLayer.tooltip;
tooltip.contentGenerator(function (d) { d.value = d.series[0].data.x; return contentGenerator(d); });
tooltip.headerFormatter(function (d) { return tsFormat(new Date(d)); });
// common stuff for the sections below
var xScale = chart.xScale();
var xPixelFirstBar = xScale(data[0].values[0].x);
var xPixelSecondBar = xScale(data[0].values[0].x + barTimespan * 1000);
var barWidth = xPixelSecondBar - xPixelFirstBar; // number of pixels representing time delta per bar
// fix the bar widths so they don't overlap when there are gaps
function fixBarWidths(barSpacingFraction) {
svgElem
.selectAll('.nv-bars')
.selectAll('rect')
.attr('width', (1 - barSpacingFraction) * barWidth)
.attr('transform', function(d, i) {
var deltaX = xScale(data[0].values[i].x) - xPixelFirstBar;
deltaX += barSpacingFraction / 2 * barWidth;
return 'translate(' + deltaX + ', 0)';
})
;
}
/*
If you're representing sample measurements spaced a certain time apart, the tick marks should
be in the middle of the bars and some spacing between bars is recommended to aid with interpretation.
On the other hand, if you want to represent a quantity measured over a span of time (one bar), you're
better off placing the ticks on the edge of the bar and leaving no gap in between bars.
*/
function shiftXAxis() {
var xAxisElem = svgElem.select('.nv-axis.nv-x');
var transform = xAxisElem.attr('transform');
var xShift = -barWidth/2;
transform = transform.replace('0,', xShift + ',');
xAxisElem.attr('transform', transform);
}
if (meaning === 'instant') {
fixBarWidths(0.2);
}
else if (meaning === 'timespan') {
fixBarWidths(0.0);
shiftXAxis();
}
return chart;
});
}
renderChart('#test1', 'instant');
renderChart('#test2', 'timespan');
window.setTimeout(function() {
window.setTimeout(function() {
document.getElementById('sc-one').style.display = 'block';
document.getElementById('sc-two').style.display = 'none';
}, 0);
}, 0);
function switchChartStyle(style) {
if (style === 'instant') {
document.getElementById('sc-one').style.display = 'block';
document.getElementById('sc-two').style.display = 'none';
}
else if (style === 'timespan') {
document.getElementById('sc-one').style.display = 'none';
document.getElementById('sc-two').style.display = 'block';
}
}
+67
View File
@@ -0,0 +1,67 @@
/// <reference path="../d3/d3.d.ts" />
/// <reference path="nvd3.d.ts" />
var width = 500,
height = 20;
var legend = nv.models.legend();
d3.select('#test1')
.attr('width', width)
.attr('height', height)
.datum(sinAndCos());
var legend2 = nv.models.legend()
.align(false);
d3.select('#test2')
.attr('width', width)
.attr('height', height)
.datum(sinAndCos()).call(legend2);
var legend3 = nv.models.legend()
.width(900)
.padding(70);
d3.select('#test3')
.attr('width', 900)
.attr('height', 200)
.datum(sinAndCos()).call(legend3);
var update = function() {
d3.select('#test1').call(legend);
}
update();
legend.dispatch.on('stateChange', function(d) {
console.log(d);
update();
});
d3.select('#changeData').on('click', function() {
d3.select('#test1')
.datum(differentData())
.call(legend);
});
function sinAndCos() {
return [
{key: "Sine Wave"},
{key: "A Very Long Label With Over Twenty Characters"},
{key: "A Very Long Series Label With Over Twenty Characters"},
{key: "A Very Long Series Label With Over Twenty Characters"},
{key: "Cosine Wave"},
{key: "Another test label"}
];
}
function differentData() {
return [
{key: "Fixed Income"},
{key: "Derivatives"},
{key: "Credit Default Swaps"},
{key: "Equities"},
{key: "Bonds"},
{key: "Stocks"},
{key: "Apple"}
];
}
+36
View File
@@ -0,0 +1,36 @@
/// <reference path="../d3/d3.d.ts" />
/// <reference path="nvd3.d.ts" />
var data = [{values: [
{"date": 15707, "open": 145.11, "high": 146.15, "low": 144.73, "close": 146.06, "volume": 192059000, "adjusted": 144.65},
{"date": 15953, "open": 165.85, "high": 166.4, "low": 165.73, "close": 165.96, "volume": 62930500, "adjusted": 165.96}
]}];
nv.addGraph(function() {
var chart = nv.models.ohlcBarChart()
.x(function(d) { return d['date'] })
.y(function(d) { return d['close'] })
.duration(250)
.margin({left: 75, bottom: 50});
// chart sub-models (ie. xAxis, yAxis, etc) when accessed directly, return themselves, not the parent chart, so need to chain separately
chart.xAxis
.axisLabel("Dates")
.tickFormat(function(d) {
// I didn't feel like changing all the above date values
// so I hack it to make each value fall on a different date
return d3.time.format('%x')(new Date(new Date().valueOf() - (20000 * 86400000) + (d * 86400000)));
});
chart.yAxis
.axisLabel('Stock Price')
.tickFormat(function(d,i){ return '$' + d3.format(',.1f')(d); });
d3.select("#chart1 svg")
.datum(data)
.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
+55
View File
@@ -0,0 +1,55 @@
/// <reference path="../d3/d3.d.ts" />
/// <reference path="nvd3.d.ts" />
var width = 500,
height = 20;
var tooltip = nv.models.tooltip();
tooltip.duration(0);
d3.select('.tooltip_me')
.on('mouseover', function(d,i) {
console.log("mouseover", d, i);
var data = {series: {
key: "title",
value: "the value",
color: "#229922"
}};
tooltip.data(data).hidden(false);
})
.on('mouseout', function(d,i) {
console.log("mouseout", d, i);
tooltip.hidden(true);
})
.on('mousemove', function(d,i) {
console.log("mousemove", d, i);
tooltip.position({top: d3.event.pageY, left: d3.event.pageX})();
});
// we must also test the scatter/line way of getting position
// Wrapping in nv.addGraph allows for '0 timeout render', stores rendered charts in nv.graphs, and may do more in the future... it's NOT required
var chart;
nv.addGraph(function() {
chart = nv.models.lineChart()
.showXAxis(false)
.showLegend(false)
.clipVoronoi(false)
.showVoronoi(true)
.showYAxis(false);
d3.select('#test2')
.datum(sinAndCos())
.call(chart);
return chart;
});
function sinAndCos() {
var cos = [];
for (var i = 0; i < 5; i++) {
cos.push({x: i, y: Math.round(.5 * Math.cos(i/10) * 100) / 100});
}
return [{
values: cos,
key: "Cosine Wave",
color: "#2ca02c"
}];
}
+252
View File
@@ -0,0 +1,252 @@
// Type definitions for nvd3 1.8.1
// Project: https://github.com/novus/nvd3
// Definitions by: Maxime LUCE <https://github.com/PjMitchell/>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/// <reference path="../d3/d3.d.ts" />
declare module nv {
// interface Datum{
// values: any[],
// key: string,
// color: string
// }
interface Margin {
left?: number,
right?: number,
top?: number,
bottom?: number
}
interface Legend extends Chart<Legend> {
key(): any;
key(value: any): Legend;
align(): boolean;
align(value: boolean): Legend;
maxKeyLength(): number;
maxKeyLength(value: number): Legend;
rightAlign(): boolean;
rightAlign(value: boolean): Legend;
//define how much space between legend items. - recommend 32 for furious version
padding(): number;
//define how much space between legend items. - recommend 32 for furious version
padding(value: number): Legend;
//If true, legend will update data.disabled and trigger a 'stateChange' dispatch.
updateState(): boolean;
//If true, legend will update data.disabled and trigger a 'stateChange' dispatch.
updateState(value: boolean): Legend;
//If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at
radioButtonMode(): boolean;
//If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at
radioButtonMode(value: boolean): Legend;
expanded(): boolean;
expanded(value: boolean): Legend;
//Options are "classic" and "furious"
vers(): string;
//Options are "classic" and "furious"
vers(value: string): Legend;
}
/**
*NVD3 extension of D3 Axis
*/
interface NvAxis extends d3.svg.Axis {
(selection: d3.Selection<any>): void;
(selection: d3.Transition<any>): void;
scale(): any;
scale(scale: any): NvAxis;
orient(): string;
orient(orientation: string): NvAxis;
ticks(): any[];
ticks(...args: any[]): NvAxis;
tickValues(): any[];
tickValues(values: any[]): NvAxis;
tickSize(): number;
tickSize(size: number): NvAxis;
tickSize(inner: number, outer: number): NvAxis;
innerTickSize(): number;
innerTickSize(size: number): NvAxis;
outerTickSize(): number;
outerTickSize(size: number): NvAxis;
tickPadding(): number;
tickPadding(padding: number): NvAxis;
tickFormat(): (t: any) => string;
tickFormat(format: (t: any) => string): NvAxis;
tickFormat(format:string): NvAxis;
tickFormat(format: (t: any, i: any) => string): NvAxis;
showMaxMin(value: boolean) : NvAxis;
axisLabel(value: string) : NvAxis;
}
interface InteractiveLayer {
tooltip : Tooltip
}
interface ContentGenerator {
(arg: any) :string
}
interface Tooltip {
show([left , top]: [number,number], content: string, gravity: string) //todo sort out use on nv.tooltip.
cleanup():void; //todo sort out use on nv.tooltip.
contentGenerator(): ContentGenerator;
contentGenerator(func: (any) => string): void;
headerFormatter(func: (any)=> string): void;
}
interface Utils {
windowResize(listener: (ev: Event) => any): void;
}
interface ChartBase {
update(): void;
interactiveLayer :InteractiveLayer;
(transition: d3.Transition<any[]>, ...args: any[]) :any;
(selection: d3.Selection<any[]>, ...args: any[]) :any;
(transition: d3.Transition<any>, ...args: any[]) :any;
(selection: d3.Selection<any>, ...args: any[]) :any;
}
interface Chart<TChart extends ChartBase> extends ChartBase {
margin() : Margin;
margin(value: Margin) : TChart;
width(): number;
width(value: number) : TChart;
height(): number;
height(value: number) : TChart;
color(value:string[]) : TChart;
color(value:string) : TChart;
dispatch : d3.Dispatch;
}
interface TwoDimensionalChart<TChart extends ChartBase> extends Chart<TChart>
{
xAxis : NvAxis;
yAxis : NvAxis;
x(func: (any)=> any) : TChart;
y(func: (any)=> any) : TChart;
xScale(scale: d3.time.Scale<number, number>) : TChart;
xScale() : d3.time.Scale<number, number>;
yScale(scale: d3.time.Scale<number, number>) : TChart;
yScale() : d3.time.Scale<number, number>
forceX([xMin, xMax] : [number,number]) : TChart;
forceY([xMin, xMax] : [number,number]) : TChart;
}
interface HistoricalBarBase<TChart extends ChartBase> extends TwoDimensionalChart<TChart>{
}
interface HistoricalBar extends HistoricalBarBase<HistoricalBar>{
}
interface HistoricalBarChart extends HistoricalBarBase<HistoricalBarChart>{
bars: HistoricalBar;
legend: Legend;
noData(): any //todo;
noData(value: any): HistoricalBarChart //todo;
defaultState(): any //todo;
defaultState(value: any): HistoricalBarChart //todo;
showXAxis(): boolean //todo;
showXAxis(value: boolean): HistoricalBarChart //todo;
showLegend(): boolean //todo;
showLegend(value: boolean): HistoricalBarChart //todo;
showYAxis(): boolean //todo;
showYAxis(value: boolean): HistoricalBarChart //todo;
rightAlignYAxis(): boolean //todo;
rightAlignYAxis(value: boolean): HistoricalBarChart //todo;
useInteractiveGuideline(value : boolean) : HistoricalBarChart;
duration(value: number) : HistoricalBarChart;
interactiveLayer :InteractiveLayer;
}
interface BoxPlotChart extends TwoDimensionalChart<BoxPlotChart>{
useInteractiveGuideline(value : boolean) : BoxPlotChart;
duration(value: number) : BoxPlotChart;
staggerLabels(value : boolean) : BoxPlotChart;
maxBoxWidth(value: number) : BoxPlotChart;
yDomain([xMin, xMax] : [number,number]): BoxPlotChart;
xDomain([xMin, xMax] : [number,number]): BoxPlotChart;
showXAxis(): boolean //todo;
showXAxis(value: boolean): BoxPlotChart //todo;
showYAxis(): boolean //todo;
showYAxis(value: boolean): BoxPlotChart //todo;
rightAlignYAxis(): boolean //todo;
rightAlignYAxis(value: boolean): BoxPlotChart //todo;
}
interface BulletBase<TBullet extends ChartBase> extends Chart<TBullet> {
orient(): string;
orient(orientation: string): TBullet;
tickFormat(): (t: any) => string;
tickFormat(format: (t: any) => string): TBullet;
tickFormat(format:string): NvAxis;
tickFormat(format: (t: any, i: any) => string): TBullet;
forceX([xMin, xMax] : [number,number]) : TBullet;
ranges(): any //todo;
ranges(value: any): TBullet //todo;
markers(): any //todo;
markers(value: any): TBullet //todo;
measures(): any //todo;
measures(value: any): TBullet //todo;
}
interface Bullet extends BulletBase<Bullet>{
}
interface BulletChart extends BulletBase<Bullet>{
bullet: Bullet
ticks(): any //todo;
ticks(value: any): BulletChart //todo;
noData(): any //todo;
noData(value: any): BulletChart //todo;
}
interface Models{
historicalBar(): HistoricalBar;
historicalBarChart(bar_model?: HistoricalBar): HistoricalBarChart;
ohlcBarChart(): HistoricalBarChart;
bullet(): Bullet;
bulletChart(): BulletChart;
boxPlotChart(): BoxPlotChart;
legend(): Legend;
tooltip(): Tooltip;
}
interface ChartFactory<T extends ChartBase> {
generate: ()=> Chart<T>;
callback?: (chart:Chart<T>)=> void;
}
interface nvStatic{
models: Models;
tooltip: Tooltip;
utils: Utils;
addGraph<T extends ChartBase>(factory: ChartFactory<T>);
addGraph<T extends ChartBase>(generate : ()=> Chart<T>, callBack?: (chart:Chart<T>)=> void) ;
}
}
declare var nv : nv.nvStatic;