UNPKG

dasf-web

Version:

Web frontend components for the data analytics software framework (DASF)

255 lines (212 loc) 6.62 kB
import * as d3 from 'd3'; export default class BarChartNegativeValues { private svg; private targetElementId: string; private data: Map<string, number> = new Map(); private paramColors: Map<string, string> = new Map(); private parent; constructor(targetElementId: string, parent) { this.targetElementId = targetElementId; this.parent = parent; } public setChart(data: Map<string, number>, paramColors: Map<string, string>) { this.paramColors = paramColors; this.data = data; this.build(); } //render chart private build() { let self = this; this.svg = d3 .select('#' + this.targetElementId) .selectAll("*") .remove(); let keys = Array.from(this.data.keys()); let values = Array.from(this.data.values()); // init the container let d3Container: HTMLElement | null = document.getElementById(this.targetElementId); if (!d3Container) { throw new Error("no container with id '" + this.targetElementId + "' found."); } const margin = 30; const width = 500 - 2 * margin; const height = 500 - 2 * margin; // init the svg canvas this.svg = d3 .select('#' + this.targetElementId) .append('svg') .attr( 'viewBox', -margin + ' ' + -margin + ' ' + 550 + ' ' + 600 ) .classed('svg-content-responsive', true); const chart = this.svg.append('g') .attr('transform', `translate(${margin}, ${margin})`) //xScale const x = d3.scaleBand() .range([0, width]) .domain(keys) .padding(0.1) chart.append('g') .attr('transform', `translate(0, ${height})`) .call(d3.axisBottom(x)); //yScale var y0 = Math.abs(d3.min(values)); var y1 = Math.abs(d3.max(values)); var y2; if(y0 > y1){ y2 = y0; } else { y2 = y1; } var y = d3.scaleLinear() .domain([-y2, y2]) .range([height,0]) .nice(); var yAxis = d3.axisLeft() .scale(y) chart.append("g") .attr("class", "x axis") .call(yAxis); //arrow chart.append("svg:defs").append("svg:marker") .attr("id", "triangle") .attr("refX", 6) .attr("refY", 6) .attr("markerWidth", 30) .attr("markerHeight", 30) .attr("markerUnits","userSpaceOnUse") .attr("orient", "auto") .append("path") .attr("d", "M 0 0 12 6 0 12 3 6") .style("fill", "white"); //Y-label chart.append('text') .attr('x', -(height / 4)) .attr('y', -(margin * 1.3)) .attr('transform', 'rotate(-90)') .attr('text-anchor', 'start') .attr("font-family", "sans-serif") .attr("font-size", "13px") .attr("fill", "white") .text('ROI') chart.append("line") .attr("x1",-(margin * 1.5)) .attr("y1",(height / 2) - (margin/3)) .attr("x2",-(margin * 1.5)) .attr("y2",(height / 3) - (margin/3)) .attr("fill","white") .attr("stroke", "white") .attr("stroke-width",2) .attr("marker-end","url(#triangle)"); chart.append('text') .attr('x', -(height - (height / 4))) .attr('y', -(margin * 1.3)) .attr('transform', 'rotate(-90)') .attr('text-anchor', 'end') .attr("font-family", "sans-serif") .attr("font-size", "13px") .attr("fill", "white") .text('non-ROI') chart.append("line") .attr("x1",-(margin * 1.5)) .attr("y1",(height / 2) + (margin/3)) .attr("x2",-(margin * 1.5)) .attr("y2",(height / 1.5) + (margin/3)) .attr("fill","white") .attr("stroke", "white") .attr("stroke-width",2) .attr("marker-end","url(#triangle)"); //grid lines chart.append('g') .attr('class', 'grid') .call(d3.axisLeft() .scale(y) .tickSize(-width, 0, 0) .tickFormat('')) //bars chart.selectAll() .data(values) .enter() .append('rect') .attr("class", function(d) { return d < 0 ? "bar negative" : "bar positive"; }) .attr("x", function(d) { return x(keys[values.indexOf(d)])}) .attr("y", function(d) { return y(Math.max(0, d)); }) .attr("height", function(d) { return Math.abs(y(d) - y(0)); }) .attr('width', x.bandwidth()) .attr('name', function(d) { return keys[values.indexOf(d)] }) .attr('stroke', 'white') .attr('stroke-width', '0') .style('fill', function(d) { var param = keys[values.indexOf(d)]; return self.getColor(param); }); // bar labels chart.selectAll() .data(values) .enter() .append("text") .text(function(d) { var num = d; var n = num.toFixed(2); return n; }) .attr("x", function(d) { var a = x(keys[values.indexOf(d)]); return a + 10; }) .attr("y", function(d) { var b = y(0); if( d < 0){ return b - 5; } else { return b + 15; } }) .attr("id", function(d) { return keys[values.indexOf(d)] }) .attr("font-family", "sans-serif") .attr("font-size", "13px") .attr("fill", "white") .attr('opacity', 0); //interactivity chart.selectAll('rect') .on('mouseenter', handleMouseEnter) .on('mouseleave', handleMouseLeave) .on('click', handleMouseClick) // Create Event Handlers for mouseEnter function handleMouseEnter(this) { // Add interactivity //select rect, change opacity d3.select(this) .attr('opacity', 0.4) .attr('stroke-width', '2') //select text var name = d3.select(this).attr("name"); d3.select("#" + name) .attr('opacity', 1); } // Create Event Handlers for mouseLeave function handleMouseLeave(this) { // Add interactivity //select rect, change opacity d3.select(this) .attr('opacity', 1) .attr('stroke-width', '0') //select text var name = d3.select(this).attr("name"); d3.select("#" + name) .attr('opacity', 0); } function handleMouseClick(this) { var name = d3.select(this).attr("name"); self.parent.showTable(name); } } private getColor(param: string) : string{ var s = this.paramColors.get(param); if(s != undefined){ return s; } else { return 'white'; } } }