Standard Approach for a page is to setup div with an ID that will become the SVG Canvas
- The SVG Canvas object (implements ISvgCanvas)
- maitains identity with the page via div:id, fetching attribute data for canvas dimensions
- Creates a Defines child object with stores filters, markers that can be used by any of the child objects
- Creates a d3v4 selection object that other controls will use for appended graphics
- The SVG Canvas object is passed to all child controls so they can
- Figure out the extents of the window
- Access the Defs (or create additional ones at the correct level)
- Append to the main SVG node
Note – the modular (AMD/EC5) approach uses the following imports from a d3 modular typings:
import * as d3_selection from “d3-selection”;
import * as $ from “jquery”;
export type d3v4Selection = d3_selection.Selection<d3_selection.BaseType, any, any, any>;
ISvgCanvas
export interface ISvgCanvas{
id:String;
defines:ICanvasDefines;
svgCanvas:d3v4Selection;
width:number;
height:number;
}
ICanvasDefines – for addding gradients, filters, markers to the <defs> child of the canvas
export interface ICanvasDefines{
AddLinearGradient(gradientId: string): d3v4Selection;
AddGaussianBlurFilter(filterID: string): d3v4Selection;
//stop1:string='70%',stop1color:string='lightgrey', stop2:string= '100%', stop2color:string= 'gray'
AddRadialGradiantWithTwoStops(gradientID:string, stop1?:string,stop1color?:string, stop2?:string, stop2color?:string): d3v4Selection;
AddArrow(markerID:string,markerWidth?:number,markerHeight?:number,refX?:number,refY?:number): d3v4Selection
}
Canvas Object (SvgD3Canvas implements ISvgCanvas)
export class SvgD3Canvas implements ISvgCanvas{
private _container:JQuery;
private _d3SVG:d3v4Selection;
private _width:number;
private _height:number;
private _defines:ICanvasDefines;
constructor(divID:string){
this._container = $(divID);
let itemHeight = this._container.attr("item-height");
if(!itemHeight){
itemHeight = this._container.css("height").replace(/[^-\d\.]/g, '');;
}
if(!itemHeight){
itemHeight = "2000";
}
let itemwidth = this._container.attr("item-width");
if(!itemwidth){
itemwidth = this._container.css("width").replace(/[^-\d\.]/g, '');
}
if(!itemwidth){
itemwidth = "2000";
}
this._height = Math.round(Number(itemHeight));
this._width =Math.round(Number(itemwidth));
this._d3SVG = d3_selection.select(divID).append("svg").attr("width",this._width).attr("height", this._height);
this._defines= new SVGdefsHelper(this._d3SVG);
}
public get width():number{
return this._width;
}
public get height():number{
return this._height;
}
public get svgCanvas():d3v4Selection{
return this._d3SVG;
}
public get defines():ICanvasDefines{
return this._defines;
}
}
Defines Object
export class SVGdefsHelper implements ICanvasDefines {
_svgDefsSection: d3v4Selection;
constructor(svgDefs: d3v4Selection) {
this._svgDefsSection = svgDefs;
}
public AddRadialGradiantWithTwoStops(gradientID:string, stop1:string='70%',stop1color:string='lightgrey', stop2:string= '100%', stop2color:string= 'gray'): d3v4Selection{
let gradient = this._svgDefsSection.append('radialGradient')
.attr("id", gradientID);
gradient.append("stop").attr("offset", stop1).attr("stop-color", stop1color);
gradient.append("stop").attr("offset", stop2).attr("stop-color", stop2color);
return gradient;
}
public AddArrow(markerID:string,markerWidth:number=10,markerHeight:number=10,refX:number=6,refY:number=3): d3v4Selection{
let marker = this._svgDefsSection.append('marker').attr("class","def-marker-arrow").attr("id", markerID)
.attr("markerWidth", markerWidth)
.attr("markerHeight",markerHeight)
.attr("refX",refX)
.attr("refY",refY)
.attr("orient","auto")
.attr("markerUnits", "strokeWidth");
let path = marker.append("path").attr("d","M0,0 L0,6 L9,3 z").attr("class","def-marker-arrow");
return marker;
// <marker id="arrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
// <path d="M0,0 L0,6 L9,3 z" fill="#f00" />
// </marker>
}
public AddRadialGradient(gradiantParams: IGradientStop2): d3v4Selection {
// <radialGradient id="exampleGradient">
// <stop offset="70%" stop-color="lightgrey"/>
// <stop offset="100%" stop-color="gray"/>
//</radialGradient>
var grayCircularRadialGrad = { id: 'grayRadial', stop1: '70%', stop1color: 'lightgrey', stop2: '100%', stop2color: 'gray' };
var gradient = this._svgDefsSection.append('radialGradient')
.attr("id", gradiantParams.id);
gradient.append("stop").attr("offset", gradiantParams.stop1).attr("stop-color", gradiantParams.stop1color);
gradient.append("stop").attr("offset", gradiantParams.stop2).attr("stop-color", gradiantParams.stop2color);
return gradient;
}
public AddLinearGradient(gradientId: string): d3v4Selection {
//<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
// <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
// <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
// </linearGradient>
var mainGradient = this._svgDefsSection.append('linearGradient')
.attr("id", gradientId)
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "0%")
mainGradient.append('stop')
.attr('class', 'stop-left')
.attr('offset', '0%')
.attr('style', 'stop-color:rgb(255,255,0);stop-opacity:1');
mainGradient.append('stop')
.attr('class', 'stop-left')
.attr('offset', '100%')
.attr('style', 'stop-color:rgb(255,0,0);stop-opacity:1');
return mainGradient;
}
public AddGaussianBlurFilter(filterID: string): d3v4Selection {
//<filter id="f3" x="0" y="0" width="200%" height="200%">
// <feOffset result="offOut" in="SourceAlpha" dx="20" dy="20" />
// <feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
// <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
// </filter>
var mainFilter = this._svgDefsSection.append('filter')
.attr("id", filterID)
.attr("x", "0")
.attr("y", "0")
.attr("width", "200%")
.attr("height", "200%");
mainFilter.append("feOffset")
.attr("result", "offOut")
.attr("in", "SourceAlpha")
.attr("dx", "20")
.attr("dy", "20");
mainFilter.append("feGaussianBlur")
.attr("result", "blurOut")
.attr("in", "offOut")
.attr("stdDeviation", "10");
mainFilter.append("feBlend")
.attr("in", "SourceGraphic")
.attr("in2", "blurOut")
.attr("mode", "normal");
return mainFilter;
}
public AddFilterToDefs(filterID: string): d3v4Selection {
//<filter id="f3" x="0" y="0" width="200%" height="200%">
// <feOffset result="offOut" in="SourceAlpha" dx="20" dy="20" />
// <feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
// <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
// </filter>
var mainFilter = this._svgDefsSection.append('filter')
.attr("id", filterID)
.attr("x", "0")
.attr("y", "0")
.attr("width", "200%")
.attr("height", "200%");
mainFilter.append("feOffset")
.attr("result", "offOut")
.attr("in", "SourceAlpha")
.attr("dx", "20")
.attr("dy", "20");
mainFilter.append("feGaussianBlur")
.attr("result", "blurOut")
.attr("in", "offOut")
.attr("stdDeviation", "10");
mainFilter.append("feBlend")
.attr("in", "SourceGraphic")
.attr("in2", "blurOut")
.attr("mode", "normal");
return mainFilter;
}
public AddWhiteToColorGradient(gradientID: string, color: string): d3v4Selection {
//<linearGradient id="gradientOrange" x1="0%" y1="0%" x2="0%" y2="100%" spreadMethod="pad">
// <stop offset="000%" stop-color="#FF9600" stop-opacity="1"/>
// <stop offset="050%" stop-color="#FFFFFF" stop-opacity="1"/>
// <stop offset="100%" stop-color="#000000" stop-opacity="1"/>
//</linearGradient>
//<linearGradient id="gradientGreen" x1="0%" y1="0%" x2="0%" y2="100%" spreadMethod="pad">
// <stop offset="000%" stop-color="#22DD00" stop-opacity="1"/>
// <stop offset="050%" stop-color="#FFFFFF" stop-opacity="1"/>
// <stop offset="100%" stop-color="#000000" stop-opacity="1"/>
//</linearGradient>
var gradient = this._svgDefsSection.append('linearGradient')
.attr("id", gradientID)
.attr("x1", "0%")
.attr("y1", "0%")
.attr("x2", "0%")
.attr("y2", "100%")
gradient.append('stop')
.attr('offset', '0%')
.attr('stop-color', color)
.attr('stop-opacity', 1);
gradient.append('stop')
.attr('offset', '50%')
.attr('stop-color', "#FFFFFF")
.attr('stop-opacity', 1);
gradient.append('stop')
.attr('offset', '100%')
.attr('stop-color', "#000000")
.attr('stop-opacity', 1);
return gradient;
}
}