chartogram
Advanced tools
Comparing version 0.1.5 to 0.1.6
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).chartogram=e()}(this,function(){"use strict";function t(t){return function(t){if(Array.isArray(t)){for(var e=0,i=new Array(t.length);e<t.length;e++)i[e]=t[e];return i}}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function e(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function i(t,e,i,n,a){for(var o=0;o<n;){var r=document.createElement("div"),s=e+o*(i-e)/(n-1);a&&(s=a(s)),r.appendChild(document.createTextNode(s)),t.appendChild(r),o++}}function n(t,e,i){function n(t){i(t.changedTouches[0].clientX,t.changedTouches[0].clientY)}function a(t){i(t.clientX,t.clientY)}function o(){window.removeEventListener("pointermove",a),window.removeEventListener("touchmove",n),window.removeEventListener("pointerup",o),window.removeEventListener("pointercancel",o),window.removeEventListener("touchend",o),window.removeEventListener("touchcancel",o)}function r(t){if(t.touches.length>1)return o();e(t.changedTouches[0].clientX,t.changedTouches[0].clientY),window.addEventListener("touchmove",n),window.addEventListener("touchend",o),window.addEventListener("touchcancel",o)}function s(t){e(t.clientX,t.clientY),window.addEventListener("pointermove",a),window.addEventListener("pointerup",o),window.addEventListener("pointercancel",o)}return t.addEventListener("touchstart",r),t.addEventListener("pointerdown",s),function(){o(),t.removeEventListener(s),t.removeEventListener(r)}}function a(t){return function(t){if(Array.isArray(t)){for(var e=0,i=new Array(t.length);e<t.length;e++)i[e]=t[e];return i}}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function o(t){for(var e=1;e<arguments.length;e++){var i=null!=arguments[e]?arguments[e]:{},n=Object.keys(i);"function"==typeof Object.getOwnPropertySymbols&&(n=n.concat(Object.getOwnPropertySymbols(i).filter(function(t){return Object.getOwnPropertyDescriptor(i,t).enumerable}))),n.forEach(function(e){l(t,e,i[e])})}return t}function r(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var i=[],n=!0,a=!1,o=void 0;try{for(var r,s=t[Symbol.iterator]();!(n=(r=s.next()).done)&&(i.push(r.value),!e||i.length!==e);n=!0);}catch(t){a=!0,o=t}finally{try{n||null==s.return||s.return()}finally{if(a)throw o}}return i}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function s(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function l(t,e,i){return e in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}var c=function(){function c(s,d){var h,u,v,m,p,f=this,g=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Title",y=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,c),l(this,"onResize",function(t){f.setState({aspectRatio:f.getCanvasAspectRatio(),timelineAspectRatio:f.getTimelineCanvasAspectRatio()})}),l(this,"onResizeThrottled",(h=this.onResize,u=33,m=0,p=function(){v=void 0,m=Date.now(),h()},function(){var t=Date.now(),e=u-(t-m);e<=0?(v&&(clearTimeout(v),v=void 0),m=t,h()):v||(v=setTimeout(p,e))})),l(this,"fixSvgCoordinate",function(t){var e=f.props.precisionFactor;return Math.round(t*e)/e}),l(this,"mapX",function(t){var e=f.props.canvasWidth,i=f.state,n=i.minX;return(t-n)/(i.maxX-n)*e}),l(this,"mapY",function(t){var e=f.props.canvasWidth,i=f.state,n=i.minY;return(t-n)/(i.maxY-n)*e/i.aspectRatio}),l(this,"mapXForTimeline",function(t){var e=f.props.canvasWidth,i=f.data,n=i.minX;return(t-n)/(i.maxX-n)*e}),l(this,"mapYForTimeline",function(t){var e=f.props.canvasWidth,i=f.state,n=i.minYGlobal;return(t-n)/(i.maxYGlobal-n)*e/i.timelineAspectRatio}),l(this,"createGridLine",function(t){var e=f.state,i=e.minX,n=e.maxX,a=(e.minY,e.maxY),o=e.yScale,r=document.createElement("line");return r.classList.add("chartogram__grid-line"),r.setAttribute("x1",f.fixSvgCoordinate(f.mapX(i))),r.setAttribute("x2",f.fixSvgCoordinate(f.mapX(n))),r.setAttribute("y1",f.fixSvgCoordinate(f.mapY(a-o*t))),r.setAttribute("y2",f.fixSvgCoordinate(f.mapY(a-o*t))),r}),l(this,"drawGauges",function(t,n,a,o,r){var s=f.props,l=s.gaugeTickMarksCount,c=s.months;e(f.xAxis),e(f.yAxis),i(f.xAxis,t,n,l,function(t){var e=new Date(t);return"".concat(c[e.getMonth()]," ").concat(e.getDate())}),i(f.yAxis,a,o,l),f.yAxis.style.height="".concat(100/r,"%")}),l(this,"renderTimeline",function(){var i=f.props.canvasWidth,n=f.data,a=n.x,o=n.y,s=f.state,l=s.timelineAspectRatio,c=s.maxYGlobal,d=s.yScale;e(f.timelineCanvas),f.timelineCanvas.setAttribute("viewBox","0 0 ".concat(i," ").concat(f.fixSvgCoordinate(i/l)));var h=function(){if(v){if(m>=u.length)return"break";p=u[m++]}else{if((m=u.next()).done)return"break";p=m.value}var e=p,i=e.id,n=e.color,o=e.points;if(f.state.y.find(function(t){return t.id===i}).isShown){var s=r(function e(i,n,a){var o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:Math.max.apply(Math,t(n)),r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:.025,s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0,l=arguments.length>6&&void 0!==arguments[6]?arguments[6]:new Array(i.length),c=arguments.length>7&&void 0!==arguments[7]?arguments[7]:new Array(i.length),d=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0;if(s+2>i.length-1){for(;s<n.length;)l[d]=i[s],c[d]=n[s],d++,s++;return l=l.slice(0,d),c=c.slice(0,d),l.length<=a?[l,c]:(i.length/l.length<1.1&&(r=Math.min(r+.025,1)),e(l,c,a,o,r))}var h=(n[s+2]+n[s])/2;return Math.abs(h-n[s+1])/o<r?(l[d]=i[s],l[d+1]=i[s+2],c[d]=n[s],c[d+1]=n[s+2],e(i,n,a,o,r,s+2,l,c,d+1)):(l[d]=i[s],l[d+1]=i[s+1],l[d+2]=i[s+2],c[d]=n[s],c[d+1]=n[s+1],c[d+2]=n[s+2],e(i,n,a,o,r,s+2,l,c,d+2))}(a.points,o,80),2),l=s[0],h=s[1],g=document.createElement("polyline");g.setAttribute("stroke",n),g.setAttribute("points",f.createPolylinePoints(l.map(f.mapXForTimeline),h.map(function(t){return f.mapYForTimeline(c-t*d)})).join(" ")),g.classList.add("chartogram__graph"),f.timelineCanvas.appendChild(g)}},u=o,v=Array.isArray(u),m=0;for(u=v?u:u[Symbol.iterator]();;){var p;if("break"===h())break}f.timelineCanvas.innerHTML+=""}),l(this,"createGraphToggler",function(t){var e=t.id,i=t.name,n=t.color,a=document.createElement("button");a.setAttribute("type","button"),a.classList.add("chartogram__chart-toggler"),a.classList.add("chartogram__chart-toggler--on"),a.classList.add("chartogram__reset-button");var r="http://www.w3.org/2000/svg",s=document.createElementNS(r,"svg");s.setAttribute("viewBox","0 0 19 19"),s.setAttribute("class","chartogram__chart-toggler-check");var l=document.createElementNS(r,"circle");l.setAttribute("cx","9.5"),l.setAttribute("cy","9.5"),l.setAttribute("r","9.5"),l.setAttribute("fill",n),s.appendChild(l);var c=document.createElementNS(r,"circle");c.setAttribute("cx","9.5"),c.setAttribute("cy","9.5"),c.setAttribute("r","8"),c.setAttribute("class","chartogram__chart-toggler-check-circle"),s.appendChild(c);var d=document.createElementNS(r,"path");return d.setAttribute("d","M13.64 4.94l-6.2 6.34-1.69-1.9c-.73-.63-1.89.1-1.36 1.06l2 3.38c.3.43 1.04.85 1.78 0 .32-.42 6.31-7.93 6.31-7.93.74-.84-.2-1.58-.84-.95z"),d.setAttribute("fill","white"),d.setAttribute("class","chartogram__chart-toggler-check-mark"),s.appendChild(d),a.appendChild(s),a.appendChild(document.createTextNode(i)),a.addEventListener("click",function(){var t=f.state.y.find(function(t){return t.id===e});if(t.isShown&&1===f.state.y.filter(function(t){return t.isShown}).length)return;t.isShown=!t.isShown,f.setState(o({},f.state,f.calculateMinMaxY(f.state.y))),a.classList.toggle("chartogram__chart-toggler--on")}),a}),l(this,"setUpTimelineWindowHandle",function(t){var e,i,a,o,r="left"===t?f.timelineWindowLeftHandle:f.timelineWindowRightHandle,s=parseFloat(getComputedStyle(f.timelineWindow).borderLeftWidth);return n(r,function(n){e=f.timeline.getBoundingClientRect();var r=f.timelineWindow.getBoundingClientRect();"left"===t?(i=e.left,a=r.left+r.width-2*s,o=n-r.left):(i=r.left+2*s,a=e.left+e.width,o=n-(r.left+r.width))},function(n){n-=o;var r=((n=Math.max(Math.min(n,a),i))-e.left)/e.width;"left"===t?f.updateBounds(r,f.state.toRatio):f.updateBounds(f.state.fromRatio,r)})}),l(this,"setUpTimelineWindow",function(){var t,e,i,a,o;return n(f.timelineWindowDrag,function(n){t=f.timeline.getBoundingClientRect(),e=f.timelineWindow.getBoundingClientRect(),o=n-e.left,i=t.left,a=t.left+(t.width-e.width)},function(n){n-=o;var r=((n=Math.max(Math.min(n,a),i))-t.left)/t.width;f.updateBounds(r,r+e.width/t.width)})}),l(this,"setTimelineWindowLeft",function(t){f.timelineOverlayLeft.style.right="".concat(100*(1-t),"%"),f.timelineWindow.style.left="".concat(100*t,"%")}),l(this,"setTimelineWindowRight",function(t){f.timelineOverlayRight.style.left="".concat(100*t,"%"),f.timelineWindow.style.right="".concat(100*(1-t),"%")}),l(this,"setUpCanvasTooltipListener",function(){var t,e,i=f.props,n=i.weekdays,a=i.months,o=function(i){var o,r=f.state,s=r.minX,l=r.maxX,c=r.xPoints,d=r.y,h=s+(i-t.left)/t.width*(l-s),u=c.findIndex(function(t){return t>=h}),v=u-1;if(e(u)||(u=-1),e(v)||(v=-1),u<0){if(v<0)return f.removeTooltip();o=v}else if(v<0)o=u;else{var m=c[v],p=c[u];o=h-m>p-h?u:v}var g=c[o];if(g!==f.tooltipForX){f.tooltipForX=g,f.tooltip||f.addTooltip();var y=new Date(g);f.tooltipDate.textContent="".concat(n[y.getDay()],", ").concat(a[y.getMonth()]," ").concat(y.getDate());var w=0,b=d,_=Array.isArray(b),x=0;for(b=_?b:b[Symbol.iterator]();;){var S;if(_){if(x>=b.length)break;S=b[x++]}else{if((x=b.next()).done)break;S=x.value}var A=S,L=A.isShown,T=A.points,C=A.name;L&&(f.tooltipValues.childNodes[2*w].textContent=T[o],f.tooltipValues.childNodes[2*w+1].textContent=C,w++)}var E=(g-s)/(l-s);f.tooltip.style.left="".concat(100*E,"%"),f.updateTooltipPoints(o,E),f.updateTooltipLine(g)}},r=function(){t=f.canvas.getBoundingClientRect(),e=function(t){var e=f.state.xPoints;return t>=0&&t<e.length}},s=function(t){if(t.touches.length>1)return d();r(),f.canvas.addEventListener("touchend",d),f.canvas.addEventListener("touchmove",l),f.canvas.addEventListener("touchend",d),f.canvas.addEventListener("touchcancel",d),l(t)};function l(e){var i=e.changedTouches[0].clientX,n=e.changedTouches[0].clientY;i<t.left||i>t.left+t.width||n<t.top||n>t.top+t.height?d():o(i,n)}function c(t){o(t.clientX,t.clientY)}f.canvas.addEventListener("touchstart",s);var d=function t(){f.canvas.removeEventListener("pointermove",c),f.canvas.removeEventListener("pointerleave",t),f.canvas.removeEventListener("pointercancel",t),f.canvas.removeEventListener("touchmove",l),f.canvas.removeEventListener("touchend",t),f.canvas.removeEventListener("touchcancel",t),f.removeTooltip()},h=function(){r(),f.canvas.addEventListener("pointermove",c),f.canvas.addEventListener("pointerleave",d),f.canvas.addEventListener("pointercancel",d)};return f.canvas.addEventListener("pointerenter",h),function(){d(),f.canvas.removeEventListener(h),f.canvas.removeEventListener(s)}}),l(this,"addTooltip",function(){var t=f.state.y;f.tooltip=document.createElement("div"),f.tooltip.classList.add("chartogram__tooltip"),f.tooltipContainer.appendChild(f.tooltip),f.tooltipDate=document.createElement("h1"),f.tooltipDate.classList.add("chartogram__tooltip-header"),f.tooltip.appendChild(f.tooltipDate),f.tooltipValues=document.createElement("dl"),f.tooltipValues.classList.add("chartogram__tooltip-values"),f.tooltip.appendChild(f.tooltipValues);var e=t,i=Array.isArray(e),n=0;for(e=i?e:e[Symbol.iterator]();;){var a;if(i){if(n>=e.length)break;a=e[n++]}else{if((n=e.next()).done)break;a=n.value}var o=a,r=o.isShown,s=o.color;if(r){var l=document.createElement("dt");l.style.color=s,f.tooltipValues.appendChild(l);var c=document.createElement("dd");c.style.color=s,f.tooltipValues.appendChild(c)}}}),l(this,"addTooltipLine",function(){f.tooltipLine=document.createElementNS("http://www.w3.org/2000/svg","line"),f.tooltipLine.setAttributeNS(null,"class","chartogram__tooltip-line"),f.canvas.insertBefore(f.tooltipLine,f.canvas.querySelector("polyline"))}),l(this,"removeTooltip",function(){f.tooltip&&(f.tooltipForX=void 0,f.tooltipContainer.removeChild(f.tooltip),f.tooltip=void 0,f.removeTooltipPoints(),f.removeTooltipLine())}),l(this,"removeTooltipLine",function(){f.canvas.removeChild(f.tooltipLine),f.tooltipLine=void 0}),l(this,"addTooltipPoints",function(){f.tooltipPoints=[];var t=f.state.y,e=Array.isArray(t),i=0;for(t=e?t:t[Symbol.iterator]();;){var n;if(e){if(i>=t.length)break;n=t[i++]}else{if((i=t.next()).done)break;n=i.value}var a=n;if(a.isShown){var o=document.createElement("div");o.classList.add("chartogram__tooltip-point"),o.style.color=a.color,f.tooltipPoints.push(o),f.canvasWrapper.appendChild(o)}}}),l(this,"removeTooltipPoints",function(){var t=f.tooltipPoints,e=Array.isArray(t),i=0;for(t=e?t:t[Symbol.iterator]();;){var n;if(e){if(i>=t.length)break;n=t[i++]}else{if((i=t.next()).done)break;n=i.value}var a=n;f.canvasWrapper.removeChild(a)}f.tooltipPoints=void 0}),l(this,"updateTooltipLine",function(t){var e=f.props.canvasWidth,i=f.state.aspectRatio;f.tooltipLine||f.addTooltipLine(),f.tooltipLine.setAttributeNS(null,"x1",f.fixSvgCoordinate(f.mapX(t))),f.tooltipLine.setAttributeNS(null,"x2",f.fixSvgCoordinate(f.mapX(t))),f.tooltipLine.setAttributeNS(null,"y1",0),f.tooltipLine.setAttributeNS(null,"y2",f.fixSvgCoordinate(e/i))}),l(this,"updateTooltipPoints",function(t,e){var i=f.state,n=i.maxY,a=i.y;f.tooltipPoints||f.addTooltipPoints();for(var o=0;o<f.tooltipPoints.length;){var r=f.tooltipPoints[o],s=a[o].points[t]/n;r.style.left="".concat(100*e,"%"),r.style.bottom="".concat(100*s,"%"),o++}}),this.props=o({title:g,gaugeTickMarksCount:6,timelineWindowSize:40,canvasWidth:512,precisionFactor:Math.pow(10,y.precision||3),months:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],weekdays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},y),this.rootNode=s,this.data=o({},d,{minX:Math.min.apply(Math,a(d.x.points)),maxX:Math.max.apply(Math,a(d.x.points)),y:d.y.map(function(t){return o({},t,{min:Math.min.apply(Math,a(t.points)),max:Math.max.apply(Math,a(t.points))})})})}var d,h,u;return d=c,(h=[{key:"componentDidMount",value:function(){this.rootNode.classList.add("chartogram"),this.rootNode.innerHTML='\n\t\t\t<header class="chartogram__header">\n\t\t\t\t<h1 class="chartogram__title">'.concat(this.props.title,'</h1>\n\t\t\t</header>\n\t\t\t<div class="chartogram__plan-with-axes">\n\t\t\t\t<div class="chartogram__plan">\n\t\t\t\t\t<div class="chartogram__top-border"></div>\n\t\t\t\t\t<div class="chartogram__canvas-wrapper">\n\t\t\t\t\t\t<svg class="chartogram__canvas"></svg>\n\t\t\t\t\t\t<div class="chartogram__x"></div>\n\t\t\t\t\t\t<div class="chartogram__y-wrapper">\n\t\t\t\t\t\t\t<div class="chartogram__y"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class="chartogram__timeline">\n\t\t\t\t<div class="chartogram__timeline-canvas-padding">\n\t\t\t\t\t<svg class="chartogram__timeline-canvas" preserveAspectRatio="none"></svg>\n\t\t\t\t</div>\n\t\t\t\t<div class="chartogram__timeline-overlay-left"></div>\n\t\t\t\t<div class="chartogram__timeline-overlay-right"></div>\n\t\t\t\t<div class="chartogram__timeline-window">\n\t\t\t\t\t<button type="button" class="chartogram__reset-button chartogram__timeline-window__drag"></button>\n\t\t\t\t\t<button type="button" class="chartogram__reset-button chartogram__timeline-window__left-handle"></button>\n\t\t\t\t\t<button type="button" class="chartogram__reset-button chartogram__timeline-window__right-handle"></button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class="chartogram__chart-togglers"></div>\n\t\t'),this.tooltipContainer=this.rootNode.querySelector(".chartogram__plan"),this.canvas=this.rootNode.querySelector(".chartogram__canvas"),this.canvasWrapper=this.rootNode.querySelector(".chartogram__canvas-wrapper"),this.xAxis=this.rootNode.querySelector(".chartogram__x"),this.yAxis=this.rootNode.querySelector(".chartogram__y"),this.timeline=this.rootNode.querySelector(".chartogram__timeline"),this.timelineOverlayLeft=this.rootNode.querySelector(".chartogram__timeline-overlay-left"),this.timelineWindowLeftHandle=this.rootNode.querySelector(".chartogram__timeline-window__left-handle"),this.timelineWindow=this.rootNode.querySelector(".chartogram__timeline-window"),this.timelineWindowDrag=this.rootNode.querySelector(".chartogram__timeline-window__drag"),this.timelineWindowRightHandle=this.rootNode.querySelector(".chartogram__timeline-window__right-handle"),this.timelineOverlayRight=this.rootNode.querySelector(".chartogram__timeline-overlay-right"),this.timelineCanvas=this.rootNode.querySelector(".chartogram__timeline-canvas"),this.setUpTimelineWindowHandle("left"),this.setUpTimelineWindowHandle("right"),this.setUpTimelineWindow(),this.setUpCanvasTooltipListener();var t=this.rootNode.querySelector(".chartogram__chart-togglers");e(t);var i=this.data.y,n=Array.isArray(i),a=0;for(i=n?i:i[Symbol.iterator]();;){var o;if(n){if(a>=i.length)break;o=i[a++]}else{if((a=i.next()).done)break;o=a.value}var r=o;t.appendChild(this.createGraphToggler(r))}this.state=this.getInitialState(),this.updateTimelineBounds(this.state.fromRatio,this.state.toRatio),window.addEventListener("resize",this.onResizeThrottled)}},{key:"componentWillUnmount",value:function(){window.removeEventListener("resize",this.onResizeThrottled)}},{key:"getCanvasAspectRatio",value:function(){var t=this.canvas.getBoundingClientRect();return t.width/t.height}},{key:"getTimelineCanvasAspectRatio",value:function(){var t=this.timelineCanvas.getBoundingClientRect();return t.width/t.height}},{key:"setState",value:function(t,e){this.state=o({},this.state,t),this.render(e)}},{key:"getInitialState",value:function(){var t,e=this.props.timelineWindowSize,i=this.data,n=i.minX,a=i.maxX;t=this.data.x.points.length>e?this.data.x.points.length-e:0;var r=(this.data.x.points[t]-n)/(a-n);return o({},this.createState(r,1),{aspectRatio:this.getCanvasAspectRatio(),timelineAspectRatio:this.getTimelineCanvasAspectRatio(),yScale:1})}},{key:"createState",value:function(t,e){var i,n,r=this,s=this.data.x,l=this.data.minX+t*(this.data.maxX-this.data.minX),c=this.data.minX+e*(this.data.maxX-this.data.minX);i=l===this.data.minX?0:s.points.findIndex(function(t){return t>l})-1,n=c===this.data.maxX?s.points.length-1:s.points.findIndex(function(t){return t>c});var d=s.points.slice(i,n+1),h=d.slice();d.length>=2&&(s.points[i]!==l&&(h[0]=l),s.points[n]!==c&&(h[h.length-1]=c));var u=this.data.y.map(function(t,e){var h=r.data.y[e].points.slice(i,n+1),u=h.slice();if(d.length>=2){if(s.points[i]!==l){var v=r.data.y[e].points[i],m=v+(r.data.y[e].points[i+1]-v)*((l-r.data.x.points[i])/(r.data.x.points[i+1]-r.data.x.points[i]));u[0]=m}if(s.points[n]!==c){var p=r.data.y[e].points[n],f=r.data.y[e].points[n-1],g=f+(p-f)*((c-r.data.x.points[n-1])/(r.data.x.points[n]-r.data.x.points[n-1]));u[u.length-1]=g}}return o({},r.data.y[e],r.state?r.state.y[e]:{isShown:!0},{points:h,graphPoints:u,min:0,max:Math.max.apply(Math,a(u))})});return o({minX:l,maxX:c,fromIndex:i,toIndex:n,fromRatio:t,toRatio:e,xPoints:d,xGraphPoints:h},this.calculateMinMaxY(u),{y:u})}},{key:"calculateMinMaxY",value:function(t){var e=1/0,i=-1/0,n=t,a=Array.isArray(n),o=0;for(n=a?n:n[Symbol.iterator]();;){var r;if(a){if(o>=n.length)break;r=n[o++]}else{if((o=n.next()).done)break;r=o.value}var s=r;s.isShown&&(e=Math.min(e,s.min),i=Math.max(i,s.max))}e=0;var l=1/0,c=-1/0,d=function(){if(u){if(v>=h.length)return"break";m=h[v++]}else{if((v=h.next()).done)return"break";m=v.value}var e=m;t.find(function(t){return t.id===e.id}).isShown&&(l=Math.min(l,e.min),c=Math.max(c,e.max))},h=this.data.y,u=Array.isArray(h),v=0;for(h=u?h:h[Symbol.iterator]();;){var m;if("break"===d())break}return{minY:e,maxY:i,minYGlobal:l=0,maxYGlobal:c}}},{key:"updateTimelineBounds",value:function(t,e){this.setTimelineWindowLeft(t),this.setTimelineWindowRight(e)}},{key:"updateBounds",value:function(t,e){this.updateTimelineBounds(t,e),this.setState(this.createState(t,e),!1)}},{key:"createPolylinePoints",value:function(t,e){return i=t.map(this.fixSvgCoordinate),n=e.map(this.fixSvgCoordinate),i.map(function(t,e){return"".concat(t,",").concat(n[e])});var i,n}},{key:"render",value:function(){var t=this,i=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],n=this.props,a=n.canvasWidth,o=n.gaugeTickMarksCount,r=this.state,s=r.minX,l=r.maxX,c=r.minY,d=r.maxY,h=r.yScale,u=r.xGraphPoints,v=r.aspectRatio;e(this.canvas),this.canvas.setAttribute("viewBox","0 0 ".concat(a," ").concat(this.fixSvgCoordinate(a/v)));var m=c,p=function(t,e){for(t=Math.floor(t);;){if(t<e)return e;if(t%e==0)return t;t--}}(d,10),f=(d-c)/(p-m),g=function(t,e,i){for(var n=new Array(i),a=0;a<i;)n[a]=t+a*(e-t)/(i-1),a++;return n}(m,p,o),y=Array.isArray(g),w=0;for(g=y?g:g[Symbol.iterator]();;){var b;if(y){if(w>=g.length)break;b=g[w++]}else{if((w=g.next()).done)break;b=w.value}var _=b;this.canvas.appendChild(this.createGridLine(_))}var x=this.state.y,S=Array.isArray(x),A=0;for(x=S?x:x[Symbol.iterator]();;){var L;if(S){if(A>=x.length)break;L=x[A++]}else{if((A=x.next()).done)break;L=A.value}var T=L,C=T.color,E=T.graphPoints;if(T.isShown){var k=document.createElement("polyline");k.setAttribute("stroke",C),k.setAttribute("points",this.createPolylinePoints(u.map(this.mapX),E.map(function(e){return t.mapY(d-e*h)})).join(" ")),k.classList.add("chartogram__graph"),this.canvas.appendChild(k)}}this.canvas.innerHTML+="",this.drawGauges(s,l,m,p,f),i&&this.renderTimeline()}}])&&s(d.prototype,h),u&&s(d,u),c}();return function(t,e,i,n){var a=new c(t,e,i,n);return a.componentDidMount(),a.render(),function(){a.componentWillUnmount()}}}); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).chartogram=e()}(this,function(){"use strict";function t(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function e(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function n(t,e){return t.map(function(t,n){return"".concat(t,",").concat(e[n])})}function i(t,e,n,i,o){for(var a=0;a<i;){var r=document.createElement("div"),s=e+a*(n-e)/(i-1);o&&(s=o(s)),r.appendChild(document.createTextNode(s)),t.appendChild(r),a++}}function o(t,e){var n,i=0,o=function(){n=void 0,i=Date.now(),t()};return function(){var a=Date.now(),r=e-(a-i);r<=0?(n&&(clearTimeout(n),n=void 0),i=a,t()):n||(n=setTimeout(o,r))}}function a(t,e,n){function i(t){n(t.changedTouches[0].clientX,t.changedTouches[0].clientY)}function o(t){n(t.clientX,t.clientY)}function a(){window.removeEventListener("pointermove",o),window.removeEventListener("touchmove",i),window.removeEventListener("pointerup",a),window.removeEventListener("pointercancel",a),window.removeEventListener("touchend",a),window.removeEventListener("touchcancel",a)}function r(t){if(t.touches.length>1)return a();e(t.changedTouches[0].clientX,t.changedTouches[0].clientY),window.addEventListener("touchmove",i),window.addEventListener("touchend",a),window.addEventListener("touchcancel",a)}function s(t){e(t.clientX,t.clientY),window.addEventListener("pointermove",o),window.addEventListener("pointerup",a),window.addEventListener("pointercancel",a)}return t.addEventListener("touchstart",r),t.addEventListener("pointerdown",s),function(){a(),t.removeEventListener(s),t.removeEventListener(r)}}function r(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=[],i=!0,o=!1,a=void 0;try{for(var r,s=t[Symbol.iterator]();!(i=(r=s.next()).done)&&(n.push(r.value),!e||n.length!==e);i=!0);}catch(t){o=!0,a=t}finally{try{i||null==s.return||s.return()}finally{if(o)throw a}}return n}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function s(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function l(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var c=function(){function i(t){var e=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,i),l(this,"onResize",function(t){e.setState({aspectRatio:e.getCanvasAspectRatio()})}),l(this,"onResizeThrottled",o(this.onResize,33)),l(this,"setState",function(t){e.state=function(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter(function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable}))),i.forEach(function(e){l(t,e,n[e])})}return t}({},e.state,t),e.render()}),l(this,"fixSvgCoordinate",function(t){var n=e.props.precisionFactor;return Math.round(t*n)/n}),l(this,"mapX",function(t){var n=e.props,i=n.canvasWidth,o=n.data,a=o.minX;return(t-a)/(o.maxX-a)*i}),l(this,"mapY",function(t){var n=e.props,i=n.canvasWidth,o=n.minYGlobal;return(t-o)/(n.maxYGlobal-o)*i/e.state.aspectRatio}),l(this,"setUpTimelineWindowHandle",function(t){var n,i,o,r,s="left"===t?e.timelineWindowLeftHandle:e.timelineWindowRightHandle,l=parseFloat(getComputedStyle(e.timelineWindow).borderLeftWidth);return a(s,function(a){n=e.timeline.getBoundingClientRect();var s=e.timelineWindow.getBoundingClientRect();"left"===t?(i=n.left,o=s.left+s.width-2*l,r=a-s.left):(i=s.left+2*l,o=n.left+n.width,r=a-(s.left+s.width))},function(a){a-=r;var s=((a=Math.max(Math.min(a,o),i))-n.left)/n.width;"left"===t?e.updateBounds(s,e.props.toRatio):e.updateBounds(e.props.fromRatio,s)})}),l(this,"setUpTimelineWindow",function(){var t,n,i,o,r;return a(e.timelineWindowDrag,function(a){t=e.timeline.getBoundingClientRect(),n=e.timelineWindow.getBoundingClientRect(),r=a-n.left,i=t.left,o=t.left+(t.width-n.width)},function(a){a-=r;var s=((a=Math.max(Math.min(a,o),i))-t.left)/t.width;e.updateBounds(s,s+n.width/t.width)})}),l(this,"setTimelineWindowLeft",function(t){e.timelineOverlayLeft.style.right="".concat(100*(1-t),"%"),e.timelineWindow.style.left="".concat(100*t,"%")}),l(this,"setTimelineWindowRight",function(t){e.timelineOverlayRight.style.left="".concat(100*t,"%"),e.timelineWindow.style.right="".concat(100*(1-t),"%")}),this.props=t}var c,h,d;return c=i,(h=[{key:"componentDidUpdate",value:function(t){this.props!==t&&(this.props=t,this.state={aspectRatio:this.getCanvasAspectRatio()},this.onChangeBounds(this.props.fromRatio,this.props.toRatio),this.render())}},{key:"componentDidMount",value:function(){var t=this.props.rootNode;this.timeline=t.querySelector(".chartogram__timeline"),this.timelineOverlayLeft=t.querySelector(".chartogram__timeline-overlay-left"),this.timelineWindowLeftHandle=t.querySelector(".chartogram__timeline-window__left-handle"),this.timelineWindow=t.querySelector(".chartogram__timeline-window"),this.timelineWindowDrag=t.querySelector(".chartogram__timeline-window__drag"),this.timelineWindowRightHandle=t.querySelector(".chartogram__timeline-window__right-handle"),this.timelineOverlayRight=t.querySelector(".chartogram__timeline-overlay-right"),this.timelineCanvas=t.querySelector(".chartogram__timeline-canvas"),this.state={aspectRatio:this.getCanvasAspectRatio()},this.setUpTimelineWindowHandle("left"),this.setUpTimelineWindowHandle("right"),this.setUpTimelineWindow(),window.addEventListener("resize",this.onResizeThrottled),this.onChangeBounds(this.props.fromRatio,this.props.toRatio),this.render()}},{key:"componentWillUnmount",value:function(){window.removeEventListener("resize",this.onResizeThrottled)}},{key:"getCanvasAspectRatio",value:function(){var t=this.timelineCanvas.getBoundingClientRect();return t.width/t.height}},{key:"render",value:function(){var n=this,i=this.props,o=i.canvasWidth,a=i.y,s=i.yScale,l=i.data,c=i.maxYGlobal,h=this.state.aspectRatio,d=l.x;e(this.timelineCanvas),this.timelineCanvas.setAttribute("viewBox","0 0 ".concat(o," ").concat(this.fixSvgCoordinate(o/h)));var u=function(){if(v){if(m>=p.length)return"break";f=p[m++]}else{if((m=p.next()).done)return"break";f=m.value}var e=f,i=e.id,o=e.color,l=e.points;if(a.find(function(t){return t.id===i}).isShown){var h=r(function e(n,i,o){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:Math.max.apply(Math,t(i)),r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:.025,s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0,l=arguments.length>6&&void 0!==arguments[6]?arguments[6]:new Array(n.length),c=arguments.length>7&&void 0!==arguments[7]?arguments[7]:new Array(n.length),h=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0;if(s+2>n.length-1){for(;s<i.length;)l[h]=n[s],c[h]=i[s],h++,s++;return l=l.slice(0,h),c=c.slice(0,h),l.length<=o?[l,c]:(n.length/l.length<1.1&&(r=Math.min(r+.025,1)),e(l,c,o,a,r))}var d=(i[s+2]+i[s])/2;return Math.abs(d-i[s+1])/a<r?(l[h]=n[s],l[h+1]=n[s+2],c[h]=i[s],c[h+1]=i[s+2],e(n,i,o,a,r,s+2,l,c,h+1)):(l[h]=n[s],l[h+1]=n[s+1],l[h+2]=n[s+2],c[h]=i[s],c[h+1]=i[s+1],c[h+2]=i[s+2],e(n,i,o,a,r,s+2,l,c,h+2))}(d.points,l,80),2),u=h[0],g=h[1],y=document.createElement("polyline");y.setAttribute("stroke",o),y.setAttribute("points",n.createPolylinePoints(u.map(n.mapX),g.map(function(t){return n.mapY(c-t*s)})).join(" ")),y.classList.add("chartogram__graph"),n.timelineCanvas.appendChild(y)}},p=l.y,v=Array.isArray(p),m=0;for(p=v?p:p[Symbol.iterator]();;){var f;if("break"===u())break}this.timelineCanvas.innerHTML+=""}},{key:"onChangeBounds",value:function(t,e){this.setTimelineWindowLeft(t),this.setTimelineWindowRight(e)}},{key:"updateBounds",value:function(t,e){this.props.onChangeBounds(t,e),this.props.fromRatio=t,this.props.toRatio=e,this.onChangeBounds(t,e)}},{key:"createPolylinePoints",value:function(t,e){return n(t.map(this.fixSvgCoordinate),e.map(this.fixSvgCoordinate))}}])&&s(c.prototype,h),d&&s(c,d),i}();function h(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function d(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}c.INITIAL_MARKUP='\n\t<div class="chartogram__timeline">\n\t\t<div class="chartogram__timeline-canvas-padding">\n\t\t\t<svg class="chartogram__timeline-canvas" preserveAspectRatio="none"></svg>\n\t\t</div>\n\t\t<div class="chartogram__timeline-overlay-left"></div>\n\t\t<div class="chartogram__timeline-overlay-right"></div>\n\t\t<div class="chartogram__timeline-window">\n\t\t\t<button type="button" class="chartogram__reset-button chartogram__timeline-window__drag"></button>\n\t\t\t<button type="button" class="chartogram__reset-button chartogram__timeline-window__left-handle"></button>\n\t\t\t<button type="button" class="chartogram__reset-button chartogram__timeline-window__right-handle"></button>\n\t\t</div>\n\t</div>\n';var u=function(){function t(e){var n=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),d(this,"createGraphToggler",function(t){var e=t.id,i=t.name,o=t.color,a=document.createElement("button");a.setAttribute("type","button"),a.classList.add("chartogram__chart-toggler"),a.classList.add("chartogram__chart-toggler--on"),a.classList.add("chartogram__reset-button");var r="http://www.w3.org/2000/svg",s=document.createElementNS(r,"svg");s.setAttribute("viewBox","0 0 19 19"),s.setAttribute("class","chartogram__chart-toggler-check");var l=document.createElementNS(r,"circle");l.setAttribute("cx","9.5"),l.setAttribute("cy","9.5"),l.setAttribute("r","9.5"),l.setAttribute("fill",o),s.appendChild(l);var c=document.createElementNS(r,"circle");c.setAttribute("cx","9.5"),c.setAttribute("cy","9.5"),c.setAttribute("r","8"),c.setAttribute("class","chartogram__chart-toggler-check-circle"),s.appendChild(c);var h=document.createElementNS(r,"path");return h.setAttribute("d","M13.64 4.94l-6.2 6.34-1.69-1.9c-.73-.63-1.89.1-1.36 1.06l2 3.38c.3.43 1.04.85 1.78 0 .32-.42 6.31-7.93 6.31-7.93.74-.84-.2-1.58-.84-.95z"),h.setAttribute("fill","white"),h.setAttribute("class","chartogram__chart-toggler-check-mark"),s.appendChild(h),a.appendChild(s),a.appendChild(document.createTextNode(i)),a.addEventListener("click",function(){return n.onToggle(e,a)}),a}),d(this,"onToggle",function(t,e){(0,n.props.onToggle)(t)&&e.classList.toggle("chartogram__chart-toggler--on")}),this.props=e}var n,i,o;return n=t,(i=[{key:"componentDidMount",value:function(){var t=this.props,n=t.rootNode,i=t.data,o=n.querySelector(".chartogram__chart-togglers");e(o);var a=i.y,r=Array.isArray(a),s=0;for(a=r?a:a[Symbol.iterator]();;){var l;if(r){if(s>=a.length)break;l=a[s++]}else{if((s=a.next()).done)break;l=s.value}var c=l;o.appendChild(this.createGraphToggler(c))}}}])&&h(n.prototype,i),o&&h(n,o),t}();function p(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}(t)||function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}()}function v(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{},i=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(i=i.concat(Object.getOwnPropertySymbols(n).filter(function(t){return Object.getOwnPropertyDescriptor(n,t).enumerable}))),i.forEach(function(e){f(t,e,n[e])})}return t}function m(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function f(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}u.INITIAL_MARKUP='\n\t<div class="chartogram__chart-togglers"></div>\n';var g=function(){function t(n,a){var r=this,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Title",l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),f(this,"onResize",function(t){r.setState({aspectRatio:r.getCanvasAspectRatio()},!1)}),f(this,"onResizeThrottled",o(this.onResize,33)),f(this,"onChangeBounds",function(t,e){r.setState(r.createState(t,e),!1)}),f(this,"fixSvgCoordinate",function(t){var e=r.props.precisionFactor;return Math.round(t*e)/e}),f(this,"mapX",function(t){var e=r.props.canvasWidth,n=r.state,i=n.minX;return(t-i)/(n.maxX-i)*e}),f(this,"mapY",function(t){var e=r.props.canvasWidth,n=r.state,i=n.minY;return(t-i)/(n.maxY-i)*e/n.aspectRatio}),f(this,"createGridLine",function(t){var e=r.state,n=e.minX,i=e.maxX,o=(e.minY,e.maxY),a=e.yScale,s=document.createElement("line");return s.classList.add("chartogram__grid-line"),s.setAttribute("x1",r.fixSvgCoordinate(r.mapX(n))),s.setAttribute("x2",r.fixSvgCoordinate(r.mapX(i))),s.setAttribute("y1",r.fixSvgCoordinate(r.mapY(o-a*t))),s.setAttribute("y2",r.fixSvgCoordinate(r.mapY(o-a*t))),s}),f(this,"drawGauges",function(t,n,o,a,s){var l=r.props,c=l.gaugeTickMarksCount,h=l.months;e(r.xAxis),e(r.yAxis),i(r.xAxis,t,n,c,function(t){var e=new Date(t);return"".concat(h[e.getMonth()]," ").concat(e.getDate())}),i(r.yAxis,o,a,c),r.yAxis.style.height="".concat(100/s,"%")}),f(this,"setUpCanvasTooltipListener",function(){var t,e,n=r.props,i=n.weekdays,o=n.months,a=function(n){var a,s=r.state,l=s.minX,c=s.maxX,h=s.xPoints,d=s.y,u=l+(n-t.left)/t.width*(c-l),p=h.findIndex(function(t){return t>=u}),v=p-1;if(e(p)||(p=-1),e(v)||(v=-1),p<0){if(v<0)return r.removeTooltip();a=v}else if(v<0)a=p;else{var m=h[v],f=h[p];a=u-m>f-u?p:v}var g=h[a];if(g!==r.tooltipForX){r.tooltipForX=g,r.tooltip||r.addTooltip();var y=new Date(g);r.tooltipDate.textContent="".concat(i[y.getDay()],", ").concat(o[y.getMonth()]," ").concat(y.getDate());var w=0,b=d,_=Array.isArray(b),x=0;for(b=_?b:b[Symbol.iterator]();;){var S;if(_){if(x>=b.length)break;S=b[x++]}else{if((x=b.next()).done)break;S=x.value}var A=S,L=A.isShown,C=A.points,T=A.name;L&&(r.tooltipValues.childNodes[2*w].textContent=C[a],r.tooltipValues.childNodes[2*w+1].textContent=T,w++)}var k=(g-l)/(c-l);r.tooltip.style.left="".concat(100*k,"%"),r.updateTooltipPoints(a,k),r.updateTooltipLine(g)}},s=function(){t=r.canvas.getBoundingClientRect(),e=function(t){var e=r.state.xPoints;return t>=0&&t<e.length}},l=function(t){if(t.touches.length>1)return d();s(),r.canvas.addEventListener("touchend",d),r.canvas.addEventListener("touchmove",c),r.canvas.addEventListener("touchend",d),r.canvas.addEventListener("touchcancel",d),c(t)};function c(e){var n=e.changedTouches[0].clientX,i=e.changedTouches[0].clientY;n<t.left||n>t.left+t.width||i<t.top||i>t.top+t.height?d():a(n,i)}function h(t){a(t.clientX,t.clientY)}r.canvas.addEventListener("touchstart",l);var d=function t(){r.canvas.removeEventListener("pointermove",h),r.canvas.removeEventListener("pointerleave",t),r.canvas.removeEventListener("pointercancel",t),r.canvas.removeEventListener("touchmove",c),r.canvas.removeEventListener("touchend",t),r.canvas.removeEventListener("touchcancel",t),r.removeTooltip()},u=function(){s(),r.canvas.addEventListener("pointermove",h),r.canvas.addEventListener("pointerleave",d),r.canvas.addEventListener("pointercancel",d)};return r.canvas.addEventListener("pointerenter",u),function(){d(),r.canvas.removeEventListener(u),r.canvas.removeEventListener(l)}}),f(this,"addTooltip",function(){var t=r.state.y;r.tooltip=document.createElement("div"),r.tooltip.classList.add("chartogram__tooltip"),r.tooltipContainer.appendChild(r.tooltip),r.tooltipDate=document.createElement("h1"),r.tooltipDate.classList.add("chartogram__tooltip-header"),r.tooltip.appendChild(r.tooltipDate),r.tooltipValues=document.createElement("dl"),r.tooltipValues.classList.add("chartogram__tooltip-values"),r.tooltip.appendChild(r.tooltipValues);var e=t,n=Array.isArray(e),i=0;for(e=n?e:e[Symbol.iterator]();;){var o;if(n){if(i>=e.length)break;o=e[i++]}else{if((i=e.next()).done)break;o=i.value}var a=o,s=a.isShown,l=a.color;if(s){var c=document.createElement("dt");c.style.color=l,r.tooltipValues.appendChild(c);var h=document.createElement("dd");h.style.color=l,r.tooltipValues.appendChild(h)}}}),f(this,"addTooltipLine",function(){r.tooltipLine=document.createElementNS("http://www.w3.org/2000/svg","line"),r.tooltipLine.setAttributeNS(null,"class","chartogram__tooltip-line"),r.canvas.insertBefore(r.tooltipLine,r.canvas.querySelector("polyline"))}),f(this,"removeTooltip",function(){r.tooltip&&(r.tooltipForX=void 0,r.tooltipContainer.removeChild(r.tooltip),r.tooltip=void 0,r.removeTooltipPoints(),r.removeTooltipLine())}),f(this,"removeTooltipLine",function(){r.canvas.removeChild(r.tooltipLine),r.tooltipLine=void 0}),f(this,"addTooltipPoints",function(){r.tooltipPoints=[];var t=r.state.y,e=Array.isArray(t),n=0;for(t=e?t:t[Symbol.iterator]();;){var i;if(e){if(n>=t.length)break;i=t[n++]}else{if((n=t.next()).done)break;i=n.value}var o=i;if(o.isShown){var a=document.createElement("div");a.classList.add("chartogram__tooltip-point"),a.style.color=o.color,r.tooltipPoints.push(a),r.canvasWrapper.appendChild(a)}}}),f(this,"removeTooltipPoints",function(){var t=r.tooltipPoints,e=Array.isArray(t),n=0;for(t=e?t:t[Symbol.iterator]();;){var i;if(e){if(n>=t.length)break;i=t[n++]}else{if((n=t.next()).done)break;i=n.value}var o=i;r.canvasWrapper.removeChild(o)}r.tooltipPoints=void 0}),f(this,"updateTooltipLine",function(t){var e=r.props.canvasWidth,n=r.state.aspectRatio;r.tooltipLine||r.addTooltipLine(),r.tooltipLine.setAttributeNS(null,"x1",r.fixSvgCoordinate(r.mapX(t))),r.tooltipLine.setAttributeNS(null,"x2",r.fixSvgCoordinate(r.mapX(t))),r.tooltipLine.setAttributeNS(null,"y1",0),r.tooltipLine.setAttributeNS(null,"y2",r.fixSvgCoordinate(e/n))}),f(this,"updateTooltipPoints",function(t,e){var n=r.state,i=n.maxY,o=n.y;r.tooltipPoints||r.addTooltipPoints();for(var a=0,s=0;a<o.length;){if(o[a].isShown){var l=r.tooltipPoints[s],c=o[a].points[t]/i;l.style.left="".concat(100*e,"%"),l.style.bottom="".concat(100*c,"%"),s++}a++}}),this.props=v({title:s,gaugeTickMarksCount:6,timelineWindowSize:40,canvasWidth:512,precisionFactor:Math.pow(10,l.precision||3),months:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],weekdays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},l),this.rootNode=n,this.data=v({},a,{minX:Math.min.apply(Math,p(a.x.points)),maxX:Math.max.apply(Math,p(a.x.points)),y:a.y.map(function(t){return v({},t,{min:Math.min.apply(Math,p(t.points)),max:Math.max.apply(Math,p(t.points))})})})}var a,r,s;return a=t,(r=[{key:"componentDidMount",value:function(){this.rootNode.classList.add("chartogram"),this.rootNode.innerHTML='\n\t\t\t<header class="chartogram__header">\n\t\t\t\t<h1 class="chartogram__title">'.concat(this.props.title,'</h1>\n\t\t\t</header>\n\t\t\t<div class="chartogram__plan-with-axes">\n\t\t\t\t<div class="chartogram__plan">\n\t\t\t\t\t<div class="chartogram__top-border"></div>\n\t\t\t\t\t<div class="chartogram__canvas-wrapper">\n\t\t\t\t\t\t<svg class="chartogram__canvas"></svg>\n\t\t\t\t\t\t<div class="chartogram__x"></div>\n\t\t\t\t\t\t<div class="chartogram__y-wrapper">\n\t\t\t\t\t\t\t<div class="chartogram__y"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t').concat(c.INITIAL_MARKUP,"\n\t\t\t").concat(u.INITIAL_MARKUP,"\n\t\t"),this.tooltipContainer=this.rootNode.querySelector(".chartogram__plan"),this.canvas=this.rootNode.querySelector(".chartogram__canvas"),this.canvasWrapper=this.rootNode.querySelector(".chartogram__canvas-wrapper"),this.xAxis=this.rootNode.querySelector(".chartogram__x"),this.yAxis=this.rootNode.querySelector(".chartogram__y"),this.setUpCanvasTooltipListener(),this.state=this.getInitialState(),this.timeline=new c(this.getTimelineProps()),this.timeline.componentDidMount(),this.togglers=new u(this.getTogglersProps()),this.togglers.componentDidMount(),window.addEventListener("resize",this.onResizeThrottled),this.render()}},{key:"componentWillUnmount",value:function(){this.rootNode.classList.remove("chartogram"),e(this.rootNode),window.removeEventListener("resize",this.onResizeThrottled)}},{key:"getCanvasAspectRatio",value:function(){var t=this.canvas.getBoundingClientRect();return t.width/t.height}},{key:"setState",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.state=v({},this.state,t),this.render(),e&&this.timeline.componentDidUpdate(this.getTimelineProps())}},{key:"getTimelineProps",value:function(){return{rootNode:this.rootNode,data:this.data,canvasWidth:this.props.canvasWidth,precisionFactor:this.props.precisionFactor,fromRatio:this.state.fromRatio,toRatio:this.state.toRatio,minYGlobal:this.state.minYGlobal,maxYGlobal:this.state.maxYGlobal,y:this.state.y,yScale:this.state.yScale,onChangeBounds:this.onChangeBounds}}},{key:"getTogglersProps",value:function(){var t=this;return{rootNode:this.rootNode,data:this.data,onToggle:function(e){var n=t.state.y.find(function(t){return t.id===e});if(n.isShown&&1===t.state.y.filter(function(t){return t.isShown}).length)return;return n.isShown=!n.isShown,t.setState(v({y:t.state.y},t.calculateMinMaxY(t.state.y))),!0}}}},{key:"getInitialState",value:function(){var t,e=this.props.timelineWindowSize,n=this.data,i=n.minX,o=n.maxX;t=this.data.x.points.length>e?this.data.x.points.length-e:0;var a=(this.data.x.points[t]-i)/(o-i);return v({},this.createState(a,1),{aspectRatio:this.getCanvasAspectRatio(),yScale:1})}},{key:"createState",value:function(t,e){var n,i,o=this,a=this.data.x,r=this.data.minX+t*(this.data.maxX-this.data.minX),s=this.data.minX+e*(this.data.maxX-this.data.minX);n=r===this.data.minX?0:a.points.findIndex(function(t){return t>r})-1,i=s===this.data.maxX?a.points.length-1:a.points.findIndex(function(t){return t>s});var l=a.points.slice(n,i+1),c=l.slice();l.length>=2&&(a.points[n]!==r&&(c[0]=r),a.points[i]!==s&&(c[c.length-1]=s));var h=this.data.y.map(function(t,e){var c=o.data.y[e].points.slice(n,i+1),h=c.slice();if(l.length>=2){if(a.points[n]!==r){var d=o.data.y[e].points[n],u=d+(o.data.y[e].points[n+1]-d)*((r-o.data.x.points[n])/(o.data.x.points[n+1]-o.data.x.points[n]));h[0]=u}if(a.points[i]!==s){var m=o.data.y[e].points[i],f=o.data.y[e].points[i-1],g=f+(m-f)*((s-o.data.x.points[i-1])/(o.data.x.points[i]-o.data.x.points[i-1]));h[h.length-1]=g}}return v({},o.data.y[e],o.state?o.state.y[e]:{isShown:!0},{points:c,graphPoints:h,min:0,max:Math.max.apply(Math,p(h))})});return v({minX:r,maxX:s,fromIndex:n,toIndex:i,fromRatio:t,toRatio:e,xPoints:l,xGraphPoints:c},this.calculateMinMaxY(h),{y:h})}},{key:"calculateMinMaxY",value:function(t){var e=1/0,n=-1/0,i=t,o=Array.isArray(i),a=0;for(i=o?i:i[Symbol.iterator]();;){var r;if(o){if(a>=i.length)break;r=i[a++]}else{if((a=i.next()).done)break;r=a.value}var s=r;s.isShown&&(e=Math.min(e,s.min),n=Math.max(n,s.max))}var l=1/0,c=-1/0,h=function(){if(u){if(p>=d.length)return"break";v=d[p++]}else{if((p=d.next()).done)return"break";v=p.value}var e=v;t.find(function(t){return t.id===e.id}).isShown&&(l=Math.min(l,e.min),c=Math.max(c,e.max))},d=this.data.y,u=Array.isArray(d),p=0;for(d=u?d:d[Symbol.iterator]();;){var v;if("break"===h())break}return{minY:e,maxY:n,minYGlobal:l=0,maxYGlobal:c}}},{key:"createPolylinePoints",value:function(t,e){return n(t.map(this.fixSvgCoordinate),e.map(this.fixSvgCoordinate))}},{key:"render",value:function(){var t=this,n=this.props,i=n.canvasWidth,o=n.gaugeTickMarksCount,a=this.state,r=a.minX,s=a.maxX,l=a.minY,c=a.maxY,h=a.yScale,d=a.xGraphPoints,u=a.aspectRatio;e(this.canvas),this.canvas.setAttribute("viewBox","0 0 ".concat(i," ").concat(this.fixSvgCoordinate(i/u)));var p=l,v=function(t,e){for(t=Math.floor(t);;){if(t<e)return e;if(t%e==0)return t;t--}}(c,10),m=(c-l)/(v-p),f=function(t,e,n){for(var i=new Array(n),o=0;o<n;)i[o]=t+o*(e-t)/(n-1),o++;return i}(p,v,o),g=Array.isArray(f),y=0;for(f=g?f:f[Symbol.iterator]();;){var w;if(g){if(y>=f.length)break;w=f[y++]}else{if((y=f.next()).done)break;w=y.value}var b=w;this.canvas.appendChild(this.createGridLine(b))}var _=this.state.y,x=Array.isArray(_),S=0;for(_=x?_:_[Symbol.iterator]();;){var A;if(x){if(S>=_.length)break;A=_[S++]}else{if((S=_.next()).done)break;A=S.value}var L=A,C=L.color,T=L.graphPoints;if(L.isShown){var k=document.createElement("polyline");k.setAttribute("stroke",C),k.setAttribute("points",this.createPolylinePoints(d.map(this.mapX),T.map(function(e){return t.mapY(c-e*h)})).join(" ")),k.classList.add("chartogram__graph"),this.canvas.appendChild(k)}}this.canvas.innerHTML+="",this.drawGauges(r,s,p,v,m)}}])&&m(a.prototype,r),s&&m(a,s),t}();return function(t,e,n,i){var o=new g(t,e,n,i);return o.componentDidMount(),function(){o.componentWillUnmount()}}}); | ||
//# sourceMappingURL=chartogram.js.map |
@@ -10,2 +10,8 @@ "use strict"; | ||
var _Timeline = _interopRequireDefault(require("./Timeline")); | ||
var _Togglers = _interopRequireDefault(require("./Togglers")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
@@ -21,10 +27,2 @@ | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -45,3 +43,3 @@ | ||
var title = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'Title'; | ||
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
var props = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
@@ -52,5 +50,4 @@ _classCallCheck(this, Chartogram); | ||
_this.setState({ | ||
aspectRatio: _this.getCanvasAspectRatio(), | ||
timelineAspectRatio: _this.getTimelineCanvasAspectRatio() | ||
}); | ||
aspectRatio: _this.getCanvasAspectRatio() | ||
}, false); | ||
}); | ||
@@ -60,2 +57,6 @@ | ||
_defineProperty(this, "onChangeBounds", function (from, to) { | ||
_this.setState(_this.createState(from, to), false); | ||
}); | ||
_defineProperty(this, "fixSvgCoordinate", function (x) { | ||
@@ -83,26 +84,9 @@ var precisionFactor = _this.props.precisionFactor; | ||
_defineProperty(this, "mapXForTimeline", function (x) { | ||
var canvasWidth = _this.props.canvasWidth; | ||
var _this$data = _this.data, | ||
minX = _this$data.minX, | ||
maxX = _this$data.maxX; | ||
return (x - minX) / (maxX - minX) * canvasWidth; | ||
}); | ||
_defineProperty(this, "mapYForTimeline", function (y) { | ||
var canvasWidth = _this.props.canvasWidth; | ||
_defineProperty(this, "createGridLine", function (y) { | ||
var _this$state3 = _this.state, | ||
minYGlobal = _this$state3.minYGlobal, | ||
maxYGlobal = _this$state3.maxYGlobal, | ||
timelineAspectRatio = _this$state3.timelineAspectRatio; | ||
return (y - minYGlobal) / (maxYGlobal - minYGlobal) * canvasWidth / timelineAspectRatio; | ||
}); | ||
_defineProperty(this, "createGridLine", function (y) { | ||
var _this$state4 = _this.state, | ||
minX = _this$state4.minX, | ||
maxX = _this$state4.maxX, | ||
minY = _this$state4.minY, | ||
maxY = _this$state4.maxY, | ||
yScale = _this$state4.yScale; | ||
minX = _this$state3.minX, | ||
maxX = _this$state3.maxX, | ||
minY = _this$state3.minY, | ||
maxY = _this$state3.maxY, | ||
yScale = _this$state3.yScale; | ||
var line = document.createElement('line'); | ||
@@ -131,205 +115,2 @@ line.classList.add('chartogram__grid-line'); | ||
_defineProperty(this, "renderTimeline", function () { | ||
var canvasWidth = _this.props.canvasWidth; | ||
var _this$data2 = _this.data, | ||
x = _this$data2.x, | ||
y = _this$data2.y; | ||
var _this$state5 = _this.state, | ||
timelineAspectRatio = _this$state5.timelineAspectRatio, | ||
maxYGlobal = _this$state5.maxYGlobal, | ||
yScale = _this$state5.yScale; // Clear canvas. | ||
(0, _utility.clearElement)(_this.timelineCanvas); // Set canvas `viewBox`. | ||
_this.timelineCanvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(_this.fixSvgCoordinate(canvasWidth / timelineAspectRatio))); | ||
var _loop = function _loop() { | ||
if (_isArray) { | ||
if (_i >= _iterator.length) return "break"; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) return "break"; | ||
_ref = _i.value; | ||
} | ||
var _ref2 = _ref, | ||
id = _ref2.id, | ||
color = _ref2.color, | ||
points = _ref2.points; | ||
var isShown = _this.state.y.find(function (_) { | ||
return _.id === id; | ||
}).isShown; | ||
if (isShown) { | ||
var _simplifyGraph = (0, _utility.simplifyGraph)(x.points, points, 80), | ||
_simplifyGraph2 = _slicedToArray(_simplifyGraph, 2), | ||
_x = _simplifyGraph2[0], | ||
_y = _simplifyGraph2[1]; | ||
var graph = document.createElement('polyline'); | ||
graph.setAttribute('stroke', color); | ||
graph.setAttribute('points', _this.createPolylinePoints(_x.map(_this.mapXForTimeline), _y.map(function (y) { | ||
return _this.mapYForTimeline(maxYGlobal - y * yScale); | ||
})).join(' ')); | ||
graph.classList.add('chartogram__graph'); | ||
_this.timelineCanvas.appendChild(graph); | ||
} | ||
}; | ||
for (var _iterator = y, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
var _ret = _loop(); | ||
if (_ret === "break") break; | ||
} // A workaround to fix WebKit bug when it's not re-rendering the <svg/>. | ||
// https://stackoverflow.com/questions/30905493/how-to-force-webkit-to-update-svg-use-elements-after-changes-to-original | ||
_this.timelineCanvas.innerHTML += ''; | ||
}); | ||
_defineProperty(this, "createGraphToggler", function (_ref3) { | ||
var id = _ref3.id, | ||
name = _ref3.name, | ||
color = _ref3.color; | ||
var toggler = document.createElement('button'); | ||
toggler.setAttribute('type', 'button'); | ||
toggler.classList.add('chartogram__chart-toggler'); | ||
toggler.classList.add('chartogram__chart-toggler--on'); | ||
toggler.classList.add('chartogram__reset-button'); // Add check. | ||
var xmlns = 'http://www.w3.org/2000/svg'; | ||
var check = document.createElementNS(xmlns, 'svg'); | ||
check.setAttribute('viewBox', '0 0 19 19'); | ||
check.setAttribute('class', 'chartogram__chart-toggler-check'); // Add background circle. | ||
var backgroundCircle = document.createElementNS(xmlns, 'circle'); | ||
backgroundCircle.setAttribute('cx', '9.5'); | ||
backgroundCircle.setAttribute('cy', '9.5'); | ||
backgroundCircle.setAttribute('r', '9.5'); | ||
backgroundCircle.setAttribute('fill', color); | ||
check.appendChild(backgroundCircle); // Add check circle. | ||
var checkCircle = document.createElementNS(xmlns, 'circle'); | ||
checkCircle.setAttribute('cx', '9.5'); | ||
checkCircle.setAttribute('cy', '9.5'); | ||
checkCircle.setAttribute('r', '8'); | ||
checkCircle.setAttribute('class', 'chartogram__chart-toggler-check-circle'); | ||
check.appendChild(checkCircle); // Add check mark. | ||
var checkMark = document.createElementNS(xmlns, 'path'); | ||
checkMark.setAttribute('d', 'M13.64 4.94l-6.2 6.34-1.69-1.9c-.73-.63-1.89.1-1.36 1.06l2 3.38c.3.43 1.04.85 1.78 0 .32-.42 6.31-7.93 6.31-7.93.74-.84-.2-1.58-.84-.95z'); | ||
checkMark.setAttribute('fill', 'white'); | ||
checkMark.setAttribute('class', 'chartogram__chart-toggler-check-mark'); | ||
check.appendChild(checkMark); // Add checkmark. | ||
toggler.appendChild(check); // Add graph name. | ||
toggler.appendChild(document.createTextNode(name)); // On click. | ||
toggler.addEventListener('click', function () { | ||
var y = _this.state.y.find(function (_) { | ||
return _.id === id; | ||
}); // Won't allow hiding all graphs. | ||
if (y.isShown) { | ||
var graphsShown = _this.state.y.filter(function (_) { | ||
return _.isShown; | ||
}); | ||
if (graphsShown.length === 1) { | ||
return; | ||
} | ||
} | ||
y.isShown = !y.isShown; | ||
_this.setState(_objectSpread({}, _this.state, _this.calculateMinMaxY(_this.state.y))); | ||
toggler.classList.toggle('chartogram__chart-toggler--on'); | ||
}); | ||
return toggler; | ||
}); | ||
_defineProperty(this, "setUpTimelineWindowHandle", function (side) { | ||
var handle = side === 'left' ? _this.timelineWindowLeftHandle : _this.timelineWindowRightHandle; | ||
var handleWidth = parseFloat(getComputedStyle(_this.timelineWindow).borderLeftWidth); | ||
var timelineCoordinates; | ||
var minX; | ||
var maxX; | ||
var deltaX; | ||
var startedX; | ||
var onDrag = function onDrag(x) { | ||
x -= deltaX; | ||
x = Math.max(Math.min(x, maxX), minX); | ||
var ratio = (x - timelineCoordinates.left) / timelineCoordinates.width; | ||
if (side === 'left') { | ||
_this.updateBounds(ratio, _this.state.toRatio); | ||
} else { | ||
_this.updateBounds(_this.state.fromRatio, ratio); | ||
} | ||
}; | ||
var onDragStart = function onDragStart(x) { | ||
timelineCoordinates = _this.timeline.getBoundingClientRect(); | ||
var timelineWindowCoordinates = _this.timelineWindow.getBoundingClientRect(); | ||
if (side === 'left') { | ||
minX = timelineCoordinates.left; | ||
maxX = timelineWindowCoordinates.left + timelineWindowCoordinates.width - 2 * handleWidth; | ||
deltaX = x - timelineWindowCoordinates.left; | ||
} else { | ||
minX = timelineWindowCoordinates.left + 2 * handleWidth; | ||
maxX = timelineCoordinates.left + timelineCoordinates.width; | ||
deltaX = x - (timelineWindowCoordinates.left + timelineWindowCoordinates.width); | ||
} | ||
}; | ||
return (0, _utility.setUpDrag)(handle, onDragStart, onDrag); | ||
}); | ||
_defineProperty(this, "setUpTimelineWindow", function () { | ||
var timelineCoordinates; | ||
var timelineWindowCoordinates; | ||
var minX; | ||
var maxX; | ||
var innerX; | ||
var onDrag = function onDrag(x) { | ||
x -= innerX; | ||
x = Math.max(Math.min(x, maxX), minX); | ||
var ratio = (x - timelineCoordinates.left) / timelineCoordinates.width; | ||
_this.updateBounds(ratio, ratio + timelineWindowCoordinates.width / timelineCoordinates.width); | ||
}; | ||
var onDragStart = function onDragStart(x) { | ||
timelineCoordinates = _this.timeline.getBoundingClientRect(); | ||
timelineWindowCoordinates = _this.timelineWindow.getBoundingClientRect(); | ||
innerX = x - timelineWindowCoordinates.left; | ||
minX = timelineCoordinates.left; | ||
maxX = timelineCoordinates.left + (timelineCoordinates.width - timelineWindowCoordinates.width); | ||
}; | ||
return (0, _utility.setUpDrag)(_this.timelineWindowDrag, onDragStart, onDrag); | ||
}); | ||
_defineProperty(this, "setTimelineWindowLeft", function (ratio) { | ||
_this.timelineOverlayLeft.style.right = "".concat(100 * (1 - ratio), "%"); | ||
_this.timelineWindow.style.left = "".concat(100 * ratio, "%"); | ||
}); | ||
_defineProperty(this, "setTimelineWindowRight", function (ratio) { | ||
_this.timelineOverlayRight.style.left = "".concat(100 * ratio, "%"); | ||
_this.timelineWindow.style.right = "".concat(100 * (1 - ratio), "%"); | ||
}); | ||
_defineProperty(this, "setUpCanvasTooltipListener", function () { | ||
@@ -343,7 +124,7 @@ var _this$props2 = _this.props, | ||
var onTrack = function onTrack(screenX) { | ||
var _this$state6 = _this.state, | ||
minX = _this$state6.minX, | ||
maxX = _this$state6.maxX, | ||
xPoints = _this$state6.xPoints, | ||
y = _this$state6.y; | ||
var _this$state4 = _this.state, | ||
minX = _this$state4.minX, | ||
maxX = _this$state4.maxX, | ||
xPoints = _this$state4.xPoints, | ||
y = _this$state4.y; | ||
var xScreenRatio = (screenX - canvasDimensions.left) / canvasDimensions.width; | ||
@@ -397,18 +178,18 @@ var xPoint = minX + xScreenRatio * (maxX - minX); | ||
for (var _iterator2 = y, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | ||
var _ref4; | ||
for (var _iterator = y, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
if (_isArray2) { | ||
if (_i2 >= _iterator2.length) break; | ||
_ref4 = _iterator2[_i2++]; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i2 = _iterator2.next(); | ||
if (_i2.done) break; | ||
_ref4 = _i2.value; | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
_ref = _i.value; | ||
} | ||
var _ref5 = _ref4, | ||
isShown = _ref5.isShown, | ||
points = _ref5.points, | ||
name = _ref5.name; | ||
var _ref2 = _ref, | ||
isShown = _ref2.isShown, | ||
points = _ref2.points, | ||
name = _ref2.name; | ||
@@ -540,17 +321,17 @@ if (isShown) { | ||
for (var _iterator3 = y, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
var _ref6; | ||
for (var _iterator2 = y, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | ||
var _ref3; | ||
if (_isArray3) { | ||
if (_i3 >= _iterator3.length) break; | ||
_ref6 = _iterator3[_i3++]; | ||
if (_isArray2) { | ||
if (_i2 >= _iterator2.length) break; | ||
_ref3 = _iterator2[_i2++]; | ||
} else { | ||
_i3 = _iterator3.next(); | ||
if (_i3.done) break; | ||
_ref6 = _i3.value; | ||
_i2 = _iterator2.next(); | ||
if (_i2.done) break; | ||
_ref3 = _i2.value; | ||
} | ||
var _ref7 = _ref6, | ||
isShown = _ref7.isShown, | ||
color = _ref7.color; | ||
var _ref4 = _ref3, | ||
isShown = _ref4.isShown, | ||
color = _ref4.color; | ||
@@ -605,15 +386,15 @@ if (isShown) { | ||
for (var _iterator4 = _this.state.y, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | ||
var _ref8; | ||
for (var _iterator3 = _this.state.y, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
var _ref5; | ||
if (_isArray4) { | ||
if (_i4 >= _iterator4.length) break; | ||
_ref8 = _iterator4[_i4++]; | ||
if (_isArray3) { | ||
if (_i3 >= _iterator3.length) break; | ||
_ref5 = _iterator3[_i3++]; | ||
} else { | ||
_i4 = _iterator4.next(); | ||
if (_i4.done) break; | ||
_ref8 = _i4.value; | ||
_i3 = _iterator3.next(); | ||
if (_i3.done) break; | ||
_ref5 = _i3.value; | ||
} | ||
var y = _ref8; | ||
var y = _ref5; | ||
@@ -633,15 +414,15 @@ if (y.isShown) { | ||
_defineProperty(this, "removeTooltipPoints", function () { | ||
for (var _iterator5 = _this.tooltipPoints, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { | ||
var _ref9; | ||
for (var _iterator4 = _this.tooltipPoints, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | ||
var _ref6; | ||
if (_isArray5) { | ||
if (_i5 >= _iterator5.length) break; | ||
_ref9 = _iterator5[_i5++]; | ||
if (_isArray4) { | ||
if (_i4 >= _iterator4.length) break; | ||
_ref6 = _iterator4[_i4++]; | ||
} else { | ||
_i5 = _iterator5.next(); | ||
if (_i5.done) break; | ||
_ref9 = _i5.value; | ||
_i4 = _iterator4.next(); | ||
if (_i4.done) break; | ||
_ref6 = _i4.value; | ||
} | ||
var point = _ref9; | ||
var point = _ref6; | ||
@@ -672,5 +453,5 @@ _this.canvasWrapper.removeChild(point); | ||
_defineProperty(this, "updateTooltipPoints", function (xIndex, xRatio) { | ||
var _this$state7 = _this.state, | ||
maxY = _this$state7.maxY, | ||
y = _this$state7.y; | ||
var _this$state5 = _this.state, | ||
maxY = _this$state5.maxY, | ||
y = _this$state5.y; | ||
@@ -682,9 +463,14 @@ if (!_this.tooltipPoints) { | ||
var i = 0; | ||
var j = 0; | ||
while (i < _this.tooltipPoints.length) { | ||
var point = _this.tooltipPoints[i]; | ||
var _y = y[i].points[xIndex]; | ||
var yRatio = _y / maxY; | ||
point.style.left = "".concat(xRatio * 100, "%"); | ||
point.style.bottom = "".concat(yRatio * 100, "%"); | ||
while (i < y.length) { | ||
if (y[i].isShown) { | ||
var point = _this.tooltipPoints[j]; | ||
var _y = y[i].points[xIndex]; | ||
var yRatio = _y / maxY; | ||
point.style.left = "".concat(xRatio * 100, "%"); | ||
point.style.bottom = "".concat(yRatio * 100, "%"); | ||
j++; | ||
} | ||
i++; | ||
@@ -699,6 +485,6 @@ } | ||
canvasWidth: 512, | ||
precisionFactor: Math.pow(10, options.precision || 3), | ||
precisionFactor: Math.pow(10, props.precision || 3), | ||
months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], | ||
weekdays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] | ||
}, options); | ||
}, props); | ||
this.rootNode = rootNode; | ||
@@ -721,3 +507,3 @@ this.data = _objectSpread({}, data, { | ||
this.rootNode.classList.add('chartogram'); | ||
this.rootNode.innerHTML = "\n\t\t\t<header class=\"chartogram__header\">\n\t\t\t\t<h1 class=\"chartogram__title\">".concat(this.props.title, "</h1>\n\t\t\t</header>\n\t\t\t<div class=\"chartogram__plan-with-axes\">\n\t\t\t\t<div class=\"chartogram__plan\">\n\t\t\t\t\t<div class=\"chartogram__top-border\"></div>\n\t\t\t\t\t<div class=\"chartogram__canvas-wrapper\">\n\t\t\t\t\t\t<svg class=\"chartogram__canvas\"></svg>\n\t\t\t\t\t\t<div class=\"chartogram__x\"></div>\n\t\t\t\t\t\t<div class=\"chartogram__y-wrapper\">\n\t\t\t\t\t\t\t<div class=\"chartogram__y\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"chartogram__timeline\">\n\t\t\t\t<div class=\"chartogram__timeline-canvas-padding\">\n\t\t\t\t\t<svg class=\"chartogram__timeline-canvas\" preserveAspectRatio=\"none\"></svg>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"chartogram__timeline-overlay-left\"></div>\n\t\t\t\t<div class=\"chartogram__timeline-overlay-right\"></div>\n\t\t\t\t<div class=\"chartogram__timeline-window\">\n\t\t\t\t\t<button type=\"button\" class=\"chartogram__reset-button chartogram__timeline-window__drag\"></button>\n\t\t\t\t\t<button type=\"button\" class=\"chartogram__reset-button chartogram__timeline-window__left-handle\"></button>\n\t\t\t\t\t<button type=\"button\" class=\"chartogram__reset-button chartogram__timeline-window__right-handle\"></button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"chartogram__chart-togglers\"></div>\n\t\t"); | ||
this.rootNode.innerHTML = "\n\t\t\t<header class=\"chartogram__header\">\n\t\t\t\t<h1 class=\"chartogram__title\">".concat(this.props.title, "</h1>\n\t\t\t</header>\n\t\t\t<div class=\"chartogram__plan-with-axes\">\n\t\t\t\t<div class=\"chartogram__plan\">\n\t\t\t\t\t<div class=\"chartogram__top-border\"></div>\n\t\t\t\t\t<div class=\"chartogram__canvas-wrapper\">\n\t\t\t\t\t\t<svg class=\"chartogram__canvas\"></svg>\n\t\t\t\t\t\t<div class=\"chartogram__x\"></div>\n\t\t\t\t\t\t<div class=\"chartogram__y-wrapper\">\n\t\t\t\t\t\t\t<div class=\"chartogram__y\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t").concat(_Timeline.default.INITIAL_MARKUP, "\n\t\t\t").concat(_Togglers.default.INITIAL_MARKUP, "\n\t\t"); | ||
this.tooltipContainer = this.rootNode.querySelector('.chartogram__plan'); | ||
@@ -728,39 +514,12 @@ this.canvas = this.rootNode.querySelector('.chartogram__canvas'); | ||
this.yAxis = this.rootNode.querySelector('.chartogram__y'); | ||
this.timeline = this.rootNode.querySelector('.chartogram__timeline'); | ||
this.timelineOverlayLeft = this.rootNode.querySelector('.chartogram__timeline-overlay-left'); | ||
this.timelineWindowLeftHandle = this.rootNode.querySelector('.chartogram__timeline-window__left-handle'); | ||
this.timelineWindow = this.rootNode.querySelector('.chartogram__timeline-window'); | ||
this.timelineWindowDrag = this.rootNode.querySelector('.chartogram__timeline-window__drag'); | ||
this.timelineWindowRightHandle = this.rootNode.querySelector('.chartogram__timeline-window__right-handle'); | ||
this.timelineOverlayRight = this.rootNode.querySelector('.chartogram__timeline-overlay-right'); | ||
this.timelineCanvas = this.rootNode.querySelector('.chartogram__timeline-canvas'); | ||
this.setUpTimelineWindowHandle('left'); | ||
this.setUpTimelineWindowHandle('right'); | ||
this.setUpTimelineWindow(); | ||
this.setUpCanvasTooltipListener(); // Add graph togglers. | ||
this.setUpCanvasTooltipListener(); // Render will be called after `.componentDidMount()`. | ||
var graphTogglers = this.rootNode.querySelector('.chartogram__chart-togglers'); | ||
(0, _utility.clearElement)(graphTogglers); | ||
for (var _iterator6 = this.data.y, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { | ||
var _ref10; | ||
if (_isArray6) { | ||
if (_i6 >= _iterator6.length) break; | ||
_ref10 = _iterator6[_i6++]; | ||
} else { | ||
_i6 = _iterator6.next(); | ||
if (_i6.done) break; | ||
_ref10 = _i6.value; | ||
} | ||
var y = _ref10; | ||
graphTogglers.appendChild(this.createGraphToggler(y)); | ||
} // Render will be called after `.componentDidMount()`. | ||
this.state = this.getInitialState(); | ||
this.updateTimelineBounds(this.state.fromRatio, this.state.toRatio); // Add window resize event listener. | ||
this.timeline = new _Timeline.default(this.getTimelineProps()); | ||
this.timeline.componentDidMount(); | ||
this.togglers = new _Togglers.default(this.getTogglersProps()); | ||
this.togglers.componentDidMount(); // Add window resize event listener. | ||
window.addEventListener('resize', this.onResizeThrottled); | ||
this.render(); | ||
} | ||
@@ -770,3 +529,5 @@ }, { | ||
value: function componentWillUnmount() { | ||
// Remove window resize event listener. | ||
this.rootNode.classList.remove('chartogram'); | ||
(0, _utility.clearElement)(this.rootNode); // Remove window resize event listener. | ||
window.removeEventListener('resize', this.onResizeThrottled); | ||
@@ -781,20 +542,70 @@ } | ||
}, { | ||
key: "getTimelineCanvasAspectRatio", | ||
value: function getTimelineCanvasAspectRatio() { | ||
var timelineCanvasDimensions = this.timelineCanvas.getBoundingClientRect(); | ||
return timelineCanvasDimensions.width / timelineCanvasDimensions.height; | ||
} | ||
}, { | ||
key: "setState", | ||
value: function setState(newState, renderTimeline) { | ||
value: function setState(newState) { | ||
var renderTimeline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
this.state = _objectSpread({}, this.state, newState); | ||
this.render(renderTimeline); | ||
this.render(); | ||
if (renderTimeline) { | ||
this.timeline.componentDidUpdate(this.getTimelineProps()); | ||
} | ||
} | ||
}, { | ||
key: "getTimelineProps", | ||
value: function getTimelineProps() { | ||
return { | ||
rootNode: this.rootNode, | ||
data: this.data, | ||
canvasWidth: this.props.canvasWidth, | ||
precisionFactor: this.props.precisionFactor, | ||
fromRatio: this.state.fromRatio, | ||
toRatio: this.state.toRatio, | ||
minYGlobal: this.state.minYGlobal, | ||
maxYGlobal: this.state.maxYGlobal, | ||
y: this.state.y, | ||
yScale: this.state.yScale, | ||
onChangeBounds: this.onChangeBounds | ||
}; | ||
} | ||
}, { | ||
key: "getTogglersProps", | ||
value: function getTogglersProps() { | ||
var _this2 = this; | ||
return { | ||
rootNode: this.rootNode, | ||
data: this.data, | ||
onToggle: function onToggle(id) { | ||
var y = _this2.state.y.find(function (_) { | ||
return _.id === id; | ||
}); // Won't allow hiding all graphs. | ||
if (y.isShown) { | ||
var graphsShown = _this2.state.y.filter(function (_) { | ||
return _.isShown; | ||
}); | ||
if (graphsShown.length === 1) { | ||
return; | ||
} | ||
} | ||
y.isShown = !y.isShown; | ||
_this2.setState(_objectSpread({ | ||
y: _this2.state.y | ||
}, _this2.calculateMinMaxY(_this2.state.y))); | ||
return true; | ||
} | ||
}; | ||
} | ||
}, { | ||
key: "getInitialState", | ||
value: function getInitialState() { | ||
var timelineWindowSize = this.props.timelineWindowSize; | ||
var _this$data3 = this.data, | ||
minX = _this$data3.minX, | ||
maxX = _this$data3.maxX; | ||
var _this$data = this.data, | ||
minX = _this$data.minX, | ||
maxX = _this$data.maxX; | ||
var fromIndex; | ||
@@ -813,3 +624,2 @@ | ||
aspectRatio: this.getCanvasAspectRatio(), | ||
timelineAspectRatio: this.getTimelineCanvasAspectRatio(), | ||
yScale: 1 | ||
@@ -821,3 +631,3 @@ }); | ||
value: function createState(fromRatio, toRatio) { | ||
var _this2 = this; | ||
var _this3 = this; | ||
@@ -861,3 +671,3 @@ var x = this.data.x; | ||
var y = this.data.y.map(function (y, i) { | ||
var points = _this2.data.y[i].points.slice(fromIndex, toIndex + 1); | ||
var points = _this3.data.y[i].points.slice(fromIndex, toIndex + 1); | ||
@@ -868,5 +678,5 @@ var graphPoints = points.slice(); | ||
if (x.points[fromIndex] !== minX) { | ||
var beforeStartY = _this2.data.y[i].points[fromIndex]; | ||
var startY = _this2.data.y[i].points[fromIndex + 1]; | ||
var fromXExcludedTickRatio = (minX - _this2.data.x.points[fromIndex]) / (_this2.data.x.points[fromIndex + 1] - _this2.data.x.points[fromIndex]); | ||
var beforeStartY = _this3.data.y[i].points[fromIndex]; | ||
var startY = _this3.data.y[i].points[fromIndex + 1]; | ||
var fromXExcludedTickRatio = (minX - _this3.data.x.points[fromIndex]) / (_this3.data.x.points[fromIndex + 1] - _this3.data.x.points[fromIndex]); | ||
var startPoint = beforeStartY + (startY - beforeStartY) * fromXExcludedTickRatio; | ||
@@ -877,5 +687,5 @@ graphPoints[0] = startPoint; | ||
if (x.points[toIndex] !== maxX) { | ||
var afterEndY = _this2.data.y[i].points[toIndex]; | ||
var endY = _this2.data.y[i].points[toIndex - 1]; | ||
var toXIncludedTickRatio = (maxX - _this2.data.x.points[toIndex - 1]) / (_this2.data.x.points[toIndex] - _this2.data.x.points[toIndex - 1]); | ||
var afterEndY = _this3.data.y[i].points[toIndex]; | ||
var endY = _this3.data.y[i].points[toIndex - 1]; | ||
var toXIncludedTickRatio = (maxX - _this3.data.x.points[toIndex - 1]) / (_this3.data.x.points[toIndex] - _this3.data.x.points[toIndex - 1]); | ||
var endPoint = endY + (afterEndY - endY) * toXIncludedTickRatio; | ||
@@ -886,3 +696,3 @@ graphPoints[graphPoints.length - 1] = endPoint; | ||
return _objectSpread({}, _this2.data.y[i], _this2.state ? _this2.state.y[i] : { | ||
return _objectSpread({}, _this3.data.y[i], _this3.state ? _this3.state.y[i] : { | ||
isShown: true | ||
@@ -914,19 +724,19 @@ }, { | ||
value: function calculateMinMaxY(y) { | ||
// Calculate timeline min/max Y for the graphs being shown. | ||
// Calculate visible min/max Y for the graphs being shown. | ||
var minY = Infinity; | ||
var maxY = -Infinity; | ||
for (var _iterator7 = y, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { | ||
var _ref11; | ||
for (var _iterator5 = y, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { | ||
var _ref7; | ||
if (_isArray7) { | ||
if (_i7 >= _iterator7.length) break; | ||
_ref11 = _iterator7[_i7++]; | ||
if (_isArray5) { | ||
if (_i5 >= _iterator5.length) break; | ||
_ref7 = _iterator5[_i5++]; | ||
} else { | ||
_i7 = _iterator7.next(); | ||
if (_i7.done) break; | ||
_ref11 = _i7.value; | ||
_i5 = _iterator5.next(); | ||
if (_i5.done) break; | ||
_ref7 = _i5.value; | ||
} | ||
var _y = _ref11; | ||
var _y = _ref7; | ||
@@ -937,21 +747,19 @@ if (_y.isShown) { | ||
} | ||
} // Min Y is always 0 by design. | ||
} // Calculate global min/max Y for the graphs being shown. | ||
minY = 0; // Calculate global min/max Y for the graphs being shown. | ||
var minYGlobal = Infinity; | ||
var maxYGlobal = -Infinity; | ||
var _loop2 = function _loop2() { | ||
if (_isArray8) { | ||
if (_i8 >= _iterator8.length) return "break"; | ||
_ref12 = _iterator8[_i8++]; | ||
var _loop = function _loop() { | ||
if (_isArray6) { | ||
if (_i6 >= _iterator6.length) return "break"; | ||
_ref8 = _iterator6[_i6++]; | ||
} else { | ||
_i8 = _iterator8.next(); | ||
if (_i8.done) return "break"; | ||
_ref12 = _i8.value; | ||
_i6 = _iterator6.next(); | ||
if (_i6.done) return "break"; | ||
_ref8 = _i6.value; | ||
} | ||
var _y = _ref12; | ||
var _y = _ref8; | ||
var isShown = y.find(function (_) { | ||
@@ -967,8 +775,8 @@ return _.id === _y.id; | ||
for (var _iterator8 = this.data.y, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { | ||
var _ref12; | ||
for (var _iterator6 = this.data.y, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { | ||
var _ref8; | ||
var _ret2 = _loop2(); | ||
var _ret = _loop(); | ||
if (_ret2 === "break") break; | ||
if (_ret === "break") break; | ||
} // Min Y is always 0 by design. | ||
@@ -986,14 +794,2 @@ | ||
}, { | ||
key: "updateTimelineBounds", | ||
value: function updateTimelineBounds(from, to) { | ||
this.setTimelineWindowLeft(from); | ||
this.setTimelineWindowRight(to); | ||
} | ||
}, { | ||
key: "updateBounds", | ||
value: function updateBounds(from, to) { | ||
this.updateTimelineBounds(from, to); | ||
this.setState(this.createState(from, to), false); | ||
} | ||
}, { | ||
key: "createPolylinePoints", | ||
@@ -1008,16 +804,15 @@ value: function createPolylinePoints(x, y) { | ||
value: function render() { | ||
var _this3 = this; | ||
var _this4 = this; | ||
var renderTimeline = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
var _this$props3 = this.props, | ||
canvasWidth = _this$props3.canvasWidth, | ||
gaugeTickMarksCount = _this$props3.gaugeTickMarksCount; | ||
var _this$state8 = this.state, | ||
minX = _this$state8.minX, | ||
maxX = _this$state8.maxX, | ||
minY = _this$state8.minY, | ||
maxY = _this$state8.maxY, | ||
yScale = _this$state8.yScale, | ||
xGraphPoints = _this$state8.xGraphPoints, | ||
aspectRatio = _this$state8.aspectRatio; // Clear canvas. | ||
var _this$state6 = this.state, | ||
minX = _this$state6.minX, | ||
maxX = _this$state6.maxX, | ||
minY = _this$state6.minY, | ||
maxY = _this$state6.maxY, | ||
yScale = _this$state6.yScale, | ||
xGraphPoints = _this$state6.xGraphPoints, | ||
aspectRatio = _this$state6.aspectRatio; // Clear canvas. | ||
@@ -1033,15 +828,15 @@ (0, _utility.clearElement)(this.canvas); // Set canvas `viewBox`. | ||
for (var _iterator9 = yAxisTickMarks, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) { | ||
var _ref13; | ||
for (var _iterator7 = yAxisTickMarks, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { | ||
var _ref9; | ||
if (_isArray9) { | ||
if (_i9 >= _iterator9.length) break; | ||
_ref13 = _iterator9[_i9++]; | ||
if (_isArray7) { | ||
if (_i7 >= _iterator7.length) break; | ||
_ref9 = _iterator7[_i7++]; | ||
} else { | ||
_i9 = _iterator9.next(); | ||
if (_i9.done) break; | ||
_ref13 = _i9.value; | ||
_i7 = _iterator7.next(); | ||
if (_i7.done) break; | ||
_ref9 = _i7.value; | ||
} | ||
var y = _ref13; | ||
var y = _ref9; | ||
this.canvas.appendChild(this.createGridLine(y)); | ||
@@ -1051,18 +846,18 @@ } // Draw charts. | ||
for (var _iterator10 = this.state.y, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) { | ||
var _ref14; | ||
for (var _iterator8 = this.state.y, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { | ||
var _ref10; | ||
if (_isArray10) { | ||
if (_i10 >= _iterator10.length) break; | ||
_ref14 = _iterator10[_i10++]; | ||
if (_isArray8) { | ||
if (_i8 >= _iterator8.length) break; | ||
_ref10 = _iterator8[_i8++]; | ||
} else { | ||
_i10 = _iterator10.next(); | ||
if (_i10.done) break; | ||
_ref14 = _i10.value; | ||
_i8 = _iterator8.next(); | ||
if (_i8.done) break; | ||
_ref10 = _i8.value; | ||
} | ||
var _ref15 = _ref14, | ||
color = _ref15.color, | ||
graphPoints = _ref15.graphPoints, | ||
isShown = _ref15.isShown; | ||
var _ref11 = _ref10, | ||
color = _ref11.color, | ||
graphPoints = _ref11.graphPoints, | ||
isShown = _ref11.isShown; | ||
@@ -1074,3 +869,3 @@ // Draw chart. | ||
graph.setAttribute('points', this.createPolylinePoints(xGraphPoints.map(this.mapX), graphPoints.map(function (y) { | ||
return _this3.mapY(maxY - y * yScale); | ||
return _this4.mapY(maxY - y * yScale); | ||
})).join(' ')); | ||
@@ -1086,7 +881,3 @@ graph.classList.add('chartogram__graph'); | ||
this.drawGauges(minX, maxX, minY_, maxY_, yAxisScale); // Draw timeline graph. | ||
if (renderTimeline) { | ||
this.renderTimeline(); | ||
} | ||
this.drawGauges(minX, maxX, minY_, maxY_, yAxisScale); | ||
} // function animateScale(scale) { | ||
@@ -1093,0 +884,0 @@ // console.log(scale) |
@@ -15,3 +15,2 @@ "use strict"; | ||
chartogram.componentDidMount(); | ||
chartogram.render(); | ||
return function () { | ||
@@ -18,0 +17,0 @@ chartogram.componentWillUnmount(); |
@@ -11,10 +11,2 @@ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -28,3 +20,5 @@ | ||
import { clearElement, commaJoin, getLowerSiblingDivisibleBy, divideInterval, renderGaugeLabels, throttle, simplifyGraph, setUpDrag } from './utility'; | ||
import { clearElement, commaJoin, getLowerSiblingDivisibleBy, divideInterval, throttle, renderGaugeLabels } from './utility'; | ||
import Timeline from './Timeline'; | ||
import Togglers from './Togglers'; | ||
@@ -38,3 +32,3 @@ var Chartogram = | ||
var title = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'Title'; | ||
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
var props = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
@@ -45,5 +39,4 @@ _classCallCheck(this, Chartogram); | ||
_this.setState({ | ||
aspectRatio: _this.getCanvasAspectRatio(), | ||
timelineAspectRatio: _this.getTimelineCanvasAspectRatio() | ||
}); | ||
aspectRatio: _this.getCanvasAspectRatio() | ||
}, false); | ||
}); | ||
@@ -53,2 +46,6 @@ | ||
_defineProperty(this, "onChangeBounds", function (from, to) { | ||
_this.setState(_this.createState(from, to), false); | ||
}); | ||
_defineProperty(this, "fixSvgCoordinate", function (x) { | ||
@@ -76,26 +73,9 @@ var precisionFactor = _this.props.precisionFactor; | ||
_defineProperty(this, "mapXForTimeline", function (x) { | ||
var canvasWidth = _this.props.canvasWidth; | ||
var _this$data = _this.data, | ||
minX = _this$data.minX, | ||
maxX = _this$data.maxX; | ||
return (x - minX) / (maxX - minX) * canvasWidth; | ||
}); | ||
_defineProperty(this, "mapYForTimeline", function (y) { | ||
var canvasWidth = _this.props.canvasWidth; | ||
_defineProperty(this, "createGridLine", function (y) { | ||
var _this$state3 = _this.state, | ||
minYGlobal = _this$state3.minYGlobal, | ||
maxYGlobal = _this$state3.maxYGlobal, | ||
timelineAspectRatio = _this$state3.timelineAspectRatio; | ||
return (y - minYGlobal) / (maxYGlobal - minYGlobal) * canvasWidth / timelineAspectRatio; | ||
}); | ||
_defineProperty(this, "createGridLine", function (y) { | ||
var _this$state4 = _this.state, | ||
minX = _this$state4.minX, | ||
maxX = _this$state4.maxX, | ||
minY = _this$state4.minY, | ||
maxY = _this$state4.maxY, | ||
yScale = _this$state4.yScale; | ||
minX = _this$state3.minX, | ||
maxX = _this$state3.maxX, | ||
minY = _this$state3.minY, | ||
maxY = _this$state3.maxY, | ||
yScale = _this$state3.yScale; | ||
var line = document.createElement('line'); | ||
@@ -124,205 +104,2 @@ line.classList.add('chartogram__grid-line'); | ||
_defineProperty(this, "renderTimeline", function () { | ||
var canvasWidth = _this.props.canvasWidth; | ||
var _this$data2 = _this.data, | ||
x = _this$data2.x, | ||
y = _this$data2.y; | ||
var _this$state5 = _this.state, | ||
timelineAspectRatio = _this$state5.timelineAspectRatio, | ||
maxYGlobal = _this$state5.maxYGlobal, | ||
yScale = _this$state5.yScale; // Clear canvas. | ||
clearElement(_this.timelineCanvas); // Set canvas `viewBox`. | ||
_this.timelineCanvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(_this.fixSvgCoordinate(canvasWidth / timelineAspectRatio))); | ||
var _loop = function _loop() { | ||
if (_isArray) { | ||
if (_i >= _iterator.length) return "break"; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i = _iterator.next(); | ||
if (_i.done) return "break"; | ||
_ref = _i.value; | ||
} | ||
var _ref2 = _ref, | ||
id = _ref2.id, | ||
color = _ref2.color, | ||
points = _ref2.points; | ||
var isShown = _this.state.y.find(function (_) { | ||
return _.id === id; | ||
}).isShown; | ||
if (isShown) { | ||
var _simplifyGraph = simplifyGraph(x.points, points, 80), | ||
_simplifyGraph2 = _slicedToArray(_simplifyGraph, 2), | ||
_x = _simplifyGraph2[0], | ||
_y = _simplifyGraph2[1]; | ||
var graph = document.createElement('polyline'); | ||
graph.setAttribute('stroke', color); | ||
graph.setAttribute('points', _this.createPolylinePoints(_x.map(_this.mapXForTimeline), _y.map(function (y) { | ||
return _this.mapYForTimeline(maxYGlobal - y * yScale); | ||
})).join(' ')); | ||
graph.classList.add('chartogram__graph'); | ||
_this.timelineCanvas.appendChild(graph); | ||
} | ||
}; | ||
for (var _iterator = y, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
var _ret = _loop(); | ||
if (_ret === "break") break; | ||
} // A workaround to fix WebKit bug when it's not re-rendering the <svg/>. | ||
// https://stackoverflow.com/questions/30905493/how-to-force-webkit-to-update-svg-use-elements-after-changes-to-original | ||
_this.timelineCanvas.innerHTML += ''; | ||
}); | ||
_defineProperty(this, "createGraphToggler", function (_ref3) { | ||
var id = _ref3.id, | ||
name = _ref3.name, | ||
color = _ref3.color; | ||
var toggler = document.createElement('button'); | ||
toggler.setAttribute('type', 'button'); | ||
toggler.classList.add('chartogram__chart-toggler'); | ||
toggler.classList.add('chartogram__chart-toggler--on'); | ||
toggler.classList.add('chartogram__reset-button'); // Add check. | ||
var xmlns = 'http://www.w3.org/2000/svg'; | ||
var check = document.createElementNS(xmlns, 'svg'); | ||
check.setAttribute('viewBox', '0 0 19 19'); | ||
check.setAttribute('class', 'chartogram__chart-toggler-check'); // Add background circle. | ||
var backgroundCircle = document.createElementNS(xmlns, 'circle'); | ||
backgroundCircle.setAttribute('cx', '9.5'); | ||
backgroundCircle.setAttribute('cy', '9.5'); | ||
backgroundCircle.setAttribute('r', '9.5'); | ||
backgroundCircle.setAttribute('fill', color); | ||
check.appendChild(backgroundCircle); // Add check circle. | ||
var checkCircle = document.createElementNS(xmlns, 'circle'); | ||
checkCircle.setAttribute('cx', '9.5'); | ||
checkCircle.setAttribute('cy', '9.5'); | ||
checkCircle.setAttribute('r', '8'); | ||
checkCircle.setAttribute('class', 'chartogram__chart-toggler-check-circle'); | ||
check.appendChild(checkCircle); // Add check mark. | ||
var checkMark = document.createElementNS(xmlns, 'path'); | ||
checkMark.setAttribute('d', 'M13.64 4.94l-6.2 6.34-1.69-1.9c-.73-.63-1.89.1-1.36 1.06l2 3.38c.3.43 1.04.85 1.78 0 .32-.42 6.31-7.93 6.31-7.93.74-.84-.2-1.58-.84-.95z'); | ||
checkMark.setAttribute('fill', 'white'); | ||
checkMark.setAttribute('class', 'chartogram__chart-toggler-check-mark'); | ||
check.appendChild(checkMark); // Add checkmark. | ||
toggler.appendChild(check); // Add graph name. | ||
toggler.appendChild(document.createTextNode(name)); // On click. | ||
toggler.addEventListener('click', function () { | ||
var y = _this.state.y.find(function (_) { | ||
return _.id === id; | ||
}); // Won't allow hiding all graphs. | ||
if (y.isShown) { | ||
var graphsShown = _this.state.y.filter(function (_) { | ||
return _.isShown; | ||
}); | ||
if (graphsShown.length === 1) { | ||
return; | ||
} | ||
} | ||
y.isShown = !y.isShown; | ||
_this.setState(_objectSpread({}, _this.state, _this.calculateMinMaxY(_this.state.y))); | ||
toggler.classList.toggle('chartogram__chart-toggler--on'); | ||
}); | ||
return toggler; | ||
}); | ||
_defineProperty(this, "setUpTimelineWindowHandle", function (side) { | ||
var handle = side === 'left' ? _this.timelineWindowLeftHandle : _this.timelineWindowRightHandle; | ||
var handleWidth = parseFloat(getComputedStyle(_this.timelineWindow).borderLeftWidth); | ||
var timelineCoordinates; | ||
var minX; | ||
var maxX; | ||
var deltaX; | ||
var startedX; | ||
var onDrag = function onDrag(x) { | ||
x -= deltaX; | ||
x = Math.max(Math.min(x, maxX), minX); | ||
var ratio = (x - timelineCoordinates.left) / timelineCoordinates.width; | ||
if (side === 'left') { | ||
_this.updateBounds(ratio, _this.state.toRatio); | ||
} else { | ||
_this.updateBounds(_this.state.fromRatio, ratio); | ||
} | ||
}; | ||
var onDragStart = function onDragStart(x) { | ||
timelineCoordinates = _this.timeline.getBoundingClientRect(); | ||
var timelineWindowCoordinates = _this.timelineWindow.getBoundingClientRect(); | ||
if (side === 'left') { | ||
minX = timelineCoordinates.left; | ||
maxX = timelineWindowCoordinates.left + timelineWindowCoordinates.width - 2 * handleWidth; | ||
deltaX = x - timelineWindowCoordinates.left; | ||
} else { | ||
minX = timelineWindowCoordinates.left + 2 * handleWidth; | ||
maxX = timelineCoordinates.left + timelineCoordinates.width; | ||
deltaX = x - (timelineWindowCoordinates.left + timelineWindowCoordinates.width); | ||
} | ||
}; | ||
return setUpDrag(handle, onDragStart, onDrag); | ||
}); | ||
_defineProperty(this, "setUpTimelineWindow", function () { | ||
var timelineCoordinates; | ||
var timelineWindowCoordinates; | ||
var minX; | ||
var maxX; | ||
var innerX; | ||
var onDrag = function onDrag(x) { | ||
x -= innerX; | ||
x = Math.max(Math.min(x, maxX), minX); | ||
var ratio = (x - timelineCoordinates.left) / timelineCoordinates.width; | ||
_this.updateBounds(ratio, ratio + timelineWindowCoordinates.width / timelineCoordinates.width); | ||
}; | ||
var onDragStart = function onDragStart(x) { | ||
timelineCoordinates = _this.timeline.getBoundingClientRect(); | ||
timelineWindowCoordinates = _this.timelineWindow.getBoundingClientRect(); | ||
innerX = x - timelineWindowCoordinates.left; | ||
minX = timelineCoordinates.left; | ||
maxX = timelineCoordinates.left + (timelineCoordinates.width - timelineWindowCoordinates.width); | ||
}; | ||
return setUpDrag(_this.timelineWindowDrag, onDragStart, onDrag); | ||
}); | ||
_defineProperty(this, "setTimelineWindowLeft", function (ratio) { | ||
_this.timelineOverlayLeft.style.right = "".concat(100 * (1 - ratio), "%"); | ||
_this.timelineWindow.style.left = "".concat(100 * ratio, "%"); | ||
}); | ||
_defineProperty(this, "setTimelineWindowRight", function (ratio) { | ||
_this.timelineOverlayRight.style.left = "".concat(100 * ratio, "%"); | ||
_this.timelineWindow.style.right = "".concat(100 * (1 - ratio), "%"); | ||
}); | ||
_defineProperty(this, "setUpCanvasTooltipListener", function () { | ||
@@ -336,7 +113,7 @@ var _this$props2 = _this.props, | ||
var onTrack = function onTrack(screenX) { | ||
var _this$state6 = _this.state, | ||
minX = _this$state6.minX, | ||
maxX = _this$state6.maxX, | ||
xPoints = _this$state6.xPoints, | ||
y = _this$state6.y; | ||
var _this$state4 = _this.state, | ||
minX = _this$state4.minX, | ||
maxX = _this$state4.maxX, | ||
xPoints = _this$state4.xPoints, | ||
y = _this$state4.y; | ||
var xScreenRatio = (screenX - canvasDimensions.left) / canvasDimensions.width; | ||
@@ -390,18 +167,18 @@ var xPoint = minX + xScreenRatio * (maxX - minX); | ||
for (var _iterator2 = y, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | ||
var _ref4; | ||
for (var _iterator = y, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { | ||
var _ref; | ||
if (_isArray2) { | ||
if (_i2 >= _iterator2.length) break; | ||
_ref4 = _iterator2[_i2++]; | ||
if (_isArray) { | ||
if (_i >= _iterator.length) break; | ||
_ref = _iterator[_i++]; | ||
} else { | ||
_i2 = _iterator2.next(); | ||
if (_i2.done) break; | ||
_ref4 = _i2.value; | ||
_i = _iterator.next(); | ||
if (_i.done) break; | ||
_ref = _i.value; | ||
} | ||
var _ref5 = _ref4, | ||
isShown = _ref5.isShown, | ||
points = _ref5.points, | ||
name = _ref5.name; | ||
var _ref2 = _ref, | ||
isShown = _ref2.isShown, | ||
points = _ref2.points, | ||
name = _ref2.name; | ||
@@ -533,17 +310,17 @@ if (isShown) { | ||
for (var _iterator3 = y, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
var _ref6; | ||
for (var _iterator2 = y, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { | ||
var _ref3; | ||
if (_isArray3) { | ||
if (_i3 >= _iterator3.length) break; | ||
_ref6 = _iterator3[_i3++]; | ||
if (_isArray2) { | ||
if (_i2 >= _iterator2.length) break; | ||
_ref3 = _iterator2[_i2++]; | ||
} else { | ||
_i3 = _iterator3.next(); | ||
if (_i3.done) break; | ||
_ref6 = _i3.value; | ||
_i2 = _iterator2.next(); | ||
if (_i2.done) break; | ||
_ref3 = _i2.value; | ||
} | ||
var _ref7 = _ref6, | ||
isShown = _ref7.isShown, | ||
color = _ref7.color; | ||
var _ref4 = _ref3, | ||
isShown = _ref4.isShown, | ||
color = _ref4.color; | ||
@@ -598,15 +375,15 @@ if (isShown) { | ||
for (var _iterator4 = _this.state.y, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | ||
var _ref8; | ||
for (var _iterator3 = _this.state.y, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
var _ref5; | ||
if (_isArray4) { | ||
if (_i4 >= _iterator4.length) break; | ||
_ref8 = _iterator4[_i4++]; | ||
if (_isArray3) { | ||
if (_i3 >= _iterator3.length) break; | ||
_ref5 = _iterator3[_i3++]; | ||
} else { | ||
_i4 = _iterator4.next(); | ||
if (_i4.done) break; | ||
_ref8 = _i4.value; | ||
_i3 = _iterator3.next(); | ||
if (_i3.done) break; | ||
_ref5 = _i3.value; | ||
} | ||
var y = _ref8; | ||
var y = _ref5; | ||
@@ -626,15 +403,15 @@ if (y.isShown) { | ||
_defineProperty(this, "removeTooltipPoints", function () { | ||
for (var _iterator5 = _this.tooltipPoints, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { | ||
var _ref9; | ||
for (var _iterator4 = _this.tooltipPoints, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) { | ||
var _ref6; | ||
if (_isArray5) { | ||
if (_i5 >= _iterator5.length) break; | ||
_ref9 = _iterator5[_i5++]; | ||
if (_isArray4) { | ||
if (_i4 >= _iterator4.length) break; | ||
_ref6 = _iterator4[_i4++]; | ||
} else { | ||
_i5 = _iterator5.next(); | ||
if (_i5.done) break; | ||
_ref9 = _i5.value; | ||
_i4 = _iterator4.next(); | ||
if (_i4.done) break; | ||
_ref6 = _i4.value; | ||
} | ||
var point = _ref9; | ||
var point = _ref6; | ||
@@ -665,5 +442,5 @@ _this.canvasWrapper.removeChild(point); | ||
_defineProperty(this, "updateTooltipPoints", function (xIndex, xRatio) { | ||
var _this$state7 = _this.state, | ||
maxY = _this$state7.maxY, | ||
y = _this$state7.y; | ||
var _this$state5 = _this.state, | ||
maxY = _this$state5.maxY, | ||
y = _this$state5.y; | ||
@@ -675,9 +452,14 @@ if (!_this.tooltipPoints) { | ||
var i = 0; | ||
var j = 0; | ||
while (i < _this.tooltipPoints.length) { | ||
var point = _this.tooltipPoints[i]; | ||
var _y = y[i].points[xIndex]; | ||
var yRatio = _y / maxY; | ||
point.style.left = "".concat(xRatio * 100, "%"); | ||
point.style.bottom = "".concat(yRatio * 100, "%"); | ||
while (i < y.length) { | ||
if (y[i].isShown) { | ||
var point = _this.tooltipPoints[j]; | ||
var _y = y[i].points[xIndex]; | ||
var yRatio = _y / maxY; | ||
point.style.left = "".concat(xRatio * 100, "%"); | ||
point.style.bottom = "".concat(yRatio * 100, "%"); | ||
j++; | ||
} | ||
i++; | ||
@@ -692,6 +474,6 @@ } | ||
canvasWidth: 512, | ||
precisionFactor: Math.pow(10, options.precision || 3), | ||
precisionFactor: Math.pow(10, props.precision || 3), | ||
months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], | ||
weekdays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] | ||
}, options); | ||
}, props); | ||
this.rootNode = rootNode; | ||
@@ -714,3 +496,3 @@ this.data = _objectSpread({}, data, { | ||
this.rootNode.classList.add('chartogram'); | ||
this.rootNode.innerHTML = "\n\t\t\t<header class=\"chartogram__header\">\n\t\t\t\t<h1 class=\"chartogram__title\">".concat(this.props.title, "</h1>\n\t\t\t</header>\n\t\t\t<div class=\"chartogram__plan-with-axes\">\n\t\t\t\t<div class=\"chartogram__plan\">\n\t\t\t\t\t<div class=\"chartogram__top-border\"></div>\n\t\t\t\t\t<div class=\"chartogram__canvas-wrapper\">\n\t\t\t\t\t\t<svg class=\"chartogram__canvas\"></svg>\n\t\t\t\t\t\t<div class=\"chartogram__x\"></div>\n\t\t\t\t\t\t<div class=\"chartogram__y-wrapper\">\n\t\t\t\t\t\t\t<div class=\"chartogram__y\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"chartogram__timeline\">\n\t\t\t\t<div class=\"chartogram__timeline-canvas-padding\">\n\t\t\t\t\t<svg class=\"chartogram__timeline-canvas\" preserveAspectRatio=\"none\"></svg>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"chartogram__timeline-overlay-left\"></div>\n\t\t\t\t<div class=\"chartogram__timeline-overlay-right\"></div>\n\t\t\t\t<div class=\"chartogram__timeline-window\">\n\t\t\t\t\t<button type=\"button\" class=\"chartogram__reset-button chartogram__timeline-window__drag\"></button>\n\t\t\t\t\t<button type=\"button\" class=\"chartogram__reset-button chartogram__timeline-window__left-handle\"></button>\n\t\t\t\t\t<button type=\"button\" class=\"chartogram__reset-button chartogram__timeline-window__right-handle\"></button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"chartogram__chart-togglers\"></div>\n\t\t"); | ||
this.rootNode.innerHTML = "\n\t\t\t<header class=\"chartogram__header\">\n\t\t\t\t<h1 class=\"chartogram__title\">".concat(this.props.title, "</h1>\n\t\t\t</header>\n\t\t\t<div class=\"chartogram__plan-with-axes\">\n\t\t\t\t<div class=\"chartogram__plan\">\n\t\t\t\t\t<div class=\"chartogram__top-border\"></div>\n\t\t\t\t\t<div class=\"chartogram__canvas-wrapper\">\n\t\t\t\t\t\t<svg class=\"chartogram__canvas\"></svg>\n\t\t\t\t\t\t<div class=\"chartogram__x\"></div>\n\t\t\t\t\t\t<div class=\"chartogram__y-wrapper\">\n\t\t\t\t\t\t\t<div class=\"chartogram__y\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t").concat(Timeline.INITIAL_MARKUP, "\n\t\t\t").concat(Togglers.INITIAL_MARKUP, "\n\t\t"); | ||
this.tooltipContainer = this.rootNode.querySelector('.chartogram__plan'); | ||
@@ -721,39 +503,12 @@ this.canvas = this.rootNode.querySelector('.chartogram__canvas'); | ||
this.yAxis = this.rootNode.querySelector('.chartogram__y'); | ||
this.timeline = this.rootNode.querySelector('.chartogram__timeline'); | ||
this.timelineOverlayLeft = this.rootNode.querySelector('.chartogram__timeline-overlay-left'); | ||
this.timelineWindowLeftHandle = this.rootNode.querySelector('.chartogram__timeline-window__left-handle'); | ||
this.timelineWindow = this.rootNode.querySelector('.chartogram__timeline-window'); | ||
this.timelineWindowDrag = this.rootNode.querySelector('.chartogram__timeline-window__drag'); | ||
this.timelineWindowRightHandle = this.rootNode.querySelector('.chartogram__timeline-window__right-handle'); | ||
this.timelineOverlayRight = this.rootNode.querySelector('.chartogram__timeline-overlay-right'); | ||
this.timelineCanvas = this.rootNode.querySelector('.chartogram__timeline-canvas'); | ||
this.setUpTimelineWindowHandle('left'); | ||
this.setUpTimelineWindowHandle('right'); | ||
this.setUpTimelineWindow(); | ||
this.setUpCanvasTooltipListener(); // Add graph togglers. | ||
this.setUpCanvasTooltipListener(); // Render will be called after `.componentDidMount()`. | ||
var graphTogglers = this.rootNode.querySelector('.chartogram__chart-togglers'); | ||
clearElement(graphTogglers); | ||
for (var _iterator6 = this.data.y, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { | ||
var _ref10; | ||
if (_isArray6) { | ||
if (_i6 >= _iterator6.length) break; | ||
_ref10 = _iterator6[_i6++]; | ||
} else { | ||
_i6 = _iterator6.next(); | ||
if (_i6.done) break; | ||
_ref10 = _i6.value; | ||
} | ||
var y = _ref10; | ||
graphTogglers.appendChild(this.createGraphToggler(y)); | ||
} // Render will be called after `.componentDidMount()`. | ||
this.state = this.getInitialState(); | ||
this.updateTimelineBounds(this.state.fromRatio, this.state.toRatio); // Add window resize event listener. | ||
this.timeline = new Timeline(this.getTimelineProps()); | ||
this.timeline.componentDidMount(); | ||
this.togglers = new Togglers(this.getTogglersProps()); | ||
this.togglers.componentDidMount(); // Add window resize event listener. | ||
window.addEventListener('resize', this.onResizeThrottled); | ||
this.render(); | ||
} | ||
@@ -763,3 +518,5 @@ }, { | ||
value: function componentWillUnmount() { | ||
// Remove window resize event listener. | ||
this.rootNode.classList.remove('chartogram'); | ||
clearElement(this.rootNode); // Remove window resize event listener. | ||
window.removeEventListener('resize', this.onResizeThrottled); | ||
@@ -774,20 +531,70 @@ } | ||
}, { | ||
key: "getTimelineCanvasAspectRatio", | ||
value: function getTimelineCanvasAspectRatio() { | ||
var timelineCanvasDimensions = this.timelineCanvas.getBoundingClientRect(); | ||
return timelineCanvasDimensions.width / timelineCanvasDimensions.height; | ||
} | ||
}, { | ||
key: "setState", | ||
value: function setState(newState, renderTimeline) { | ||
value: function setState(newState) { | ||
var renderTimeline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
this.state = _objectSpread({}, this.state, newState); | ||
this.render(renderTimeline); | ||
this.render(); | ||
if (renderTimeline) { | ||
this.timeline.componentDidUpdate(this.getTimelineProps()); | ||
} | ||
} | ||
}, { | ||
key: "getTimelineProps", | ||
value: function getTimelineProps() { | ||
return { | ||
rootNode: this.rootNode, | ||
data: this.data, | ||
canvasWidth: this.props.canvasWidth, | ||
precisionFactor: this.props.precisionFactor, | ||
fromRatio: this.state.fromRatio, | ||
toRatio: this.state.toRatio, | ||
minYGlobal: this.state.minYGlobal, | ||
maxYGlobal: this.state.maxYGlobal, | ||
y: this.state.y, | ||
yScale: this.state.yScale, | ||
onChangeBounds: this.onChangeBounds | ||
}; | ||
} | ||
}, { | ||
key: "getTogglersProps", | ||
value: function getTogglersProps() { | ||
var _this2 = this; | ||
return { | ||
rootNode: this.rootNode, | ||
data: this.data, | ||
onToggle: function onToggle(id) { | ||
var y = _this2.state.y.find(function (_) { | ||
return _.id === id; | ||
}); // Won't allow hiding all graphs. | ||
if (y.isShown) { | ||
var graphsShown = _this2.state.y.filter(function (_) { | ||
return _.isShown; | ||
}); | ||
if (graphsShown.length === 1) { | ||
return; | ||
} | ||
} | ||
y.isShown = !y.isShown; | ||
_this2.setState(_objectSpread({ | ||
y: _this2.state.y | ||
}, _this2.calculateMinMaxY(_this2.state.y))); | ||
return true; | ||
} | ||
}; | ||
} | ||
}, { | ||
key: "getInitialState", | ||
value: function getInitialState() { | ||
var timelineWindowSize = this.props.timelineWindowSize; | ||
var _this$data3 = this.data, | ||
minX = _this$data3.minX, | ||
maxX = _this$data3.maxX; | ||
var _this$data = this.data, | ||
minX = _this$data.minX, | ||
maxX = _this$data.maxX; | ||
var fromIndex; | ||
@@ -806,3 +613,2 @@ | ||
aspectRatio: this.getCanvasAspectRatio(), | ||
timelineAspectRatio: this.getTimelineCanvasAspectRatio(), | ||
yScale: 1 | ||
@@ -814,3 +620,3 @@ }); | ||
value: function createState(fromRatio, toRatio) { | ||
var _this2 = this; | ||
var _this3 = this; | ||
@@ -854,3 +660,3 @@ var x = this.data.x; | ||
var y = this.data.y.map(function (y, i) { | ||
var points = _this2.data.y[i].points.slice(fromIndex, toIndex + 1); | ||
var points = _this3.data.y[i].points.slice(fromIndex, toIndex + 1); | ||
@@ -861,5 +667,5 @@ var graphPoints = points.slice(); | ||
if (x.points[fromIndex] !== minX) { | ||
var beforeStartY = _this2.data.y[i].points[fromIndex]; | ||
var startY = _this2.data.y[i].points[fromIndex + 1]; | ||
var fromXExcludedTickRatio = (minX - _this2.data.x.points[fromIndex]) / (_this2.data.x.points[fromIndex + 1] - _this2.data.x.points[fromIndex]); | ||
var beforeStartY = _this3.data.y[i].points[fromIndex]; | ||
var startY = _this3.data.y[i].points[fromIndex + 1]; | ||
var fromXExcludedTickRatio = (minX - _this3.data.x.points[fromIndex]) / (_this3.data.x.points[fromIndex + 1] - _this3.data.x.points[fromIndex]); | ||
var startPoint = beforeStartY + (startY - beforeStartY) * fromXExcludedTickRatio; | ||
@@ -870,5 +676,5 @@ graphPoints[0] = startPoint; | ||
if (x.points[toIndex] !== maxX) { | ||
var afterEndY = _this2.data.y[i].points[toIndex]; | ||
var endY = _this2.data.y[i].points[toIndex - 1]; | ||
var toXIncludedTickRatio = (maxX - _this2.data.x.points[toIndex - 1]) / (_this2.data.x.points[toIndex] - _this2.data.x.points[toIndex - 1]); | ||
var afterEndY = _this3.data.y[i].points[toIndex]; | ||
var endY = _this3.data.y[i].points[toIndex - 1]; | ||
var toXIncludedTickRatio = (maxX - _this3.data.x.points[toIndex - 1]) / (_this3.data.x.points[toIndex] - _this3.data.x.points[toIndex - 1]); | ||
var endPoint = endY + (afterEndY - endY) * toXIncludedTickRatio; | ||
@@ -879,3 +685,3 @@ graphPoints[graphPoints.length - 1] = endPoint; | ||
return _objectSpread({}, _this2.data.y[i], _this2.state ? _this2.state.y[i] : { | ||
return _objectSpread({}, _this3.data.y[i], _this3.state ? _this3.state.y[i] : { | ||
isShown: true | ||
@@ -907,19 +713,19 @@ }, { | ||
value: function calculateMinMaxY(y) { | ||
// Calculate timeline min/max Y for the graphs being shown. | ||
// Calculate visible min/max Y for the graphs being shown. | ||
var minY = Infinity; | ||
var maxY = -Infinity; | ||
for (var _iterator7 = y, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { | ||
var _ref11; | ||
for (var _iterator5 = y, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) { | ||
var _ref7; | ||
if (_isArray7) { | ||
if (_i7 >= _iterator7.length) break; | ||
_ref11 = _iterator7[_i7++]; | ||
if (_isArray5) { | ||
if (_i5 >= _iterator5.length) break; | ||
_ref7 = _iterator5[_i5++]; | ||
} else { | ||
_i7 = _iterator7.next(); | ||
if (_i7.done) break; | ||
_ref11 = _i7.value; | ||
_i5 = _iterator5.next(); | ||
if (_i5.done) break; | ||
_ref7 = _i5.value; | ||
} | ||
var _y = _ref11; | ||
var _y = _ref7; | ||
@@ -930,21 +736,19 @@ if (_y.isShown) { | ||
} | ||
} // Min Y is always 0 by design. | ||
} // Calculate global min/max Y for the graphs being shown. | ||
minY = 0; // Calculate global min/max Y for the graphs being shown. | ||
var minYGlobal = Infinity; | ||
var maxYGlobal = -Infinity; | ||
var _loop2 = function _loop2() { | ||
if (_isArray8) { | ||
if (_i8 >= _iterator8.length) return "break"; | ||
_ref12 = _iterator8[_i8++]; | ||
var _loop = function _loop() { | ||
if (_isArray6) { | ||
if (_i6 >= _iterator6.length) return "break"; | ||
_ref8 = _iterator6[_i6++]; | ||
} else { | ||
_i8 = _iterator8.next(); | ||
if (_i8.done) return "break"; | ||
_ref12 = _i8.value; | ||
_i6 = _iterator6.next(); | ||
if (_i6.done) return "break"; | ||
_ref8 = _i6.value; | ||
} | ||
var _y = _ref12; | ||
var _y = _ref8; | ||
var isShown = y.find(function (_) { | ||
@@ -960,8 +764,8 @@ return _.id === _y.id; | ||
for (var _iterator8 = this.data.y, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { | ||
var _ref12; | ||
for (var _iterator6 = this.data.y, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) { | ||
var _ref8; | ||
var _ret2 = _loop2(); | ||
var _ret = _loop(); | ||
if (_ret2 === "break") break; | ||
if (_ret === "break") break; | ||
} // Min Y is always 0 by design. | ||
@@ -979,14 +783,2 @@ | ||
}, { | ||
key: "updateTimelineBounds", | ||
value: function updateTimelineBounds(from, to) { | ||
this.setTimelineWindowLeft(from); | ||
this.setTimelineWindowRight(to); | ||
} | ||
}, { | ||
key: "updateBounds", | ||
value: function updateBounds(from, to) { | ||
this.updateTimelineBounds(from, to); | ||
this.setState(this.createState(from, to), false); | ||
} | ||
}, { | ||
key: "createPolylinePoints", | ||
@@ -1001,16 +793,15 @@ value: function createPolylinePoints(x, y) { | ||
value: function render() { | ||
var _this3 = this; | ||
var _this4 = this; | ||
var renderTimeline = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
var _this$props3 = this.props, | ||
canvasWidth = _this$props3.canvasWidth, | ||
gaugeTickMarksCount = _this$props3.gaugeTickMarksCount; | ||
var _this$state8 = this.state, | ||
minX = _this$state8.minX, | ||
maxX = _this$state8.maxX, | ||
minY = _this$state8.minY, | ||
maxY = _this$state8.maxY, | ||
yScale = _this$state8.yScale, | ||
xGraphPoints = _this$state8.xGraphPoints, | ||
aspectRatio = _this$state8.aspectRatio; // Clear canvas. | ||
var _this$state6 = this.state, | ||
minX = _this$state6.minX, | ||
maxX = _this$state6.maxX, | ||
minY = _this$state6.minY, | ||
maxY = _this$state6.maxY, | ||
yScale = _this$state6.yScale, | ||
xGraphPoints = _this$state6.xGraphPoints, | ||
aspectRatio = _this$state6.aspectRatio; // Clear canvas. | ||
@@ -1026,15 +817,15 @@ clearElement(this.canvas); // Set canvas `viewBox`. | ||
for (var _iterator9 = yAxisTickMarks, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) { | ||
var _ref13; | ||
for (var _iterator7 = yAxisTickMarks, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) { | ||
var _ref9; | ||
if (_isArray9) { | ||
if (_i9 >= _iterator9.length) break; | ||
_ref13 = _iterator9[_i9++]; | ||
if (_isArray7) { | ||
if (_i7 >= _iterator7.length) break; | ||
_ref9 = _iterator7[_i7++]; | ||
} else { | ||
_i9 = _iterator9.next(); | ||
if (_i9.done) break; | ||
_ref13 = _i9.value; | ||
_i7 = _iterator7.next(); | ||
if (_i7.done) break; | ||
_ref9 = _i7.value; | ||
} | ||
var y = _ref13; | ||
var y = _ref9; | ||
this.canvas.appendChild(this.createGridLine(y)); | ||
@@ -1044,18 +835,18 @@ } // Draw charts. | ||
for (var _iterator10 = this.state.y, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) { | ||
var _ref14; | ||
for (var _iterator8 = this.state.y, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) { | ||
var _ref10; | ||
if (_isArray10) { | ||
if (_i10 >= _iterator10.length) break; | ||
_ref14 = _iterator10[_i10++]; | ||
if (_isArray8) { | ||
if (_i8 >= _iterator8.length) break; | ||
_ref10 = _iterator8[_i8++]; | ||
} else { | ||
_i10 = _iterator10.next(); | ||
if (_i10.done) break; | ||
_ref14 = _i10.value; | ||
_i8 = _iterator8.next(); | ||
if (_i8.done) break; | ||
_ref10 = _i8.value; | ||
} | ||
var _ref15 = _ref14, | ||
color = _ref15.color, | ||
graphPoints = _ref15.graphPoints, | ||
isShown = _ref15.isShown; | ||
var _ref11 = _ref10, | ||
color = _ref11.color, | ||
graphPoints = _ref11.graphPoints, | ||
isShown = _ref11.isShown; | ||
@@ -1067,3 +858,3 @@ // Draw chart. | ||
graph.setAttribute('points', this.createPolylinePoints(xGraphPoints.map(this.mapX), graphPoints.map(function (y) { | ||
return _this3.mapY(maxY - y * yScale); | ||
return _this4.mapY(maxY - y * yScale); | ||
})).join(' ')); | ||
@@ -1079,7 +870,3 @@ graph.classList.add('chartogram__graph'); | ||
this.drawGauges(minX, maxX, minY_, maxY_, yAxisScale); // Draw timeline graph. | ||
if (renderTimeline) { | ||
this.renderTimeline(); | ||
} | ||
this.drawGauges(minX, maxX, minY_, maxY_, yAxisScale); | ||
} // function animateScale(scale) { | ||
@@ -1086,0 +873,0 @@ // console.log(scale) |
@@ -5,3 +5,2 @@ import Chartogram from './Chartogram'; | ||
chartogram.componentDidMount(); | ||
chartogram.render(); | ||
return function () { | ||
@@ -8,0 +7,0 @@ chartogram.componentWillUnmount(); |
{ | ||
"name": "chartogram", | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "Charts in JS with no dependencies", | ||
@@ -45,3 +45,7 @@ "main": "index.commonjs.js", | ||
"keywords": [ | ||
"charts" | ||
"charts", | ||
"chart", | ||
"graph", | ||
"plot", | ||
"diagram" | ||
], | ||
@@ -48,0 +52,0 @@ "author": "catamphetamine <purecatamphetamine@gmail.com>", |
@@ -82,3 +82,3 @@ # chartogram | ||
The default exported function returns another function which must be called in case of "destroying" the chart (it cleans up global event listeners). | ||
The default exported function returns another function which must be called in case of "destroying" the chart (it cleans up global event listeners and resets the DOM node). | ||
@@ -85,0 +85,0 @@ ### Browser |
@@ -6,10 +6,11 @@ import { | ||
divideInterval, | ||
renderGaugeLabels, | ||
throttle, | ||
simplifyGraph, | ||
setUpDrag | ||
renderGaugeLabels | ||
} from './utility' | ||
import Timeline from './Timeline' | ||
import Togglers from './Togglers' | ||
export default class Chartogram { | ||
constructor(rootNode, data, title = 'Title', options = {}) { | ||
constructor(rootNode, data, title = 'Title', props = {}) { | ||
this.props = { | ||
@@ -20,3 +21,3 @@ title, | ||
canvasWidth: 512, | ||
precisionFactor: Math.pow(10, options.precision || 3), | ||
precisionFactor: Math.pow(10, props.precision || 3), | ||
months: [ | ||
@@ -45,3 +46,3 @@ 'Jan', | ||
], | ||
...options | ||
...props | ||
} | ||
@@ -82,15 +83,4 @@ | ||
</div> | ||
<div class="chartogram__timeline"> | ||
<div class="chartogram__timeline-canvas-padding"> | ||
<svg class="chartogram__timeline-canvas" preserveAspectRatio="none"></svg> | ||
</div> | ||
<div class="chartogram__timeline-overlay-left"></div> | ||
<div class="chartogram__timeline-overlay-right"></div> | ||
<div class="chartogram__timeline-window"> | ||
<button type="button" class="chartogram__reset-button chartogram__timeline-window__drag"></button> | ||
<button type="button" class="chartogram__reset-button chartogram__timeline-window__left-handle"></button> | ||
<button type="button" class="chartogram__reset-button chartogram__timeline-window__right-handle"></button> | ||
</div> | ||
</div> | ||
<div class="chartogram__chart-togglers"></div> | ||
${Timeline.INITIAL_MARKUP} | ||
${Togglers.INITIAL_MARKUP} | ||
` | ||
@@ -103,33 +93,23 @@ | ||
this.yAxis = this.rootNode.querySelector('.chartogram__y') | ||
this.timeline = this.rootNode.querySelector('.chartogram__timeline') | ||
this.timelineOverlayLeft = this.rootNode.querySelector('.chartogram__timeline-overlay-left') | ||
this.timelineWindowLeftHandle = this.rootNode.querySelector('.chartogram__timeline-window__left-handle') | ||
this.timelineWindow = this.rootNode.querySelector('.chartogram__timeline-window') | ||
this.timelineWindowDrag = this.rootNode.querySelector('.chartogram__timeline-window__drag') | ||
this.timelineWindowRightHandle = this.rootNode.querySelector('.chartogram__timeline-window__right-handle') | ||
this.timelineOverlayRight = this.rootNode.querySelector('.chartogram__timeline-overlay-right') | ||
this.timelineCanvas = this.rootNode.querySelector('.chartogram__timeline-canvas') | ||
this.setUpTimelineWindowHandle('left') | ||
this.setUpTimelineWindowHandle('right') | ||
this.setUpTimelineWindow() | ||
this.setUpCanvasTooltipListener() | ||
// Add graph togglers. | ||
const graphTogglers = this.rootNode.querySelector('.chartogram__chart-togglers') | ||
clearElement(graphTogglers) | ||
for (const y of this.data.y) { | ||
graphTogglers.appendChild(this.createGraphToggler(y)) | ||
} | ||
// Render will be called after `.componentDidMount()`. | ||
this.state = this.getInitialState() | ||
this.updateTimelineBounds(this.state.fromRatio, this.state.toRatio) | ||
this.timeline = new Timeline(this.getTimelineProps()) | ||
this.timeline.componentDidMount() | ||
this.togglers = new Togglers(this.getTogglersProps()) | ||
this.togglers.componentDidMount() | ||
// Add window resize event listener. | ||
window.addEventListener('resize', this.onResizeThrottled) | ||
this.render() | ||
} | ||
componentWillUnmount() { | ||
this.rootNode.classList.remove('chartogram') | ||
clearElement(this.rootNode) | ||
// Remove window resize event listener. | ||
@@ -141,5 +121,4 @@ window.removeEventListener('resize', this.onResizeThrottled) | ||
this.setState({ | ||
aspectRatio: this.getCanvasAspectRatio(), | ||
timelineAspectRatio: this.getTimelineCanvasAspectRatio() | ||
}) | ||
aspectRatio: this.getCanvasAspectRatio() | ||
}, false) | ||
} | ||
@@ -154,8 +133,3 @@ | ||
getTimelineCanvasAspectRatio() { | ||
const timelineCanvasDimensions = this.timelineCanvas.getBoundingClientRect() | ||
return timelineCanvasDimensions.width / timelineCanvasDimensions.height | ||
} | ||
setState(newState, renderTimeline) { | ||
setState(newState, renderTimeline = true) { | ||
this.state = { | ||
@@ -165,5 +139,47 @@ ...this.state, | ||
} | ||
this.render(renderTimeline) | ||
this.render() | ||
if (renderTimeline) { | ||
this.timeline.componentDidUpdate(this.getTimelineProps()) | ||
} | ||
} | ||
getTimelineProps() { | ||
return { | ||
rootNode: this.rootNode, | ||
data: this.data, | ||
canvasWidth: this.props.canvasWidth, | ||
precisionFactor: this.props.precisionFactor, | ||
fromRatio: this.state.fromRatio, | ||
toRatio: this.state.toRatio, | ||
minYGlobal: this.state.minYGlobal, | ||
maxYGlobal: this.state.maxYGlobal, | ||
y: this.state.y, | ||
yScale: this.state.yScale, | ||
onChangeBounds: this.onChangeBounds | ||
} | ||
} | ||
getTogglersProps() { | ||
return { | ||
rootNode: this.rootNode, | ||
data: this.data, | ||
onToggle: (id) => { | ||
const y = this.state.y.find(_ => _.id === id) | ||
// Won't allow hiding all graphs. | ||
if (y.isShown) { | ||
const graphsShown = this.state.y.filter(_ => _.isShown) | ||
if (graphsShown.length === 1) { | ||
return | ||
} | ||
} | ||
y.isShown = !y.isShown | ||
this.setState({ | ||
y: this.state.y, | ||
...this.calculateMinMaxY(this.state.y) | ||
}) | ||
return true | ||
} | ||
} | ||
} | ||
getInitialState() { | ||
@@ -184,3 +200,2 @@ const { timelineWindowSize } = this.props | ||
aspectRatio: this.getCanvasAspectRatio(), | ||
timelineAspectRatio: this.getTimelineCanvasAspectRatio(), | ||
yScale: 1 | ||
@@ -262,3 +277,3 @@ } | ||
calculateMinMaxY(y) { | ||
// Calculate timeline min/max Y for the graphs being shown. | ||
// Calculate visible min/max Y for the graphs being shown. | ||
let minY = Infinity | ||
@@ -272,4 +287,2 @@ let maxY = -Infinity | ||
} | ||
// Min Y is always 0 by design. | ||
minY = 0 | ||
// Calculate global min/max Y for the graphs being shown. | ||
@@ -295,9 +308,3 @@ let minYGlobal = Infinity | ||
updateTimelineBounds(from, to) { | ||
this.setTimelineWindowLeft(from) | ||
this.setTimelineWindowRight(to) | ||
} | ||
updateBounds(from, to) { | ||
this.updateTimelineBounds(from, to) | ||
onChangeBounds = (from, to) => { | ||
this.setState(this.createState(from, to), false) | ||
@@ -329,15 +336,3 @@ } | ||
mapXForTimeline = (x) => { | ||
const { canvasWidth } = this.props | ||
const { minX, maxX } = this.data | ||
return ((x - minX) / (maxX - minX)) * canvasWidth | ||
} | ||
mapYForTimeline = (y) => { | ||
const { canvasWidth } = this.props | ||
const { minYGlobal, maxYGlobal, timelineAspectRatio } = this.state | ||
return ((y - minYGlobal) / (maxYGlobal - minYGlobal)) * canvasWidth / timelineAspectRatio | ||
} | ||
render(renderTimeline = true) { | ||
render() { | ||
const { canvasWidth, gaugeTickMarksCount } = this.props | ||
@@ -383,6 +378,2 @@ const { minX, maxX, minY, maxY, yScale, xGraphPoints, aspectRatio } = this.state | ||
) | ||
// Draw timeline graph. | ||
if (renderTimeline) { | ||
this.renderTimeline() | ||
} | ||
} | ||
@@ -430,150 +421,2 @@ | ||
renderTimeline = () => { | ||
const { canvasWidth } = this.props | ||
const { x, y } = this.data | ||
const { timelineAspectRatio, maxYGlobal, yScale } = this.state | ||
// Clear canvas. | ||
clearElement(this.timelineCanvas) | ||
// Set canvas `viewBox`. | ||
this.timelineCanvas.setAttribute('viewBox', `0 0 ${canvasWidth} ${this.fixSvgCoordinate(canvasWidth / timelineAspectRatio)}`) | ||
for (const { id, color, points } of y) { | ||
const isShown = this.state.y.find(_ => _.id === id).isShown | ||
if (isShown) { | ||
const [_x, _y] = simplifyGraph(x.points, points, 80) | ||
const graph = document.createElement('polyline') | ||
graph.setAttribute('stroke', color) | ||
graph.setAttribute('points', this.createPolylinePoints( | ||
_x.map(this.mapXForTimeline), | ||
_y.map(y => this.mapYForTimeline(maxYGlobal - y * yScale)) | ||
).join(' ')) | ||
graph.classList.add('chartogram__graph') | ||
this.timelineCanvas.appendChild(graph) | ||
} | ||
} | ||
// A workaround to fix WebKit bug when it's not re-rendering the <svg/>. | ||
// https://stackoverflow.com/questions/30905493/how-to-force-webkit-to-update-svg-use-elements-after-changes-to-original | ||
this.timelineCanvas.innerHTML += '' | ||
} | ||
createGraphToggler = ({ id, name, color }) => { | ||
const toggler = document.createElement('button') | ||
toggler.setAttribute('type', 'button') | ||
toggler.classList.add('chartogram__chart-toggler') | ||
toggler.classList.add('chartogram__chart-toggler--on') | ||
toggler.classList.add('chartogram__reset-button') | ||
// Add check. | ||
const xmlns = 'http://www.w3.org/2000/svg' | ||
const check = document.createElementNS(xmlns, 'svg') | ||
check.setAttribute('viewBox', '0 0 19 19') | ||
check.setAttribute('class', 'chartogram__chart-toggler-check') | ||
// Add background circle. | ||
const backgroundCircle = document.createElementNS(xmlns, 'circle') | ||
backgroundCircle.setAttribute('cx', '9.5') | ||
backgroundCircle.setAttribute('cy', '9.5') | ||
backgroundCircle.setAttribute('r', '9.5') | ||
backgroundCircle.setAttribute('fill', color) | ||
check.appendChild(backgroundCircle) | ||
// Add check circle. | ||
const checkCircle = document.createElementNS(xmlns, 'circle') | ||
checkCircle.setAttribute('cx', '9.5') | ||
checkCircle.setAttribute('cy', '9.5') | ||
checkCircle.setAttribute('r', '8') | ||
checkCircle.setAttribute('class', 'chartogram__chart-toggler-check-circle') | ||
check.appendChild(checkCircle) | ||
// Add check mark. | ||
const checkMark = document.createElementNS(xmlns, 'path') | ||
checkMark.setAttribute('d', 'M13.64 4.94l-6.2 6.34-1.69-1.9c-.73-.63-1.89.1-1.36 1.06l2 3.38c.3.43 1.04.85 1.78 0 .32-.42 6.31-7.93 6.31-7.93.74-.84-.2-1.58-.84-.95z') | ||
checkMark.setAttribute('fill', 'white') | ||
checkMark.setAttribute('class', 'chartogram__chart-toggler-check-mark') | ||
check.appendChild(checkMark) | ||
// Add checkmark. | ||
toggler.appendChild(check) | ||
// Add graph name. | ||
toggler.appendChild(document.createTextNode(name)) | ||
// On click. | ||
toggler.addEventListener('click', () => { | ||
const y = this.state.y.find(_ => _.id === id) | ||
// Won't allow hiding all graphs. | ||
if (y.isShown) { | ||
const graphsShown = this.state.y.filter(_ => _.isShown) | ||
if (graphsShown.length === 1) { | ||
return | ||
} | ||
} | ||
y.isShown = !y.isShown | ||
this.setState({ | ||
...this.state, | ||
...this.calculateMinMaxY(this.state.y) | ||
}) | ||
toggler.classList.toggle('chartogram__chart-toggler--on') | ||
}) | ||
return toggler | ||
} | ||
setUpTimelineWindowHandle = (side) => { | ||
const handle = side === 'left' ? this.timelineWindowLeftHandle : this.timelineWindowRightHandle | ||
const handleWidth = parseFloat(getComputedStyle(this.timelineWindow).borderLeftWidth) | ||
let timelineCoordinates | ||
let minX | ||
let maxX | ||
let deltaX | ||
let startedX | ||
const onDrag = (x) => { | ||
x -= deltaX | ||
x = Math.max(Math.min(x, maxX), minX) | ||
const ratio = (x - timelineCoordinates.left) / timelineCoordinates.width | ||
if (side === 'left') { | ||
this.updateBounds(ratio, this.state.toRatio) | ||
} else { | ||
this.updateBounds(this.state.fromRatio, ratio) | ||
} | ||
} | ||
const onDragStart = (x) => { | ||
timelineCoordinates = this.timeline.getBoundingClientRect() | ||
const timelineWindowCoordinates = this.timelineWindow.getBoundingClientRect() | ||
if (side === 'left') { | ||
minX = timelineCoordinates.left | ||
maxX = timelineWindowCoordinates.left + timelineWindowCoordinates.width - 2 * handleWidth | ||
deltaX = x - timelineWindowCoordinates.left | ||
} else { | ||
minX = timelineWindowCoordinates.left + 2 * handleWidth | ||
maxX = timelineCoordinates.left + timelineCoordinates.width | ||
deltaX = x - (timelineWindowCoordinates.left + timelineWindowCoordinates.width) | ||
} | ||
} | ||
return setUpDrag(handle, onDragStart, onDrag) | ||
} | ||
setUpTimelineWindow = () => { | ||
let timelineCoordinates | ||
let timelineWindowCoordinates | ||
let minX | ||
let maxX | ||
let innerX | ||
const onDrag = (x) => { | ||
x -= innerX | ||
x = Math.max(Math.min(x, maxX), minX) | ||
const ratio = (x - timelineCoordinates.left) / timelineCoordinates.width | ||
this.updateBounds(ratio, ratio + timelineWindowCoordinates.width / timelineCoordinates.width) | ||
} | ||
const onDragStart = (x) => { | ||
timelineCoordinates = this.timeline.getBoundingClientRect() | ||
timelineWindowCoordinates = this.timelineWindow.getBoundingClientRect() | ||
innerX = x - timelineWindowCoordinates.left | ||
minX = timelineCoordinates.left | ||
maxX = timelineCoordinates.left + (timelineCoordinates.width - timelineWindowCoordinates.width) | ||
} | ||
return setUpDrag(this.timelineWindowDrag, onDragStart, onDrag) | ||
} | ||
setTimelineWindowLeft = (ratio) => { | ||
this.timelineOverlayLeft.style.right = `${100 * (1 - ratio)}%` | ||
this.timelineWindow.style.left = `${100 * ratio}%` | ||
} | ||
setTimelineWindowRight = (ratio) => { | ||
this.timelineOverlayRight.style.left = `${100 * ratio}%` | ||
this.timelineWindow.style.right = `${100 * (1 - ratio)}%` | ||
} | ||
setUpCanvasTooltipListener = () => { | ||
@@ -786,8 +629,12 @@ const { weekdays, months } = this.props | ||
let i = 0 | ||
while (i < this.tooltipPoints.length) { | ||
const point = this.tooltipPoints[i] | ||
const _y = y[i].points[xIndex] | ||
const yRatio = _y / maxY | ||
point.style.left = `${xRatio * 100}%` | ||
point.style.bottom = `${yRatio * 100}%` | ||
let j = 0 | ||
while (i < y.length) { | ||
if (y[i].isShown) { | ||
const point = this.tooltipPoints[j] | ||
const _y = y[i].points[xIndex] | ||
const yRatio = _y / maxY | ||
point.style.left = `${xRatio * 100}%` | ||
point.style.bottom = `${yRatio * 100}%` | ||
j++ | ||
} | ||
i++ | ||
@@ -794,0 +641,0 @@ } |
@@ -6,3 +6,2 @@ import Chartogram from './Chartogram' | ||
chartogram.componentDidMount() | ||
chartogram.render() | ||
return () => { | ||
@@ -9,0 +8,0 @@ chartogram.componentWillUnmount() |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
1046675
38
3834
0
0