/** * Created by vitaliy on 1/19/18. */ export default (d3, el, title, min, max) => { // Set Up const container = d3.select(el); const c = container.node().getBoundingClientRect(); const width = container.node() ? container.node().getBoundingClientRect().width : false; if (!width) { console.error('something went wrong. No width is defined'); return () => {}; } let lastVal; let lastMax = 0; const pi = Math.PI; let current; let foreground; let newColor; let hold; let curColor = 'limegreen'; let arc; const rangeScale = max - min; const rangeSector = rangeScale / 4; const colors = [ { max: min + rangeSector, color: '#c12f1a' }, // "red": { max: min + rangeSector * 2, color: '#ffb901' }, // "yellow" { max: min + rangeSector * 3, color: '#34b440' }, // "lightGreen" { max, color: '#269b2b' }, // "darkGreen" ]; const init = () => { container.selectAll('*').remove(); const width = container.node() ? container.node().getBoundingClientRect().width : false; const height = 400; let iR = width / 2; if (iR > 180) { iR = 180; } if (iR > height / 2) { iR = height / 2; } const oR = iR - 50; // var max:number = 180; // var min:number = 0; arc = d3 .arc() .innerRadius(iR) .outerRadius(oR) .startAngle(-110 * (pi / 180)); // Arc Defaults // Place svg element const svg = container .append('svg') .attr('width', width) .attr('height', height) .append('g') .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); const background = svg .append('path') .datum({ endAngle: 110 * (pi / 180) }) .style('fill', '#ddd') .attr('d', arc); // Append background arc to svg foreground = svg .append('path') .datum({ endAngle: -110 * (pi / 180) }) .style('fill', curColor) .attr('d', arc); // Append foreground arc to svg // var maxa = svg.append("text").attr("transform", "translate(" + (iR + ((oR - iR) / 2)) + ",15)") // Display Max value // .attr("text-anchor", "middle").style("font-family", "Helvetica").text(max) // Set between inner and outer Radius // Display Min value // var mina = svg.append("text").attr("transform", "translate(" + -(iR + ((oR - iR) / 2)) + ",15)") // Set between inner and outer Radius // .attr("text-anchor", "middle").style("font-family", "Helvetica").text(min) // Display Min value const titleArray = title.match(/.{1,15}(\s|$)/g); // change 15 for configure string length titleArray.forEach((row, index) => { svg.append('text') .attr('transform', 'translate(0,' + -(iR / 4 - 60 - 20 * index) + ')') // Set between inner and outer Radius .attr('text-anchor', 'middle') .style('fill', '#b9b3b3') .style('font-size', '15') .style('font-family', 'Helvetica') .style('font-weight', 'bold') .text(row); }); // Display Current value current = svg .append('text') .attr('class', 'mos-score-text') .attr('transform', 'translate(0,' + -(iR / 4 - 30) + ')') // Push up from center 1/4 of innerRadius .attr('text-anchor', 'middle') .style('font-size', '50') .style('font-family', 'Helvetica') .text(0); // Update every x seconds }; init(); const arcTween = (transition, newAngle) => { transition.attrTween('d', (d) => { const interpolate = d3.interpolate(d.endAngle, newAngle); return (t) => { d.endAngle = interpolate(t); return arc(d); }; }); }; // Update animation const updateVal = (val, max) => { let valueFull = 0; lastVal = val; lastMax = max; if (val === max) { valueFull = 180 / 4 - 5; } const num = val * (180 / max) + valueFull; const numPi = Math.floor(num - 110) * (pi / 180); // Get value newColor = colors.find((colorOption) => { return colorOption.max >= val; }).color; current.transition().text(val.toPrecision(3)); // Text transition foreground .transition() .duration(750) .styleTween('fill', () => { return d3.interpolate(newColor, curColor); }) .call(arcTween, numPi); hold = curColor; curColor = newColor; newColor = hold; }; const onresize = (event) => { if (lastMax) { init(); updateVal(lastVal, lastMax); } }; window.removeEventListener('resize', onresize, false); window.addEventListener('resize', onresize, false); return updateVal; };