/** * Typescript definition tests for d3/d3-shape module * * Note: These tests are intended to test the definitions only * in the sense of typing and call signature consistency. They * are not intended as functional tests. */ import * as d3Shape from '../../src/d3-shape'; import { Selection } from '../../src/d3-selection'; // ----------------------------------------------------------------------------------- // Preparatory Steps (General) // ----------------------------------------------------------------------------------- let context: CanvasRenderingContext2D; let num: number; let pathString: string; // ----------------------------------------------------------------------------------- // Test Arc Generator // ----------------------------------------------------------------------------------- interface ArcDatum { iRadius: number; oRadius: number; sAngle: number; eAngle: number; pAngle: number; } let arcDefaultDatum: d3Shape.DefaultArcObject = { innerRadius: 40, outerRadius: 60, startAngle: 0, endAngle: Math.PI / 2, padAngle: 0.03 }; let arcDatum: ArcDatum = { iRadius: 40, oRadius: 60, sAngle: 0, eAngle: Math.PI / 2, pAngle: 0.03 }; let accessorArcDatumNumber: (this: any, d: ArcDatum, ...args: any[]) => number; // DefaultArcObject interface ======================================================== let defaultArcObject: d3Shape.DefaultArcObject; num = defaultArcObject.innerRadius; num = defaultArcObject.outerRadius; num = defaultArcObject.startAngle; num = defaultArcObject.endAngle; num = defaultArcObject.padAngle; // arc(...) create Arc generator ===================================================== let canvasArc: d3Shape.Arc = d3Shape.arc(); let svgArc: d3Shape.Arc = d3Shape.arc(); // configure Arc(...) generator ====================================================== // context(...) ---------------------------------------------------------------------- canvasArc = canvasArc.context(context); // draw to canvas context = canvasArc.context(); svgArc = svgArc.context(null); // use as path string generator for SVG // innerRadius(...) ------------------------------------------------------------------- canvasArc = canvasArc.innerRadius(40); svgArc = svgArc.innerRadius(function (d) { return d.iRadius; // datum type is ArcDatum }); accessorArcDatumNumber = svgArc.innerRadius(); // outerRadius(...) -------------------------------------------------------------------- canvasArc = canvasArc.outerRadius(60); svgArc = svgArc.outerRadius(function (d) { return d.oRadius; // datum type is ArcDatum }); accessorArcDatumNumber = svgArc.outerRadius(); // cornerRadius(...) ------------------------------------------------------------------ canvasArc = canvasArc.cornerRadius(4); svgArc = svgArc.cornerRadius(function (d) { return d.oRadius / 10; // datum type is ArcDatum }); accessorArcDatumNumber = svgArc.cornerRadius(); // startAngle(...) -------------------------------------------------------------------- canvasArc = canvasArc.startAngle(0); svgArc = svgArc.startAngle(function (d) { return d.sAngle; // datum type is ArcDatum }); accessorArcDatumNumber = svgArc.startAngle(); // endAngle(...) ---------------------------------------------------------------------- canvasArc = canvasArc.endAngle(Math.PI / 2); svgArc = svgArc.endAngle(function (d) { return d.eAngle; // datum type is ArcDatum }); accessorArcDatumNumber = svgArc.endAngle(); // padAngle(...) ---------------------------------------------------------------------- canvasArc = canvasArc.padAngle(0); svgArc = svgArc.padAngle(function (d) { return d.pAngle; // datum type is ArcDatum }); accessorArcDatumNumber = svgArc.padAngle(); // use Arc(...) generator ============================================================ // centroid(...) --------------------------------------------------------------------- let centroid: [number, number] = svgArc.centroid(arcDatum); // centroid = arc.centroid(arcDefaultDatum); // fails, wrong datum type // generate arc ---------------------------------------------------------------------- // use with canvas canvasArc(arcDefaultDatum); // use with svg let pArc: Selection; let wrongArc1: Selection; let wrongArc2: Selection; pArc.attr('d', svgArc); // wrongArc1.attr('d', svgArc); // fails, incompatible this contexts // wrongArc2.attr('d', svgArc); // fails, incompatible datum types // pathString = svgArc(arcDatum); // fails, wrong this type for invocation // Use with custom object interface ArcerDatum { innerRadius: number; outerRadius: number; } class Arcer { constructor(innerRadius: number, outerRadius: number) { this.startAngle = 0; this.endAngle = Math.PI / 2; this.padAngle = 0; this.innerRadius = innerRadius; this.outerRadius = outerRadius; this.cornerRadius = 3; this.arc = d3Shape.arc() .innerRadius(function (d) { return Math.min(d.innerRadius, this.innerRadius); }) .outerRadius(function (d) { return Math.min(d.outerRadius, this.outerRadius); }) .cornerRadius(this.cornerRadius) .startAngle(this.startAngle) .endAngle(this.endAngle) .padAngle(this.padAngle); } private startAngle: number; private endAngle: number; private padAngle: number; private innerRadius: number; private outerRadius: number; private cornerRadius: number; private arc: d3Shape.Arc; public getPathString(d?: ArcerDatum) { return d ? this.arc(d) : this.arc({ innerRadius: this.innerRadius, outerRadius: this.outerRadius }); } } let arcer = new Arcer(100, 120); pathString = arcer.getPathString(); pathString = arcer.getPathString({ innerRadius: 10, outerRadius: 20 }); // ----------------------------------------------------------------------------------- // Test Pie Generator // ----------------------------------------------------------------------------------- interface PieDatum { val: number; name: string; } let accessorPieDatumNumber: (this: any, data: Array, ...args: any[]) => number; // PieArcDatum interface ============================================================= let pieArcObject: d3Shape.PieArcDatum; let pieDatum: PieDatum = pieArcObject.data; num = pieArcObject.value; num = pieArcObject.index; num = pieArcObject.startAngle; num = pieArcObject.endAngle; num = pieArcObject.padAngle; // pie(...) create Pie generator ===================================================== let defaultPie: d3Shape.Pie = d3Shape.pie(); let pie: d3Shape.Pie = d3Shape.pie(); // configure Pie(...) generator ====================================================== // value(...) ------------------------------------------------------------------------- let defaultPieValueAccessor: (d: number | { valueOf(): number }, i?: number, data?: Array) => number; defaultPie = defaultPie.value(10); defaultPieValueAccessor = defaultPie.value(); let pieValueAccessor: (d: PieDatum, i?: number, data?: Array) => number; pie = pie.value(function (d, i, data) { console.log(data.length > 0 ? data[0].val : 'no data'); // data type is Array return d.val; // d type is PieDatum }); pieValueAccessor = pie.value(); // sort(...) --------------------------------------------------------------------------- let pieSorter: ((a: PieDatum, b: PieDatum) => number) | null; pie = pie.sort(function (a, b) { return b.val - a.val; // type of a and b is PieDatum }); pieSorter = pie.sort(); pie = pie.sort(null); // sortValues(...) --------------------------------------------------------------------- let pieValuesSorter: ((a: number, b: number) => number) | null; pie = pie.sortValues(function (a, b) { return b - a; // type of a and b is number }); pieValuesSorter = pie.sortValues(); pie = pie.sortValues(null); // startAngle(...) -------------------------------------------------------------------- defaultPie = defaultPie.startAngle(0); pie = pie.startAngle(function (d) { console.log(d.length > 0 ? d[0].val : 'no data'); // data type is Array return 0; }); accessorPieDatumNumber = pie.startAngle(); // endAngle(...) ---------------------------------------------------------------------- defaultPie = defaultPie.endAngle(2 * Math.PI); pie = pie.endAngle(function (d) { console.log(d.length > 0 ? d[0].val : 'no data'); // data type is Array return 2 * Math.PI; }); accessorPieDatumNumber = pie.endAngle(); // padAngle(...) ---------------------------------------------------------------------- defaultPie = defaultPie.padAngle(0.03); pie = pie.padAngle(function (d) { console.log(d.length > 0 ? d[0].val : 'no data'); // data type is Array return 0.03; }); accessorPieDatumNumber = pie.padAngle(); // use Pie(...) generator ============================================================ let defaultPieChart: Array>; defaultPieChart = defaultPie([20, 10, 30, 40]); let pieData: Array = [ { name: 'John', val: 20 }, { name: 'Jill', val: 10 }, { name: 'Rodrigo', val: 30 } ]; let pieChart: Array>; pieChart = pie(pieData); // ----------------------------------------------------------------------------------- // Test Line Generators // ----------------------------------------------------------------------------------- interface LineDatum { x: number; y: number; missing: boolean; } let lineXYAccessorFn: (d: LineDatum, index?: number, data?: Array) => number; let lineDefAccessorFn: (d: LineDatum, index?: number, data?: Array) => boolean; interface RadialLineDatum { angle: number; radius: number; missing: boolean; } let radialLineAngRAccessorFn: (d: RadialLineDatum, index?: number, data?: Array) => number; let radialLineDefAccessorFn: (d: RadialLineDatum, index?: number, data?: Array) => boolean; // line(...) create Line generator ===================================================== let defaultLine: d3Shape.Line<[number, number]> = d3Shape.line(); let line: d3Shape.Line = d3Shape.line(); // configure Line(...) generator ====================================================== // context(...) ---------------------------------------------------------------------- defaultLine = defaultLine.context(context); // draw to canvas context = defaultLine.context(); line = line.context(null); // use as path string generator for SVG // x(...) ---------------------------------------------------------------------------- defaultLine = defaultLine.x(30); line = line.x(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('X-Coordinate of first point: ', data[0].x); // data type is Array return d.x; // d type is LineDatum }); lineXYAccessorFn = line.x(); // y(...) ---------------------------------------------------------------------------- defaultLine = defaultLine.y(10); line = line.y(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Y-Coordinate of first point: ', data[0].y); // data type is Array return d.y; // d type is LineDatum }); lineXYAccessorFn = line.y(); // defined(...) ---------------------------------------------------------------------- defaultLine = defaultLine.defined(true); line = line.defined(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Y-Coordinate of first point: ', data[0].y); // data type is Array return !d.missing; // d type is LineDatum }); lineDefAccessorFn = line.defined(); // curve(...) ------------------------------------------------------------------------ defaultLine = defaultLine.curve(d3Shape.curveLinear); line = line.curve(d3Shape.curveBundle.beta(0.5)); let currentCurveFactory: d3Shape.CurveFactory | d3Shape.CurveFactoryLineOnly = line.curve(); // use Line generator =============================================================== defaultLine([[10, 10], [20, 10], [20, 20]]); let lineData: Array = [ { x: 10, y: 10, missing: false }, { x: 20, y: 10, missing: false }, { x: 20, y: 20, missing: false } ]; let linePathString: string = line(lineData); // radialLine(...) create Line generator ===================================================== let defaultRadialLine: d3Shape.RadialLine<[number, number]> = d3Shape.radialLine(); let radialLine: d3Shape.RadialLine = d3Shape.radialLine(); // configure RadialLine(...) generator ====================================================== // context(...) ---------------------------------------------------------------------- defaultRadialLine = defaultRadialLine.context(context); // draw to canvas context = defaultRadialLine.context(); radialLine = radialLine.context(null); // use as path string generator for SVG // angle(...) ---------------------------------------------------------------------------- defaultRadialLine = defaultRadialLine.angle(Math.PI); radialLine = radialLine.angle(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Angle of first point: ', data[0].angle); // data type is Array return d.angle; // d type is RadialLineDatum }); radialLineAngRAccessorFn = radialLine.angle(); // radius(...) ---------------------------------------------------------------------------- defaultRadialLine = defaultRadialLine.radius(30); radialLine = radialLine.radius(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Angle of first point: ', data[0].angle); // data type is Array return d.radius; // d type is RadialLineDatum }); radialLineAngRAccessorFn = radialLine.radius(); // defined(...) ---------------------------------------------------------------------- defaultRadialLine = defaultRadialLine.defined(true); radialLine = radialLine.defined(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Angle of first point: ', data[0].angle); // data type is Array return !d.missing; // d type is RadialLineDatum }); radialLineDefAccessorFn = radialLine.defined(); // curve(...) ------------------------------------------------------------------------ defaultRadialLine = defaultRadialLine.curve(d3Shape.curveLinear); radialLine = radialLine.curve(d3Shape.curveBundle.beta(0.5)); currentCurveFactory = radialLine.curve(); // use RadialLine generator =============================================================== defaultRadialLine([[10, 10], [20, 10], [20, 20]]); let radialLineData: Array = [ { angle: 0, radius: 10, missing: false }, { angle: Math.PI / 2, radius: 20, missing: false }, { angle: 2 * Math.PI, radius: 10, missing: false } ]; let radialLinePathString: string = radialLine(radialLineData); // ----------------------------------------------------------------------------------- // Test Area Generators // ----------------------------------------------------------------------------------- interface AreaDatum { x0: number; y0: number; x1: number; y1: number; missing: boolean; } let areaXYAccessorFn: (d: AreaDatum, index?: number, data?: Array) => number; let areaDefAccessorFn: (d: AreaDatum, index?: number, data?: Array) => boolean; interface RadialAreaDatum { startAngle: number; endAngle: number; innerRadius: number; outerRadius: number; missing: boolean; } let radialAreaAngRAccessorFn: (d: RadialAreaDatum, index?: number, data?: Array) => number; let radialAreaDefAccessorFn: (d: RadialAreaDatum, index?: number, data?: Array) => boolean; // area(...) create Area generator ===================================================== let defaultArea: d3Shape.Area<[number, number]> = d3Shape.area(); let area: d3Shape.Area = d3Shape.area(); // configure Area(...) generator ====================================================== // context(...) ---------------------------------------------------------------------- defaultArea = defaultArea.context(context); // draw to canvas context = defaultArea.context(); area = area.context(null); // use as path string generator for SVG // x(...) ---------------------------------------------------------------------------- defaultArea = defaultArea.x(30); area = area.x(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('X0-Coordinate of first point: ', data[0].x0); // data type is Array return d.x0; // d type is AreaDatum }); areaXYAccessorFn = area.x(); // x0(...) ---------------------------------------------------------------------------- defaultArea = defaultArea.x0(30); area = area.x0(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('X0-Coordinate of first point: ', data[0].x0); // data type is Array return d.x0; // d type is AreaDatum }); areaXYAccessorFn = area.x0(); // x1(...) ---------------------------------------------------------------------------- defaultArea = defaultArea.x1(30); area = area.x1(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('X1-Coordinate of first point: ', data[0].x1); // data type is Array return d.x1; // d type is AreaDatum }); areaXYAccessorFn = area.x1(); // y(...) ---------------------------------------------------------------------------- defaultArea = defaultArea.y(10); area = area.y(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Y0-Coordinate of first point: ', data[0].y0); // data type is Array return d.y0; // d type is AreaDatum }); areaXYAccessorFn = area.y(); // y0(...) ---------------------------------------------------------------------------- defaultArea = defaultArea.y0(10); area = area.y0(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Y0-Coordinate of first point: ', data[0].y0); // data type is Array return d.y0; // d type is AreaDatum }); areaXYAccessorFn = area.y0(); // y1(...) ---------------------------------------------------------------------------- defaultArea = defaultArea.y1(10); area = area.y1(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Y1-Coordinate of first point: ', data[0].y1); // data type is Array return d.y1; // d type is AreaDatum }); areaXYAccessorFn = area.y1(); // defined(...) ---------------------------------------------------------------------- defaultArea = defaultArea.defined(true); area = area.defined(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Y0-Coordinate of first point: ', data[0].y0); // data type is Array return !d.missing; // d type is AreaDatum }); areaDefAccessorFn = area.defined(); // curve(...) ------------------------------------------------------------------------ defaultArea = defaultArea.curve(d3Shape.curveLinear); area = area.curve(d3Shape.curveCardinal.tension(0.5)); // area = area.curve(d3Shape.curveBundle.beta(0.5)); // fails, as curveBundle-based line generator does not support area-related methods currentCurveFactory = area.curve(); // use Area generator =============================================================== defaultArea([[10, 10], [20, 10], [20, 20]]); let areaData: Array = [ { x0: 10, y0: 10, x1: 10, y1: 30, missing: false }, { x0: 20, y0: 20, x1: 20, y1: 40, missing: false }, { x0: 30, y0: 30, x1: 30, y1: 30, missing: false } ]; let areaPathString: string = area(areaData); // Get Line Generators from Area generator ======================================================== let areaLineGenerator: d3Shape.Line; areaLineGenerator = area.lineX0(); areaLineGenerator = area.lineY0(); areaLineGenerator = area.lineX1(); areaLineGenerator = area.lineY1(); // radialArea(...) create RadialArea generator ===================================================== let defaultRadialArea: d3Shape.RadialArea<[number, number]> = d3Shape.radialArea(); let radialArea: d3Shape.RadialArea = d3Shape.radialArea(); // configure RadialArea(...) generator ====================================================== // context(...) ---------------------------------------------------------------------- defaultRadialArea = defaultRadialArea.context(context); // draw to canvas context = defaultRadialArea.context(); radialArea = radialArea.context(null); // use as path string generator for SVG // angle(...) ---------------------------------------------------------------------------- defaultRadialArea = defaultRadialArea.angle(Math.PI); radialArea = radialArea.angle(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Start angle of first point: ', data[0].startAngle); // data type is Array return d.startAngle; // d type is RadialAreaDatum }); radialAreaAngRAccessorFn = radialArea.angle(); // startAngle(...) ---------------------------------------------------------------------------- defaultRadialArea = defaultRadialArea.startAngle(Math.PI); radialArea = radialArea.startAngle(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Start angle of first point: ', data[0].startAngle); // data type is Array return d.startAngle; // d type is RadialAreaDatum }); radialAreaAngRAccessorFn = radialArea.startAngle(); // endAngle(...) ---------------------------------------------------------------------------- defaultRadialArea = defaultRadialArea.endAngle(Math.PI); radialArea = radialArea.endAngle(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('End angle of first point: ', data[0].endAngle); // data type is Array return d.endAngle; // d type is RadialAreaDatum }); radialAreaAngRAccessorFn = radialArea.endAngle(); // radius(...) ---------------------------------------------------------------------------- defaultRadialArea = defaultRadialArea.radius(10); radialArea = radialArea.radius(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Inner radius of first point: ', data[0].innerRadius); // data type is Array return d.innerRadius; // d type is RadialAreaDatum }); radialAreaAngRAccessorFn = radialArea.radius(); // innerRadius(...) ---------------------------------------------------------------------------- defaultRadialArea = defaultRadialArea.innerRadius(10); radialArea = radialArea.innerRadius(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Inner radius of first point: ', data[0].innerRadius); // data type is Array return d.innerRadius; // d type is RadialAreaDatum }); radialAreaAngRAccessorFn = radialArea.innerRadius(); // outerRadius(...) ---------------------------------------------------------------------------- defaultRadialArea = defaultRadialArea.outerRadius(20); radialArea = radialArea.outerRadius(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Outer radius of first point: ', data[0].outerRadius); // data type is Array return d.outerRadius; // d type is RadialAreaDatum }); radialAreaAngRAccessorFn = radialArea.outerRadius(); // defined(...) ---------------------------------------------------------------------- defaultRadialArea = defaultRadialArea.defined(true); radialArea = radialArea.defined(function (d, t, data) { console.log('Number of Points: ', data.length); console.log('Inner radius of first point: ', data[0].innerRadius); // data type is Array return !d.missing; // d type is RadialAreaDatum }); radialAreaDefAccessorFn = radialArea.defined(); // curve(...) ------------------------------------------------------------------------ defaultRadialArea = defaultRadialArea.curve(d3Shape.curveLinear); radialArea = radialArea.curve(d3Shape.curveCardinal.tension(0.5)); // radialArea = radialArea.curve(d3Shape.curveBundle.beta(0.5)); // fails, as curveBundle-based line generator does not support area-related methods currentCurveFactory = radialArea.curve(); // use RadialArea generator =============================================================== defaultRadialArea([[10, 10], [20, 10], [20, 20]]); let radialAreaData: Array = [ { startAngle: 0, innerRadius: 10, endAngle: 0, outerRadius: 30, missing: false }, { startAngle: Math.PI / 2, innerRadius: 20, endAngle: Math.PI / 2, outerRadius: 40, missing: false }, { startAngle: Math.PI, innerRadius: 30, endAngle: Math.PI, outerRadius: 30, missing: false } ]; let radialAreaPathString: string = radialArea(radialAreaData); // Get RadialLine Generators from RadialArea generator ======================================================== let areaRadialLineGenerator: d3Shape.RadialLine; areaRadialLineGenerator = radialArea.lineStartAngle(); areaRadialLineGenerator = radialArea.lineInnerRadius(); areaRadialLineGenerator = radialArea.lineEndAngle(); areaRadialLineGenerator = radialArea.lineOuterRadius(); // ----------------------------------------------------------------------------------- // Test Curve Factories // ----------------------------------------------------------------------------------- // Test General interfaces ----------------------------------------------------------- let lineOnlyGenerator: d3Shape.CurveGeneratorLineOnly; let lineOnlyFactory: d3Shape.CurveFactoryLineOnly; lineOnlyGenerator = lineOnlyFactory(null); lineOnlyGenerator = lineOnlyFactory(context); lineOnlyGenerator.lineStart(); lineOnlyGenerator.lineEnd(); lineOnlyGenerator.point(10, 20); let curveGenerator: d3Shape.CurveGenerator; let curveFactory: d3Shape.CurveFactory; curveGenerator = curveFactory(null); curveGenerator = curveFactory(context); curveGenerator.lineStart(); curveGenerator.lineEnd(); curveGenerator.point(10, 20); curveGenerator.areaStart(); curveGenerator.areaEnd(); // Test factories -------------------------------------------------------------------- curveFactory = d3Shape.curveBasis; curveFactory = d3Shape.curveBasisOpen; curveFactory = d3Shape.curveBasisClosed; let curveBundleFactory: d3Shape.CurveBundleFactory; curveBundleFactory = d3Shape.curveBundle; curveBundleFactory = d3Shape.curveBundle.beta(0.5); lineOnlyGenerator = d3Shape.curveBundle.beta(0.5)(context); // curveGenerator = d3Shape.curveBundle.beta(0.5)(context); // fails, no area related methods let curveCardinalFactory: d3Shape.CurveCardinalFactory; curveCardinalFactory = d3Shape.curveCardinal; curveCardinalFactory = d3Shape.curveCardinal.tension(0.5); curveGenerator = d3Shape.curveCardinal.tension(0.5)(context); curveCardinalFactory = d3Shape.curveCardinalOpen; curveCardinalFactory = d3Shape.curveCardinalOpen.tension(0.5); curveGenerator = d3Shape.curveCardinalOpen.tension(0.5)(context); curveCardinalFactory = d3Shape.curveCardinalClosed; curveCardinalFactory = d3Shape.curveCardinalClosed.tension(0.5); curveGenerator = d3Shape.curveCardinalClosed.tension(0.5)(context); let curveCatmullRomFactory: d3Shape.CurveCatmullRomFactory; curveCatmullRomFactory = d3Shape.curveCatmullRom; curveCatmullRomFactory = d3Shape.curveCatmullRom.alpha(0.5); curveGenerator = d3Shape.curveCatmullRom.alpha(0.5)(context); curveCatmullRomFactory = d3Shape.curveCatmullRomOpen; curveCatmullRomFactory = d3Shape.curveCatmullRomOpen.alpha(0.5); curveGenerator = d3Shape.curveCatmullRomOpen.alpha(0.5)(context); curveCatmullRomFactory = d3Shape.curveCatmullRomClosed; curveCatmullRomFactory = d3Shape.curveCatmullRomClosed.alpha(0.5); curveGenerator = d3Shape.curveCatmullRomClosed.alpha(0.5)(context); curveFactory = d3Shape.curveLinear; curveFactory = d3Shape.curveLinearClosed; curveFactory = d3Shape.curveMonotoneX; curveFactory = d3Shape.curveMonotoneY; curveFactory = d3Shape.curveNatural; curveFactory = d3Shape.curveStep; curveFactory = d3Shape.curveStepAfter; curveFactory = d3Shape.curveStepBefore; // ----------------------------------------------------------------------------------- // Test Symbols // ----------------------------------------------------------------------------------- interface SymbolDatum { size: number; type: 'circle' | 'square'; } // Test Symbol Type ================================================================== let customSymbol: d3Shape.SymbolType; customSymbol = { draw: function (context: CanvasPathMethods, size: number): void { // draw custom symbol using canvas path methods } }; // Symbol() create Symbol Generator =================================================== let canvasSymbol: d3Shape.Symbol; let svgSymbol: d3Shape.Symbol; canvasSymbol = d3Shape.symbol(); svgSymbol = d3Shape.symbol(); // Configure Symbol Generator ========================================================= // context() -------------------------------------------------------------------------- canvasSymbol = canvasSymbol.context(context); // draw to canvas context = canvasSymbol.context(); svgSymbol = svgSymbol.context(null); // use as path string generator for SVG // size() ---------------------------------------------------------------------------- canvasSymbol = canvasSymbol.size(30); svgSymbol = svgSymbol.size(function (d) { return d.size; // datum type is SymbolDatum }); let sizeAccessorFn: (d: SymbolDatum) => number; sizeAccessorFn = svgSymbol.size(); // type() ---------------------------------------------------------------------------- canvasSymbol = canvasSymbol.type(d3Shape.symbolDiamond); svgSymbol = svgSymbol.type(function (d) { let t: d3Shape.SymbolType; switch (d.type) { // datum type is SymbolDatum case 'circle': t = d3Shape.symbolCircle; break; case 'square': t = d3Shape.symbolSquare; break; default: t = d3Shape.symbolCircle; break; } return t; }); let typeAccessorFn: (d: SymbolDatum) => d3Shape.SymbolType; typeAccessorFn = svgSymbol.type(); // Use Symbol Generator =============================================================== // use with canvas canvasSymbol(); let symbolDatum: SymbolDatum = { size: 30, type: 'circle' }; let pSymbol: Selection; let wrongSymbol1: Selection; let wrongSymbol2: Selection; pSymbol.attr('d', svgSymbol); // wrongSymbol1.attr('d', svgSymbol); // fails, incompatible this contexts // wrongSymbol2.attr('d', svgSymbol); // fails, incompatible datum types // pathString = svgSymbol(symbolDatum); // fails, wrong this type for invocation // Use with custom object class Symbolizer { constructor(size: number, type: 'circle' | 'square') { this.size = size; switch (type) { case 'circle': this.type = d3Shape.symbolCircle; break; case 'square': this.type = d3Shape.symbolSquare; break; default: this.type = d3Shape.symbolCircle; break; } this.symbol = d3Shape.symbol() .size(function (this: Symbolizer, d?: SymbolDatum) { return d ? d.size : this.size; }) .type(function (this: Symbolizer, d?: SymbolDatum) { let type = this.type; if (d && d.type) { switch (d.type) { case 'circle': type = d3Shape.symbolCircle; break; case 'square': type = d3Shape.symbolSquare; break; } } return type; }); } private size: number; private type: d3Shape.SymbolType; private symbol: d3Shape.Symbol; public getPathString(d?: SymbolDatum) { return d ? this.symbol(d) : this.symbol(); } } let sym = new Symbolizer(100, 'square'); pathString = sym.getPathString(); pathString = sym.getPathString({ size: 10, type: 'circle' }); // Test pre-fab symbols =============================================================== let symbolArray: Array = d3Shape.symbols; customSymbol = d3Shape.symbolCircle; customSymbol = d3Shape.symbolCross; customSymbol = d3Shape.symbolDiamond; customSymbol = d3Shape.symbolSquare; customSymbol = d3Shape.symbolStar; customSymbol = d3Shape.symbolTriangle; customSymbol = d3Shape.symbolWye; // ----------------------------------------------------------------------------------- // Test Stacks // ----------------------------------------------------------------------------------- interface StackDatum { values: { [name: string]: number; }; } let seriesDatum: StackDatum; interface StackKey { name: string; label: string; } let key: StackKey; let keys: Array = [ { name: 'bananas', label: 'Bananas' }, { name: 'apples', label: 'Apples' }, { name: 'oranges', label: 'Oranges' } ]; let stackData: Array = [ { values: { bananas: 10, apples: 20, oranges: 10 } }, { values: { bananas: 10, apples: 25, oranges: 0 } }, { values: { bananas: 20, apples: 20, oranges: 30 } }, { values: { bananas: 12, apples: 10, oranges: 50 } } ]; // Test SeriesPoint and Series interfaces ============================================ let seriesPoint: d3Shape.SeriesPoint; num = seriesPoint[0]; num = seriesPoint[1]; num = seriesPoint.index; seriesDatum = seriesPoint.data; let series: d3Shape.Series; seriesPoint = series[0]; key = series.key; // Create stack generator ========================================================== let defaultStack: d3Shape.Stack; defaultStack = d3Shape.stack(); let overlyComplicatedStack: d3Shape.Stack; overlyComplicatedStack = d3Shape.stack(); // Configure stack generator ======================================================= // keys(...) ---------------------------------------------------------------------- defaultStack = defaultStack.keys(['bananas', 'apples', 'oranges']); overlyComplicatedStack = overlyComplicatedStack.keys(function (data: Array, keys: Array) { return keys; }); let keysAccessor: (this: any, data: Array, keys: Array) => Array; keysAccessor = overlyComplicatedStack.keys(); // values(...) ---------------------------------------------------------------------- defaultStack = defaultStack.value(30); overlyComplicatedStack = overlyComplicatedStack.value(function (d, key, j, data) { return d.values[key.name]; }); let valueAccessorFn: (this: any, d: StackDatum, key: StackKey, j?: number, data?: Array) => number; valueAccessorFn = overlyComplicatedStack.value(); // order(...) ---------------------------------------------------------------------- defaultStack = defaultStack.order([2, 3, 1]); defaultStack = defaultStack.order(null); overlyComplicatedStack = overlyComplicatedStack.order(d3Shape.stackOrderAscending); let orderStackDatumSeries: (series: d3Shape.Series) => Array; orderStackDatumSeries = overlyComplicatedStack.order(); // TODO: other signatures // offset(...) ---------------------------------------------------------------------- defaultStack = defaultStack.offset(null); overlyComplicatedStack = overlyComplicatedStack.offset(d3Shape.stackOffsetWiggle); let offsetStackDatumSeries: (series: d3Shape.Series, order: Array) => void; offsetStackDatumSeries = overlyComplicatedStack.offset(); // Use stack generator ============================================================ let defaultSeriesArray: Array>; defaultSeriesArray = defaultStack([ {bananas: 10, apples: 20, oranges: 10}, {bananas: 30, apples: 10, oranges: 30}, {bananas: 80, apples: 20, oranges: 40} ]); let seriesArray: Array>; seriesArray = overlyComplicatedStack(stackData, keys); // Test stack orders =============================================================== let order: Array; let seriesAnyAny: d3Shape.Series; order = d3Shape.stackOrderAscending(seriesAnyAny); order = d3Shape.stackOrderDescending(seriesAnyAny); order = d3Shape.stackOrderInsideOut(seriesAnyAny); order = d3Shape.stackOrderNone(seriesAnyAny); order = d3Shape.stackOrderReverse(seriesAnyAny); // Test stack offsets =============================================================== d3Shape.stackOffsetExpand(seriesAnyAny, order); d3Shape.stackOffsetNone(seriesAnyAny, order); d3Shape.stackOffsetSilhouette(seriesAnyAny, order); d3Shape.stackOffsetWiggle(seriesAnyAny, order);