chartogram
Advanced tools
Comparing version 0.1.10 to 0.1.11
@@ -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,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,n,i,a){for(var o=0;o<i;){var r=document.createElement("div"),s=e+o*(n-e)/(i-1);a&&(s=a(s)),r.appendChild(document.createTextNode(s)),t.appendChild(r),o++}}function i(t,e){var n,i=0,a=function(){n=void 0,i=Date.now(),t()};return function(){var o=Date.now(),r=e-(o-i);r<=0?(n&&(clearTimeout(n),n=void 0),i=o,t()):n||(n=setTimeout(a,r))}}function a(t,e,n){function i(t){n(t.changedTouches[0].clientX,t.changedTouches[0].clientY)}function a(t){n(t.clientX,t.clientY)}function o(){window.removeEventListener("pointermove",a),window.removeEventListener("touchmove",i),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",i),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 o(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=[],i=!0,a=!1,o=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){a=!0,o=t}finally{try{i||null==s.return||s.return()}finally{if(a)throw o}}return n}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function r(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 s(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var l=function(){function n(t){var e=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,n),s(this,"onResize",function(t){e.setState({aspectRatio:e.getCanvasAspectRatio()})}),s(this,"onResizeThrottled",i(this.onResize,33)),s(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){s(t,e,n[e])})}return t}({},e.state,t),e.render()}),s(this,"mapX",function(t){var n=e.props,i=n.canvasWidth,a=n.data,o=a.minX;return(t-o)/(a.maxX-o)*i}),s(this,"mapY",function(t){var n=e.props,i=n.canvasWidth,a=n.minYGlobal;return(t-a)/(n.maxYGlobal-a)*i/e.state.aspectRatio}),s(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)})}),s(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)})}),s(this,"setTimelineWindowLeft",function(t){e.timelineOverlayLeft.style.right="".concat(100*(1-t),"%"),e.timelineWindow.style.left="".concat(100*t,"%")}),s(this,"setTimelineWindowRight",function(t){e.timelineOverlayRight.style.left="".concat(100*t,"%"),e.timelineWindow.style.right="".concat(100*(1-t),"%")}),this.props=t}var l,c,h;return l=n,(c=[{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,a=i.canvasWidth,r=i.y,s=i.data,l=i.maxYGlobal,c=i.fixSvgCoordinate,h=i.createPolylinePoints,u=i.graphOpacity,d=this.state.aspectRatio;e(this.timelineCanvas),this.timelineCanvas.setAttribute("viewBox","0 0 ".concat(a," ").concat(c(a/d)));for(var p=0,m=function(){var e=s.y[p],i=e.id,a=e.color,c=e.points,d=u[p];if(r.find(function(t){return t.id===i}).isShown||d>0){var m=o(function e(n,i,a){var o=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<=a?[l,c]:(n.length/l.length<1.1&&(r=Math.min(r+.025,1)),e(l,c,a,o,r))}var u=(i[s+2]+i[s])/2;return Math.abs(u-i[s+1])/o<r?(l[h]=n[s],l[h+1]=n[s+2],c[h]=i[s],c[h+1]=i[s+2],e(n,i,a,o,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,a,o,r,s+2,l,c,h+2))}(s.x.points,c,80),2),v=m[0],f=m[1],g=document.createElement("polyline");g.setAttribute("stroke",a),g.setAttribute("points",h(v.map(n.mapX),f.map(function(t){return n.mapY(l-t)})).join(" ")),g.classList.add("chartogram__graph"),1!==d&&(g.style.opacity=d),n.timelineCanvas.appendChild(g)}p++};p<s.y.length;)m();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)}}])&&r(l.prototype,c),h&&r(l,h),n}();function c(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 h(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}l.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),h(this,"createGraphToggler",function(t){var e=t.id,i=t.name,a=t.color,o=document.createElement("button");o.setAttribute("type","button"),o.classList.add("chartogram__chart-toggler"),o.classList.add("chartogram__chart-toggler--on"),o.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",a),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),o.appendChild(s),o.appendChild(document.createTextNode(i)),o.addEventListener("click",function(){return n.onToggle(e,o)}),o}),h(this,"onToggle",function(t,e){(0,n.props.onToggle)(t)&&e.classList.toggle("chartogram__chart-toggler--on")}),this.props=e}var n,i,a;return n=t,(i=[{key:"componentDidMount",value:function(){var t=this.props,n=t.rootNode,i=t.data,a=n.querySelector(".chartogram__chart-togglers");e(a);var o=i.y,r=Array.isArray(o),s=0;for(o=r?o:o[Symbol.iterator]();;){var l;if(r){if(s>=o.length)break;l=o[s++]}else{if((s=o.next()).done)break;l=s.value}var c=l;a.appendChild(this.createGraphToggler(c))}}}])&&c(n.prototype,i),a&&c(n,a),t}();function d(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 p(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 m=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),p(this,"setUpListener",function(){!function(t,e,n,i){var a;function o(t,e){n(t,e,a)}function r(){a=t.getBoundingClientRect(),e()}function s(e){if(e.touches.length>1)return h();r(),t.addEventListener("touchend",h),t.addEventListener("touchmove",l),t.addEventListener("touchend",h),t.addEventListener("touchcancel",h),l(e)}function l(t){var e=t.changedTouches[0].clientX,n=t.changedTouches[0].clientY;e<a.left||e>a.left+a.width||n<a.top||n>a.top+a.height?h():o(e,n)}function c(t){o(t.clientX,t.clientY)}function h(){t.removeEventListener("pointermove",c),t.removeEventListener("pointerleave",h),t.removeEventListener("pointercancel",h),t.removeEventListener("touchmove",l),t.removeEventListener("touchend",h),t.removeEventListener("touchcancel",h),i()}function u(){r(),t.addEventListener("pointermove",c),t.addEventListener("pointerleave",h),t.addEventListener("pointercancel",h)}t.addEventListener("touchstart",s),t.addEventListener("pointerenter",u)}(n.props.canvas,function(){},n.onTrack,function(){return n.unmount()})}),p(this,"onTrack",function(t,e,i){var a,o=n.props,r=o.minX,s=o.maxX,l=o.xPoints,c=r+(t-i.left)/i.width*(s-r),h=l.findIndex(function(t){return t>=c}),u=h-1;if((h<0||h>=l.length)&&(h=-1),(u<0||u>=l.length)&&(u=-1),h<0){if(u<0)return n.unmount();a=u}else if(u<0)a=h;else{var d=l[u],p=l[h];a=c-d>p-c?h:u}var m=l[a];m!==n.tooltipForX&&(n.tooltipForX=m,n.tooltip||n.mount(),n.updateTooltip(m,a,i.width))}),p(this,"unmountLine",function(){n.props.canvas.removeChild(n.line),n.line=void 0}),p(this,"mountPoints",function(){var t=n.props.pointsContainer;n.points=n.renderPoints();var e=n.points,i=Array.isArray(e),a=0;for(e=i?e:e[Symbol.iterator]();;){var o;if(i){if(a>=e.length)break;o=e[a++]}else{if((a=e.next()).done)break;o=a.value}var r=o;t.appendChild(r)}}),p(this,"unmountPoints",function(){var t=n.props.pointsContainer,e=n.points,i=Array.isArray(e),a=0;for(e=i?e:e[Symbol.iterator]();;){var o;if(i){if(a>=e.length)break;o=e[a++]}else{if((a=e.next()).done)break;o=a.value}var r=o;t.removeChild(r)}n.points=void 0}),p(this,"updateLinePosition",function(t){n.isLineRendered()||n.mountLine();var e=n.props,i=e.canvasWidth,a=e.aspectRatio,o=e.fixSvgCoordinate,r=e.mapX;n.line.setAttributeNS(null,"x1",o(r(t))),n.line.setAttributeNS(null,"x2",o(r(t))),n.line.setAttributeNS(null,"y1",0),n.line.setAttributeNS(null,"y2",o(i/a))}),p(this,"updatePointPositions",function(t,e){for(var i=n.props,a=i.maxY,o=i.y,r=0,s=0;r<o.length;){if(o[r].isShown){var l=n.points[s],c=o[r].points[t]/a;l.style.left="".concat(100*e,"%"),l.style.bottom="".concat(100*c,"%"),s++}r++}}),this.props=e}var e,n,i;return e=t,(n=[{key:"componentDidMount",value:function(){this.unlisten=this.setUpListener()}},{key:"componentWillUnmount",value:function(){this.unlisten(),this.unmount()}},{key:"componentDidUpdate",value:function(t){this.props!==t&&(this.props=t)}},{key:"mount",value:function(){var t=this.props.container;this.tooltip=this.renderTooltip(),t.appendChild(this.tooltip),this.mountPoints(),this.isLineRendered()||this.mountLine()}},{key:"unmount",value:function(){if(this.tooltip){var t=this.props.container;this.tooltipForX=void 0,t.removeChild(this.tooltip),this.tooltip=void 0,this.unmountPoints(),this.isLineRendered()&&this.unmountLine()}}},{key:"mountLine",value:function(){var t=this.props.canvas;this.line=this.renderLine(),t.insertBefore(this.line,t.querySelector("polyline"))}},{key:"renderTooltip",value:function(){var t=this.props.y,e=document.createElement("div");e.classList.add("chartogram__tooltip");var n=document.createElement("h1");n.classList.add("chartogram__tooltip-header"),e.appendChild(n);var i=document.createElement("dl");i.classList.add("chartogram__tooltip-values"),e.appendChild(i);var a=t,o=Array.isArray(a),r=0;for(a=o?a:a[Symbol.iterator]();;){var s;if(o){if(r>=a.length)break;s=a[r++]}else{if((r=a.next()).done)break;s=r.value}var l=s,c=l.isShown,h=l.color;if(c){var u=document.createElement("dt");u.style.color=h,i.appendChild(u);var d=document.createElement("dd");d.style.color=h,i.appendChild(d)}}return e}},{key:"renderLine",value:function(){var t=document.createElementNS("http://www.w3.org/2000/svg","line");return t.setAttribute("class","chartogram__tooltip-line"),t}},{key:"isLineRendered",value:function(){var t=this.props.canvas;return this.line&&this.line.parentNode===t}},{key:"renderPoints",value:function(){var t=[],e=this.props,n=e.pointsContainer,i=e.y,a=Array.isArray(i),o=0;for(i=a?i:i[Symbol.iterator]();;){var r;if(a){if(o>=i.length)break;r=i[o++]}else{if((o=i.next()).done)break;r=o.value}var s=r;if(s.isShown){var l=document.createElement("div");l.classList.add("chartogram__tooltip-point"),l.style.color=s.color,t.push(l),n.appendChild(l)}}return t}},{key:"updateTooltip",value:function(t,e,n){var i=this.props,a=i.minX,o=(t-a)/(i.maxX-a);this.updateTooltipDate(new Date(t)),this.updateTooltipValues(e),this.updateTooltipPosition(o,n),this.updatePointPositions(e,o),this.updateLinePosition(t)}},{key:"updateTooltipPosition",value:function(t,e){var n=this.props,i=n.tooltipShift,a=n.maxOverflow,o=t*e;o-=void 0===i?40:i;var r=this.tooltip.getBoundingClientRect().width,s=void 0===a?5:a;o<-1*s?o=-1*s:o+r>e+s&&(o=e+s-r),this.tooltip.style.left=o+"px"}},{key:"updateTooltipDate",value:function(t){var e=this.props,n=e.weekdays,i=e.months;this.tooltip.childNodes[0].textContent="".concat(n[t.getDay()],", ").concat(i[t.getMonth()]," ").concat(t.getDate())}},{key:"updateTooltipValues",value:function(t){var e=this.props.y,n=this.tooltip.childNodes[1],i=0,a=e,o=Array.isArray(a),r=0;for(a=o?a:a[Symbol.iterator]();;){var s;if(o){if(r>=a.length)break;s=a[r++]}else{if((r=a.next()).done)break;s=r.value}var l=s,c=l.isShown,h=l.points,u=l.name;c&&(n.childNodes[2*i].textContent=h[t],n.childNodes[2*i+1].textContent=u,i++)}}}])&&d(e.prototype,n),i&&d(e,i),t}();function v(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 f(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){y(t,e,n[e])})}return t}function g(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 y(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var b=function(){function t(a,o){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),y(this,"onResize",function(t){r.setState({aspectRatio:r.getCanvasAspectRatio()},!1)}),y(this,"onResizeThrottled",i(this.onResize,33)),y(this,"onToggle",function(t){var e=r.state.y.find(function(e){return e.id===t});if(e.isShown&&1===r.state.y.filter(function(t){return t.isShown}).length)return;e.isShown=!e.isShown,r.setState({y:r.state.y});var n=r.calculateMinMaxY(r.state.y),i=n.minY,a=n.maxY,o=n.minYGlobal,s=n.maxYGlobal;return r.transitionState(i,a,o,s,r.state.y.map(function(t){return t.isShown?1:0})),!0}),y(this,"onChangeBounds",function(t,e){var n=r.createState(t,e),i=n.minY,a=n.maxY;delete n.minY,delete n.maxY,r.setState(n,!1),r.transitionState(i,a)}),y(this,"createPolylinePoints",function(t,e){return n=t.map(r.fixSvgCoordinate),i=e.map(r.fixSvgCoordinate),n.map(function(t,e){return"".concat(t,",").concat(i[e])});var n,i}),y(this,"fixSvgCoordinate",function(t){var e=r.props.precisionFactor;return Math.round(t*e)/e}),y(this,"mapX",function(t){var e=r.props.canvasWidth,n=r.state,i=n.minX;return(t-i)/(n.maxX-i)*e}),y(this,"mapY",function(t){var e=r.props.canvasWidth,n=r.state,i=n.minY;return(t-i)/(n.maxY-i)*e/n.aspectRatio}),y(this,"transitionStateTick",function(){var t=r.props.transitionEasing,e=r.state,n=e.transitionStartedAt,i=e.transitionDuration,a=e.graphOpacityFrom,o=e.graphOpacityTo,s=e.minYFrom,l=e.minYTo,c=e.maxYFrom,h=e.maxYTo,u=e.minYGlobalFrom,d=e.minYGlobalTo,p=e.maxYGlobalFrom,m=e.maxYGlobalTo,v=Date.now()-n,f=Math.min(v/i,1);f=S[t](f);var g={};void 0!==l&&(g.minY=s+(l-s)*f,g.maxY=c+(h-c)*f,1===f&&(g.minYFrom=void 0,g.minYTo=void 0,g.maxYFrom=void 0,g.maxYTo=void 0)),void 0!==d&&(g.minYGlobal=u+(d-u)*f,g.maxYGlobal=p+(m-p)*f,1===f&&(g.minYGlobalFrom=void 0,g.minYGlobalTo=void 0,g.maxYGlobalFrom=void 0,g.maxYGlobalTo=void 0)),void 0!==o&&(g.graphOpacity=o.map(function(t,e){return a[e]+(o[e]-a[e])*f}),1===f&&(g.graphOpacityFrom=void 0,g.graphOpacityTo=void 0)),r.setState(g),r.transition=f<1?requestAnimationFrame(r.transitionStateTick):void 0}),y(this,"createGridLine",function(t){var e=r.state,n=e.minX,i=e.maxX,a=(e.minY,e.maxY),o=document.createElement("line");return o.classList.add("chartogram__grid-line"),o.setAttribute("x1",r.fixSvgCoordinate(r.mapX(n))),o.setAttribute("x2",r.fixSvgCoordinate(r.mapX(i))),o.setAttribute("y1",r.fixSvgCoordinate(r.mapY(a-t))),o.setAttribute("y2",r.fixSvgCoordinate(r.mapY(a-t))),o}),y(this,"drawGauges",function(t,i,a,o,s){var l=r.props,c=l.gaugeTickMarksCount,h=l.months;e(r.xAxis),e(r.yAxis),n(r.xAxis,t,i,c,function(t){var e=new Date(t);return"".concat(h[e.getMonth()]," ").concat(e.getDate())}),n(r.yAxis,a,o,c),r.yAxis.style.height="".concat(100/s,"%")}),this.props=f({title:s,transitionDuration:250,transitionEasing:"easeOutQuad",gaugeTickMarksCount:6,timelineWindowSize:40,canvasWidth:512,precisionFactor:Math.pow(10,l.precision||3),months:w,weekdays:x},l),this.rootNode=a,this.data=f({},o,{minX:Math.min.apply(Math,v(o.x.points)),maxX:Math.max.apply(Math,v(o.x.points)),y:o.y.map(function(t){return f({},t,{min:Math.min.apply(Math,v(t.points)),max:Math.max.apply(Math,v(t.points))})})})}var a,o,r;return a=t,(o=[{key:"componentDidMount",value:function(){this.rootNode.classList.add("chartogram"),this.rootNode.innerHTML="\n\t\t\t".concat(_.replace("{title}",this.props.title),"\n\t\t\t").concat(l.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.state=this.getInitialState(),this.timeline=new l(this.getTimelineProps()),this.timeline.componentDidMount(),this.togglers=new u(this.getTogglersProps()),this.togglers.componentDidMount(),this.tooltip=new m(this.getTooltipProps()),this.tooltip.componentDidMount(),window.addEventListener("resize",this.onResizeThrottled),this.render()}},{key:"componentWillUnmount",value:function(){this.timeline.componentWillUnmount(),this.rootNode.classList.remove("chartogram"),e(this.rootNode),window.removeEventListener("resize",this.onResizeThrottled),this.transition&&cancelAnimationFrame(this.transition)}},{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=f({},this.state,t),this.render(),e&&this.timeline.componentDidUpdate(this.getTimelineProps()),this.tooltip.componentDidUpdate(this.getTooltipProps())}},{key:"getTimelineProps",value:function(){return{rootNode:this.rootNode,data:this.data,canvasWidth:this.props.canvasWidth,fixSvgCoordinate:this.fixSvgCoordinate,createPolylinePoints:this.createPolylinePoints,fromRatio:this.state.fromRatio,toRatio:this.state.toRatio,minYGlobal:this.state.minYGlobal,maxYGlobal:this.state.maxYGlobal,y:this.state.y,graphOpacity:this.state.graphOpacity,onChangeBounds:this.onChangeBounds}}},{key:"getTogglersProps",value:function(){return{rootNode:this.rootNode,data:this.data,onToggle:this.onToggle}}},{key:"getTooltipProps",value:function(){return{canvas:this.canvas,container:this.tooltipContainer,pointsContainer:this.canvasWrapper,weekdays:this.props.weekdays,months:this.props.months,canvasWidth:this.props.canvasWidth,aspectRatio:this.state.aspectRatio,mapX:this.mapX,fixSvgCoordinate:this.fixSvgCoordinate,minX:this.state.minX,maxX:this.state.maxX,maxY:this.state.maxY,xPoints:this.state.xPoints,y:this.state.y}}},{key:"getInitialState",value:function(){var t,e=this.props.timelineWindowSize,n=this.data,i=n.minX,a=n.maxX;t=this.data.x.points.length>e?this.data.x.points.length-e:0;var o=(this.data.x.points[t]-i)/(a-i);return f({},this.createState(o,1),{aspectRatio:this.getCanvasAspectRatio(),graphOpacity:this.data.y.map(function(t){return 1})})}},{key:"createState",value:function(t,e){var n,i,a=this,o=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:o.points.findIndex(function(t){return t>r})-1,i=s===this.data.maxX?o.points.length-1:o.points.findIndex(function(t){return t>s});var l=o.points.slice(n,i+1),c=l.slice();l.length>=2&&(o.points[n]!==r&&(c[0]=r),o.points[i]!==s&&(c[c.length-1]=s));var h=this.data.y.map(function(t,e){var c=a.data.y[e].points.slice(n,i+1),h=c.slice();if(l.length>=2){if(o.points[n]!==r){var u=a.data.y[e].points[n],d=u+(a.data.y[e].points[n+1]-u)*((r-a.data.x.points[n])/(a.data.x.points[n+1]-a.data.x.points[n]));h[0]=d}if(o.points[i]!==s){var p=a.data.y[e].points[i],m=a.data.y[e].points[i-1],g=m+(p-m)*((s-a.data.x.points[i-1])/(a.data.x.points[i]-a.data.x.points[i-1]));h[h.length-1]=g}}return f({},a.data.y[e],a.state?a.state.y[e]:{isShown:!0},{points:c,graphPoints:h,min:0,max:Math.max.apply(Math,v(h))})});return f({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,a=Array.isArray(i),o=0;for(i=a?i:i[Symbol.iterator]();;){var r;if(a){if(o>=i.length)break;r=i[o++]}else{if((o=i.next()).done)break;r=o.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(d){if(p>=u.length)return"break";m=u[p++]}else{if((p=u.next()).done)return"break";m=p.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))},u=this.data.y,d=Array.isArray(u),p=0;for(u=d?u:u[Symbol.iterator]();;){var m;if("break"===h())break}return{minY:e,maxY:n,minYGlobal:l=0,maxYGlobal:c}}},{key:"render",value:function(){var t=this,n=this.props,i=n.canvasWidth,a=n.gaugeTickMarksCount,o=this.state,r=o.minX,s=o.maxX,l=o.minY,c=o.maxY,h=o.xGraphPoints,u=o.aspectRatio,d=o.graphOpacity;e(this.canvas),this.canvas.setAttribute("viewBox","0 0 ".concat(i," ").concat(this.fixSvgCoordinate(i/u)));var p=l,m=function(t,e){for(t=Math.floor(t);;){if(t<e)return e;if(t%e==0)return t;t--}}(c,10),v=(c-l)/(m-p),f=function(t,e,n){for(var i=new Array(n),a=0;a<n;)i[a]=t+a*(e-t)/(n-1),a++;return i}(p,m,a),g=Array.isArray(f),y=0;for(f=g?f:f[Symbol.iterator]();;){var b;if(g){if(y>=f.length)break;b=f[y++]}else{if((y=f.next()).done)break;b=y.value}var w=b;this.canvas.appendChild(this.createGridLine(w))}for(var x=0;x<this.state.y.length;){var _=this.state.y[x],S=_.color,A=_.graphPoints,T=_.isShown,C=d[x];if(T||C>0){var k=document.createElement("polyline");k.setAttribute("stroke",S),k.setAttribute("points",this.createPolylinePoints(h.map(this.mapX),A.map(function(e){return t.mapY(c-e)})).join(" ")),k.classList.add("chartogram__graph"),1!==C&&(k.style.opacity=C),this.canvas.appendChild(k)}x++}this.canvas.innerHTML+="",this.drawGauges(r,s,p,m,v)}},{key:"transitionState",value:function(t,e,n,i,a){var o=this.props.transitionDuration;this.transition&&cancelAnimationFrame(this.transition);var r=o;if(void 0!==t){var s=this.state.maxY-this.state.minY,l=Math.abs(e-this.state.maxY)/s,c=Math.abs(t-this.state.minY)/s,h=Math.max(c,l);r=o*Math.max(.2,2*Math.min(h,.5))}a||(r/=2);var u={transitionStartedAt:Date.now(),transitionDuration:r};void 0!==t&&(u.minYFrom=this.state.minY,u.maxYFrom=this.state.maxY,u.minYTo=t,u.maxYTo=e),void 0!==a&&(u.graphOpacityFrom=this.state.graphOpacity,u.graphOpacityTo=a),void 0!==n&&(u.minYGlobalFrom=this.state.minYGlobal,u.maxYGlobalFrom=this.state.maxYGlobal,u.minYGlobalTo=n,u.maxYGlobalTo=i),this.setState(u),this.transition=requestAnimationFrame(this.transitionStateTick)}}])&&g(a.prototype,o),r&&g(a,r),t}(),w=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],x=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],_='\n\t<header class="chartogram__header">\n\t\t<h1 class="chartogram__title">{title}</h1>\n\t</header>\n\t<div class="chartogram__plan-with-axes">\n\t\t<div class="chartogram__plan">\n\t\t\t<div class="chartogram__top-border"></div>\n\t\t\t<div class="chartogram__canvas-wrapper">\n\t\t\t\t<svg class="chartogram__canvas"></svg>\n\t\t\t\t<div class="chartogram__x"></div>\n\t\t\t\t<div class="chartogram__y-wrapper">\n\t\t\t\t\t<div class="chartogram__y"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n',S={linear:function(t){return t},easeInOutSin:function(t){return(1+Math.sin(Math.PI*t-Math.PI/2))/2},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeOutCubic:function(t){return--t*t*t+1},easeOutQuad:function(t){return t*(2-t)}};return function(t,e,n,i){var a=new b(t,e,n,i);return a.componentDidMount(),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){var n,i=0,a=function(){n=void 0,i=Date.now(),t()};return function(){var o=Date.now(),r=e-(o-i);r<=0?(n&&(clearTimeout(n),n=void 0),i=o,t()):n||(n=setTimeout(a,r))}}function i(t,e,n){function i(t){n(t.changedTouches[0].clientX,t.changedTouches[0].clientY)}function a(t){n(t.clientX,t.clientY)}function o(){window.removeEventListener("pointermove",a),window.removeEventListener("touchmove",i),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",i),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,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=[],i=!0,a=!1,o=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){a=!0,o=t}finally{try{i||null==s.return||s.return()}finally{if(a)throw o}}return n}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function o(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 r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var s=function(){function e(t){var a=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),r(this,"onResize",function(t){a.setState({aspectRatio:a.getCanvasAspectRatio()})}),r(this,"onResizeThrottled",n(this.onResize,33)),r(this,"setState",function(t){t.aspectRatio!==a.state.aspectRatio&&a.updateAspectRatio(t.aspectRatio),a.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){r(t,e,n[e])})}return t}({},a.state,t),a.render()}),r(this,"mapX",function(t){var e=a.props,n=e.canvasWidth,i=e.data,o=i.minX;return(t-o)/(i.maxX-o)*n}),r(this,"mapY",function(t){var e=a.props,n=e.canvasWidth,i=e.minY;return(t-i)/(e.maxY-i)*n/a.state.aspectRatio}),r(this,"setUpTimelineWindowHandle",function(t){var e,n,o,r,s="left"===t?a.timelineWindowLeftHandle:a.timelineWindowRightHandle,h=parseFloat(getComputedStyle(a.timelineWindow).borderLeftWidth);return i(s,function(i){e=a.timeline.getBoundingClientRect();var s=a.timelineWindow.getBoundingClientRect();"left"===t?(n=e.left,o=s.left+s.width-2*h,r=i-s.left):(n=s.left+2*h,o=e.left+e.width,r=i-(s.left+s.width))},function(i){i-=r;var s=((i=Math.max(Math.min(i,o),n))-e.left)/e.width;"left"===t?a.updateBounds(s,a.props.toRatio):a.updateBounds(a.props.fromRatio,s)})}),r(this,"setUpTimelineWindow",function(){var t,e,n,o,r;return i(a.timelineWindowDrag,function(i){t=a.timeline.getBoundingClientRect(),e=a.timelineWindow.getBoundingClientRect(),r=i-e.left,n=t.left,o=t.left+(t.width-e.width)},function(i){i-=r;var s=((i=Math.max(Math.min(i,o),n))-t.left)/t.width;a.updateBounds(s,s+e.width/t.width)})}),r(this,"setTimelineWindowLeft",function(t){a.timelineOverlayLeft.style.right="".concat(100*(1-t),"%"),a.timelineWindow.style.left="".concat(100*t,"%")}),r(this,"setTimelineWindowRight",function(t){a.timelineOverlayRight.style.left="".concat(100*t,"%"),a.timelineWindow.style.right="".concat(100*(1-t),"%")}),this.props=t}var s,h,l;return s=e,(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.updateAspectRatio(),this.setUpTimelineWindowHandle("left"),this.setUpTimelineWindowHandle("right"),this.setUpTimelineWindow(),window.addEventListener("resize",this.onResizeThrottled),this.onChangeBounds(this.props.fromRatio,this.props.toRatio),this.mountGraphs(),this.render()}},{key:"componentWillUnmount",value:function(){window.removeEventListener("resize",this.onResizeThrottled)}},{key:"updateAspectRatio",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.state.aspectRatio,e=this.props,n=e.canvasWidth,i=e.fixSvgCoordinate;this.timelineCanvas.setAttribute("viewBox","0 0 ".concat(n," ").concat(i(n/t)))}},{key:"getCanvasAspectRatio",value:function(){var t=this.timelineCanvas.getBoundingClientRect();return t.width/t.height}},{key:"render",value:function(){for(var e=this,n=this.props,i=n.y,o=n.data,r=n.graphOpacity,s=0,h=function(){var n=o.y[s],h=n.id,l=n.points,c=n.color,u=i.find(function(t){return t.id===h}).isShown,d=r[s];if(u||d>0){var p=a(function e(n,i,a){var o=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,h=arguments.length>6&&void 0!==arguments[6]?arguments[6]:new Array(n.length),l=arguments.length>7&&void 0!==arguments[7]?arguments[7]:new Array(n.length),c=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0;if(s+2>n.length-1){for(;s<i.length;)h[c]=n[s],l[c]=i[s],c++,s++;return h=h.slice(0,c),l=l.slice(0,c),h.length<=a?[h,l]:(n.length/h.length<1.1&&(r=Math.min(r+.025,1)),e(h,l,a,o,r))}var u=(i[s+2]+i[s])/2;return Math.abs(u-i[s+1])/o<r?(h[c]=n[s],h[c+1]=n[s+2],l[c]=i[s],l[c+1]=i[s+2],e(n,i,a,o,r,s+2,h,l,c+1)):(h[c]=n[s],h[c+1]=n[s+1],h[c+2]=n[s+2],l[c]=i[s],l[c+1]=i[s+1],l[c+2]=i[s+2],e(n,i,a,o,r,s+2,h,l,c+2))}(o.x.points,l,80),2),m=p[0],v=p[1];e.graphs[s]?e.updateGraph(s,m,v,d):e.mountGraph(s,m,v,c,d)}else e.graphs[s]&&e.unmountGraph(s);s++};s<o.y.length;)h()}},{key:"renderGraph",value:function(t,e,n){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,a=document.createElementNS("http://www.w3.org/2000/svg","polyline");return a.setAttribute("stroke",n),this.updateGraph(a,t,e,i),a.classList.add("chartogram__graph"),a}},{key:"mountGraphs",value:function(){var t=this;this.graphs=[];var e=this.props.data;e.y.forEach(function(n,i){var a=n.points,o=n.color;t.mountGraph(i,e.x.points,a,o)})}},{key:"mountGraph",value:function(t,e,n,i,a){var o=this.renderGraph(e,n,i,a);this.graphs[t]=o,this.timelineCanvas.appendChild(o)}},{key:"unmountGraph",value:function(t){this.timelineCanvas.removeChild(this.graphs[t]),this.graphs[t]=void 0}},{key:"updateGraph",value:function(t,e,n,i){var a=this,o=this.props,r=o.maxY,s=o.createPolylinePoints;"number"==typeof t&&(t=this.graphs[t]),t.setAttribute("points",s(e.map(this.mapX),n.map(function(t){return a.mapY(r-t)})).join(" ")),1!==i&&(t.style.opacity=i)}},{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)}}])&&o(s.prototype,h),l&&o(s,l),e}();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 l(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}s.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 c=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),l(this,"createGraphToggler",function(t){var e=t.id,i=t.name,a=t.color,o=document.createElement("button");o.setAttribute("type","button"),o.classList.add("chartogram__chart-toggler"),o.classList.add("chartogram__chart-toggler--on"),o.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 h=document.createElementNS(r,"circle");h.setAttribute("cx","9.5"),h.setAttribute("cy","9.5"),h.setAttribute("r","9.5"),h.setAttribute("fill",a),s.appendChild(h);var l=document.createElementNS(r,"circle");l.setAttribute("cx","9.5"),l.setAttribute("cy","9.5"),l.setAttribute("r","8"),l.setAttribute("class","chartogram__chart-toggler-check-circle"),s.appendChild(l);var c=document.createElementNS(r,"path");return c.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"),c.setAttribute("fill","white"),c.setAttribute("class","chartogram__chart-toggler-check-mark"),s.appendChild(c),o.appendChild(s),o.appendChild(document.createTextNode(i)),o.addEventListener("click",function(){return n.onToggle(e,o)}),o}),l(this,"onToggle",function(t,e){(0,n.props.onToggle)(t)&&e.classList.toggle("chartogram__chart-toggler--on")}),this.props=e}var n,i,a;return n=t,(i=[{key:"componentDidMount",value:function(){var t=this.props,n=t.rootNode,i=t.data,a=n.querySelector(".chartogram__chart-togglers");e(a);var o=i.y,r=Array.isArray(o),s=0;for(o=r?o:o[Symbol.iterator]();;){var h;if(r){if(s>=o.length)break;h=o[s++]}else{if((s=o.next()).done)break;h=s.value}var l=h;a.appendChild(this.createGraphToggler(l))}}}])&&h(n.prototype,i),a&&h(n,a),t}();function u(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__chart-togglers"></div>\n';var p=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,"setUpListener",function(){!function(t,e,n,i){var a;function o(t,e){n(t,e,a)}function r(){a=t.getBoundingClientRect(),e()}function s(e){if(e.touches.length>1)return c();r(),t.addEventListener("touchend",c),t.addEventListener("touchmove",h),t.addEventListener("touchend",c),t.addEventListener("touchcancel",c),h(e)}function h(t){var e=t.changedTouches[0].clientX,n=t.changedTouches[0].clientY;e<a.left||e>a.left+a.width||n<a.top||n>a.top+a.height?c():o(e,n)}function l(t){o(t.clientX,t.clientY)}function c(){t.removeEventListener("pointermove",l),t.removeEventListener("pointerleave",c),t.removeEventListener("pointercancel",c),t.removeEventListener("touchmove",h),t.removeEventListener("touchend",c),t.removeEventListener("touchcancel",c),i()}function u(){r(),t.addEventListener("pointermove",l),t.addEventListener("pointerleave",c),t.addEventListener("pointercancel",c)}t.addEventListener("touchstart",s),t.addEventListener("pointerenter",u)}(n.props.canvas,function(){},n.onTrack,function(){return n.unmount()})}),d(this,"onTrack",function(t,e,i){var a,o=n.props,r=o.minX,s=o.maxX,h=o.xPoints,l=r+(t-i.left)/i.width*(s-r),c=h.findIndex(function(t){return t>=l}),u=c-1;if((c<0||c>=h.length)&&(c=-1),(u<0||u>=h.length)&&(u=-1),c<0){if(u<0)return n.unmount();a=u}else if(u<0)a=c;else{var d=h[u],p=h[c];a=l-d>p-l?c:u}var m=h[a];m!==n.tooltipForX&&(n.tooltipForX=m,n.tooltip||n.mount(),n.updateTooltip(m,a,i.width))}),d(this,"unmountLine",function(){n.props.canvas.removeChild(n.line),n.line=void 0}),d(this,"mountPoints",function(){var t=n.props.pointsContainer;n.points=n.renderPoints();var e=n.points,i=Array.isArray(e),a=0;for(e=i?e:e[Symbol.iterator]();;){var o;if(i){if(a>=e.length)break;o=e[a++]}else{if((a=e.next()).done)break;o=a.value}var r=o;t.appendChild(r)}}),d(this,"unmountPoints",function(){var t=n.props.pointsContainer,e=n.points,i=Array.isArray(e),a=0;for(e=i?e:e[Symbol.iterator]();;){var o;if(i){if(a>=e.length)break;o=e[a++]}else{if((a=e.next()).done)break;o=a.value}var r=o;t.removeChild(r)}n.points=void 0}),d(this,"updateLinePosition",function(t){n.isLineRendered()||n.mountLine();var e=n.props,i=e.canvasWidth,a=e.aspectRatio,o=e.fixSvgCoordinate,r=e.mapX;n.line.setAttributeNS(null,"x1",o(r(t))),n.line.setAttributeNS(null,"x2",o(r(t))),n.line.setAttributeNS(null,"y1",0),n.line.setAttributeNS(null,"y2",o(i/a))}),d(this,"updatePointPositions",function(t,e){for(var i=n.props,a=i.maxY,o=i.y,r=0,s=0;r<o.length;){if(o[r].isShown){var h=n.points[s],l=o[r].points[t]/a;h.style.left="".concat(100*e,"%"),h.style.bottom="".concat(100*l,"%"),s++}r++}}),this.props=e}var e,n,i;return e=t,(n=[{key:"componentDidMount",value:function(){this.unlisten=this.setUpListener()}},{key:"componentWillUnmount",value:function(){this.unlisten(),this.unmount()}},{key:"componentDidUpdate",value:function(t){this.props!==t&&(this.props=t)}},{key:"mount",value:function(){var t=this.props.container;this.tooltip=this.renderTooltip(),t.appendChild(this.tooltip),this.mountPoints(),this.isLineRendered()||this.mountLine()}},{key:"unmount",value:function(){if(this.tooltip){var t=this.props.container;this.tooltipForX=void 0,t.removeChild(this.tooltip),this.tooltip=void 0,this.unmountPoints(),this.isLineRendered()&&this.unmountLine()}}},{key:"mountLine",value:function(){var t=this.props.canvas;this.line=this.renderLine(),t.insertBefore(this.line,t.querySelector("polyline"))}},{key:"renderTooltip",value:function(){var t=this.props.y,e=document.createElement("div");e.classList.add("chartogram__tooltip");var n=document.createElement("h1");n.classList.add("chartogram__tooltip-header"),e.appendChild(n);var i=document.createElement("dl");i.classList.add("chartogram__tooltip-values"),e.appendChild(i);var a=t,o=Array.isArray(a),r=0;for(a=o?a:a[Symbol.iterator]();;){var s;if(o){if(r>=a.length)break;s=a[r++]}else{if((r=a.next()).done)break;s=r.value}var h=s,l=h.isShown,c=h.color;if(l){var u=document.createElement("dt");u.style.color=c,i.appendChild(u);var d=document.createElement("dd");d.style.color=c,i.appendChild(d)}}return e}},{key:"renderLine",value:function(){var t=document.createElementNS("http://www.w3.org/2000/svg","line");return t.setAttribute("class","chartogram__tooltip-line"),t}},{key:"isLineRendered",value:function(){var t=this.props.canvas;return this.line&&this.line.parentNode===t}},{key:"renderPoints",value:function(){var t=[],e=this.props,n=e.pointsContainer,i=e.y,a=Array.isArray(i),o=0;for(i=a?i:i[Symbol.iterator]();;){var r;if(a){if(o>=i.length)break;r=i[o++]}else{if((o=i.next()).done)break;r=o.value}var s=r;if(s.isShown){var h=document.createElement("div");h.classList.add("chartogram__tooltip-point"),h.style.color=s.color,t.push(h),n.appendChild(h)}}return t}},{key:"updateTooltip",value:function(t,e,n){var i=this.props,a=i.minX,o=(t-a)/(i.maxX-a);this.updateTooltipDate(new Date(t)),this.updateTooltipValues(e),this.updateTooltipPosition(o,n),this.updatePointPositions(e,o),this.updateLinePosition(t)}},{key:"updateTooltipPosition",value:function(t,e){var n=this.props,i=n.tooltipShift,a=n.maxOverflow,o=t*e;o-=void 0===i?40:i;var r=this.tooltip.getBoundingClientRect().width,s=void 0===a?5:a;o<-1*s?o=-1*s:o+r>e+s&&(o=e+s-r),this.tooltip.style.left=o+"px"}},{key:"updateTooltipDate",value:function(t){var e=this.props,n=e.weekdays,i=e.months;this.tooltip.childNodes[0].textContent="".concat(n[t.getDay()],", ").concat(i[t.getMonth()]," ").concat(t.getDate())}},{key:"updateTooltipValues",value:function(t){var e=this.props.y,n=this.tooltip.childNodes[1],i=0,a=e,o=Array.isArray(a),r=0;for(a=o?a:a[Symbol.iterator]();;){var s;if(o){if(r>=a.length)break;s=a[r++]}else{if((r=a.next()).done)break;s=r.value}var h=s,l=h.isShown,c=h.points,u=h.name;l&&(n.childNodes[2*i].textContent=c[t],n.childNodes[2*i+1].textContent=u,i++)}}}])&&u(e.prototype,n),i&&u(e,i),t}();function m(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){g(t,e,n[e])})}return t}function f(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 g(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var y=function(){function t(e,i){var a=this,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Title",r=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),g(this,"onResize",function(t){a.setState({aspectRatio:a.getCanvasAspectRatio()},!1)}),g(this,"onResizeThrottled",n(this.onResize,33)),g(this,"onToggle",function(t){var e=a.state.y.find(function(e){return e.id===t});if(e.isShown&&1===a.state.y.filter(function(t){return t.isShown}).length)return;e.isShown=!e.isShown,a.setState({y:a.state.y});var n=a.calculateMinMaxY(a.state.y),i=n.minY,o=n.maxY,r=n.minYGlobal,s=n.maxYGlobal;return a.transitionState(i,o,r,s,a.state.y.map(function(t){return t.isShown?1:0})),!0}),g(this,"onChangeBounds",function(t,e){var n=a.createState(t,e),i=n.minY,o=n.maxY;delete n.minY,delete n.maxY,a.setState(n,!1),a.transitionState(i,o)}),g(this,"createPolylinePoints",function(t,e){return n=t.map(a.fixSvgCoordinate),i=e.map(a.fixSvgCoordinate),n.map(function(t,e){return"".concat(t,",").concat(i[e])});var n,i}),g(this,"fixSvgCoordinate",function(t){var e=a.props.precisionFactor;return Math.round(t*e)/e}),g(this,"mapX",function(t){var e=a.props.canvasWidth,n=a.state,i=n.minX;return(t-i)/(n.maxX-i)*e}),g(this,"mapY",function(t){var e=a.props.canvasWidth,n=a.state,i=n.minY;return(t-i)/(n.maxY-i)*e/n.aspectRatio}),g(this,"transitionStateTick",function(){var t=a.props.transitionEasing,e=a.state,n=e.transitionStartedAt,i=e.transitionDuration,o=e.transitionUpdatesTimeline,r=e.graphOpacityFrom,s=e.graphOpacityTo,h=e.minYFrom,l=e.minYTo,c=e.maxYFrom,u=e.maxYTo,d=e.minYGlobalFrom,p=e.minYGlobalTo,m=e.maxYGlobalFrom,v=e.maxYGlobalTo,f=Date.now()-n,g=Math.min(f/i,1);g=_[t](g);var y={};void 0!==l&&(y.minY=h+(l-h)*g,y.maxY=c+(u-c)*g,1===g&&(y.minYFrom=void 0,y.minYTo=void 0,y.maxYFrom=void 0,y.maxYTo=void 0)),void 0!==p&&(y.minYGlobal=d+(p-d)*g,y.maxYGlobal=m+(v-m)*g,1===g&&(y.minYGlobalFrom=void 0,y.minYGlobalTo=void 0,y.maxYGlobalFrom=void 0,y.maxYGlobalTo=void 0)),void 0!==s&&(y.graphOpacity=s.map(function(t,e){return r[e]+(s[e]-r[e])*g}),1===g&&(y.graphOpacityFrom=void 0,y.graphOpacityTo=void 0)),a.setState(y,o),a.transition=g<1?requestAnimationFrame(a.transitionStateTick):void 0}),this.props=v({title:o,transitionDuration:250,transitionEasing:"easeOutQuad",gaugeTickMarksCount:6,timelineWindowSize:40,canvasWidth:512,precisionFactor:Math.pow(10,r.precision||3),months:w,weekdays:b},r),this.rootNode=e,this.data=v({},i,{minX:Math.min.apply(Math,m(i.x.points)),maxX:Math.max.apply(Math,m(i.x.points)),y:i.y.map(function(t){return v({},t,{min:Math.min.apply(Math,m(t.points)),max:Math.max.apply(Math,m(t.points))})})})}var i,a,o;return i=t,(a=[{key:"componentDidMount",value:function(){this.rootNode.classList.add("chartogram"),this.rootNode.innerHTML="\n\t\t\t".concat(x.replace("{title}",this.props.title),"\n\t\t\t").concat(s.INITIAL_MARKUP,"\n\t\t\t").concat(c.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.state=this.getInitialState(),this.updateAspectRatio(),this.timeline=new s(this.getTimelineProps()),this.timeline.componentDidMount(),this.togglers=new c(this.getTogglersProps()),this.togglers.componentDidMount(),this.tooltip=new p(this.getTooltipProps()),this.tooltip.componentDidMount(),this.mountGridLines(),this.mountGauges(),this.mountGraphs(),window.addEventListener("resize",this.onResizeThrottled),this.render()}},{key:"componentWillUnmount",value:function(){this.timeline.componentWillUnmount(),this.rootNode.classList.remove("chartogram"),e(this.rootNode),window.removeEventListener("resize",this.onResizeThrottled),this.transition&&cancelAnimationFrame(this.transition)}},{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];t.aspectRatio!==this.state.aspectRatio&&this.updateAspectRatio(t.aspectRatio),this.state=v({},this.state,t),this.render(),e&&this.timeline.componentDidUpdate(this.getTimelineProps()),this.tooltip.componentDidUpdate(this.getTooltipProps())}},{key:"getTimelineProps",value:function(){return{rootNode:this.rootNode,data:this.data,canvasWidth:this.props.canvasWidth,fixSvgCoordinate:this.fixSvgCoordinate,createPolylinePoints:this.createPolylinePoints,fromRatio:this.state.fromRatio,toRatio:this.state.toRatio,minY:this.state.minYGlobal,maxY:this.state.maxYGlobal,y:this.state.y,graphOpacity:this.state.graphOpacity,onChangeBounds:this.onChangeBounds}}},{key:"getTogglersProps",value:function(){return{rootNode:this.rootNode,data:this.data,onToggle:this.onToggle}}},{key:"getTooltipProps",value:function(){return{canvas:this.canvas,container:this.tooltipContainer,pointsContainer:this.canvasWrapper,weekdays:this.props.weekdays,months:this.props.months,canvasWidth:this.props.canvasWidth,aspectRatio:this.state.aspectRatio,mapX:this.mapX,fixSvgCoordinate:this.fixSvgCoordinate,minX:this.state.minX,maxX:this.state.maxX,maxY:this.state.maxY,xPoints:this.state.xPoints,y:this.state.y}}},{key:"getInitialState",value:function(){var t,e=this.props.timelineWindowSize,n=this.data,i=n.minX,a=n.maxX;t=this.data.x.points.length>e?this.data.x.points.length-e:0;var o=(this.data.x.points[t]-i)/(a-i);return v({},this.createState(o,1),{aspectRatio:this.getCanvasAspectRatio(),graphOpacity:this.data.y.map(function(t){return 1})})}},{key:"createState",value:function(t,e){var n,i,a=this,o=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:o.points.findIndex(function(t){return t>r})-1,i=s===this.data.maxX?o.points.length-1:o.points.findIndex(function(t){return t>s});var h=o.points.slice(n,i+1),l=h.slice();h.length>=2&&(o.points[n]!==r&&(l[0]=r),o.points[i]!==s&&(l[l.length-1]=s));var c=this.data.y.map(function(t,e){var l=a.data.y[e].points.slice(n,i+1),c=l.slice();if(h.length>=2){if(o.points[n]!==r){var u=a.data.y[e].points[n],d=u+(a.data.y[e].points[n+1]-u)*((r-a.data.x.points[n])/(a.data.x.points[n+1]-a.data.x.points[n]));c[0]=d}if(o.points[i]!==s){var p=a.data.y[e].points[i],f=a.data.y[e].points[i-1],g=f+(p-f)*((s-a.data.x.points[i-1])/(a.data.x.points[i]-a.data.x.points[i-1]));c[c.length-1]=g}}return v({},a.data.y[e],a.state?a.state.y[e]:{isShown:!0},{points:l,graphPoints:c,min:0,max:Math.max.apply(Math,m(c))})});return v({minX:r,maxX:s,fromIndex:n,toIndex:i,fromRatio:t,toRatio:e,xPoints:h,xGraphPoints:l},this.calculateMinMaxY(c),{y:c})}},{key:"calculateMinMaxY",value:function(t){var e=1/0,n=-1/0,i=t,a=Array.isArray(i),o=0;for(i=a?i:i[Symbol.iterator]();;){var r;if(a){if(o>=i.length)break;r=i[o++]}else{if((o=i.next()).done)break;r=o.value}var s=r;s.isShown&&(e=Math.min(e,s.min),n=Math.max(n,s.max))}var h=1/0,l=-1/0,c=function(){if(d){if(p>=u.length)return"break";m=u[p++]}else{if((p=u.next()).done)return"break";m=p.value}var e=m;t.find(function(t){return t.id===e.id}).isShown&&(h=Math.min(h,e.min),l=Math.max(l,e.max))},u=this.data.y,d=Array.isArray(u),p=0;for(u=d?u:u[Symbol.iterator]();;){var m;if("break"===c())break}return{minY:e,maxY:n,minYGlobal:h=0,maxYGlobal:l}}},{key:"updateAspectRatio",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.state.aspectRatio,e=this.props.canvasWidth;this.canvas.setAttribute("viewBox","0 0 ".concat(e," ").concat(this.fixSvgCoordinate(e/t)))}},{key:"updateGridLine",value:function(t,e){var n=this.state.maxY,i=this.gridLines[t];i.setAttribute("y1",this.fixSvgCoordinate(this.mapY(n-e))),i.setAttribute("y2",this.fixSvgCoordinate(this.mapY(n-e)))}},{key:"render",value:function(){var t=this,e=this.props.gaugeTickMarksCount,n=this.state,i=n.y,a=n.minX,o=n.maxX,r=n.minY,s=n.maxY,h=n.graphOpacity,l=r,c=function(t,e){for(t=Math.floor(t);;){if(t<e)return e;if(t%e==0)return t;t--}}(s,10),u=(s-r)/(c-l);(function(t,e,n){for(var i=new Array(n),a=0;a<n;)i[a]=t+a*(e-t)/(n-1),a++;return i})(l,c,e).forEach(function(e,n){return t.updateGridLine(n,e)});for(var d=0;d<i.length;){var p=i[d],m=p.isShown,v=p.graphPoints,f=p.color,g=h[d];m||g>0?this.graphs[d]?this.updateGraph(d,v,g):this.mountGraph(d,v,f,g):this.graphs[d]&&this.unmountGraph(d),d++}this.updateGauges(a,o,l,c,u)}},{key:"renderGraph",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,i=document.createElementNS("http://www.w3.org/2000/svg","polyline");return i.setAttribute("stroke",e),i.classList.add("chartogram__graph"),this.updateGraph(i,t,n),i}},{key:"mountGridLines",value:function(){var t=this.props.gaugeTickMarksCount;this.gridLines=[];for(var e=0;e<t;){var n=this.renderGridLine(0);this.gridLines.push(n),this.canvas.appendChild(n),e++}}},{key:"mountGraphs",value:function(){var t=this;this.graphs=[],this.state.y.forEach(function(e,n){var i=e.graphPoints,a=e.color;t.mountGraph(n,i,a)})}},{key:"mountGraph",value:function(t,e,n,i){var a=this.renderGraph(e,n,i);this.graphs[t]=a,this.canvas.appendChild(a)}},{key:"unmountGraph",value:function(t){this.canvas.removeChild(this.graphs[t]),this.graphs[t]=void 0}},{key:"updateGraph",value:function(t,e,n){var i=this,a=this.state,o=a.xGraphPoints,r=a.maxY;"number"==typeof t&&(t=this.graphs[t]),t.setAttribute("points",this.createPolylinePoints(o.map(this.mapX),e.map(function(t){return i.mapY(r-t)})).join(" ")),1!==n&&(t.style.opacity=n)}},{key:"transitionState",value:function(t,e,n,i,a){var o=this.props.transitionDuration;this.transition&&cancelAnimationFrame(this.transition);var r=o;if(void 0!==t){var s=this.state.maxY-this.state.minY,h=Math.abs(e-this.state.maxY)/s,l=Math.abs(t-this.state.minY)/s,c=Math.max(l,h);r=o*Math.max(.2,2*Math.min(c,.5))}a||(r/=2);var u={transitionStartedAt:Date.now(),transitionDuration:r};void 0!==t&&(u.minYFrom=this.state.minY,u.maxYFrom=this.state.maxY,u.minYTo=t,u.maxYTo=e),void 0!==a&&(u.graphOpacityFrom=this.state.graphOpacity,u.graphOpacityTo=a),void 0!==n&&(u.minYGlobalFrom=this.state.minYGlobal,u.maxYGlobalFrom=this.state.maxYGlobal,u.minYGlobalTo=n,u.maxYGlobalTo=i);var d=void 0!==a||void 0!==n;u.transitionUpdatesTimeline=d,this.setState(u,d),this.transition=requestAnimationFrame(this.transitionStateTick)}},{key:"renderGridLine",value:function(t){var e=this.state,n=e.minX,i=e.maxX,a=(e.minY,e.maxY),o=document.createElementNS("http://www.w3.org/2000/svg","line");return o.classList.add("chartogram__grid-line"),o.setAttribute("x1",this.fixSvgCoordinate(this.mapX(n))),o.setAttribute("x2",this.fixSvgCoordinate(this.mapX(i))),o.setAttribute("y1",this.fixSvgCoordinate(this.mapY(a-t))),o.setAttribute("y2",this.fixSvgCoordinate(this.mapY(a-t))),o}},{key:"mountGauges",value:function(){for(var t=this.props.gaugeTickMarksCount,e=0;e<t;)this.xAxis.appendChild(document.createElement("div")),this.yAxis.appendChild(document.createElement("div")),e++}},{key:"updateGauges",value:function(t,e,n,i,a){var o=this.props,r=o.months,s=o.gaugeTickMarksCount;this.updateGauge(this.xAxis,t,e,s,function(t){var e=new Date(t);return"".concat(r[e.getMonth()]," ").concat(e.getDate())}),this.updateGauge(this.yAxis,n,i,s),this.yAxis.style.height="".concat(100/a,"%")}},{key:"updateGauge",value:function(t,e,n,i,a){for(var o=0;o<i;){var r=t.childNodes[o],s=e+o*(n-e)/(i-1);a&&(s=a(s)),r.textContent=s,o++}}}])&&f(i.prototype,a),o&&f(i,o),t}(),w=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],b=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],x='\n\t<header class="chartogram__header">\n\t\t<h1 class="chartogram__title">{title}</h1>\n\t</header>\n\t<div class="chartogram__plan-with-axes">\n\t\t<div class="chartogram__plan">\n\t\t\t<div class="chartogram__top-border"></div>\n\t\t\t<div class="chartogram__canvas-wrapper">\n\t\t\t\t<svg class="chartogram__canvas"></svg>\n\t\t\t\t<div class="chartogram__x"></div>\n\t\t\t\t<div class="chartogram__y-wrapper">\n\t\t\t\t\t<div class="chartogram__y"></div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n',_={linear:function(t){return t},easeInOutSin:function(t){return(1+Math.sin(Math.PI*t-Math.PI/2))/2},easeInOutQuad:function(t){return t<.5?2*t*t:(4-2*t)*t-1},easeInOutCubic:function(t){return t<.5?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1},easeOutCubic:function(t){return--t*t*t+1},easeOutQuad:function(t){return t*(2-t)}};return function(t,e,n,i){var a=new y(t,e,n,i);return a.componentDidMount(),function(){a.componentWillUnmount()}}}); | ||
//# sourceMappingURL=chartogram.js.map |
@@ -36,2 +36,4 @@ "use strict"; | ||
var SVG_XMLNS = 'http://www.w3.org/2000/svg'; | ||
var Chartogram = | ||
@@ -136,2 +138,3 @@ /*#__PURE__*/ | ||
transitionDuration = _this$state3.transitionDuration, | ||
transitionUpdatesTimeline = _this$state3.transitionUpdatesTimeline, | ||
graphOpacityFrom = _this$state3.graphOpacityFrom, | ||
@@ -187,3 +190,3 @@ graphOpacityTo = _this$state3.graphOpacityTo, | ||
_this.setState(state); | ||
_this.setState(state, transitionUpdatesTimeline); | ||
@@ -197,31 +200,2 @@ if (ratio < 1) { | ||
_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; | ||
var line = document.createElement('line'); | ||
line.classList.add('chartogram__grid-line'); | ||
line.setAttribute('x1', _this.fixSvgCoordinate(_this.mapX(minX))); | ||
line.setAttribute('x2', _this.fixSvgCoordinate(_this.mapX(maxX))); | ||
line.setAttribute('y1', _this.fixSvgCoordinate(_this.mapY(maxY - y))); | ||
line.setAttribute('y2', _this.fixSvgCoordinate(_this.mapY(maxY - y))); | ||
return line; | ||
}); | ||
_defineProperty(this, "drawGauges", function (minX, maxX, minY, maxY, yAxisScale) { | ||
var _this$props = _this.props, | ||
gaugeTickMarksCount = _this$props.gaugeTickMarksCount, | ||
months = _this$props.months; | ||
(0, _utility.clearElement)(_this.xAxis); | ||
(0, _utility.clearElement)(_this.yAxis); | ||
(0, _utility.renderGaugeLabels)(_this.xAxis, minX, maxX, gaugeTickMarksCount, function (timestamp) { | ||
var date = new Date(timestamp); | ||
return "".concat(months[date.getMonth()], " ").concat(date.getDate()); | ||
}); | ||
(0, _utility.renderGaugeLabels)(_this.yAxis, minY, maxY, gaugeTickMarksCount); | ||
_this.yAxis.style.height = "".concat(100 / yAxisScale, "%"); | ||
}); | ||
this.props = _objectSpread({ | ||
@@ -263,2 +237,3 @@ title: title, | ||
this.state = this.getInitialState(); | ||
this.updateAspectRatio(); | ||
this.timeline = new _Timeline.default(this.getTimelineProps()); | ||
@@ -269,3 +244,6 @@ this.timeline.componentDidMount(); | ||
this.tooltip = new _Tooltip.default(this.getTooltipProps()); | ||
this.tooltip.componentDidMount(); // Add window resize event listener. | ||
this.tooltip.componentDidMount(); | ||
this.mountGridLines(); | ||
this.mountGauges(); | ||
this.mountGraphs(); // Add window resize event listener. | ||
@@ -298,2 +276,7 @@ window.addEventListener('resize', this.onResizeThrottled); | ||
var renderTimeline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
if (newState.aspectRatio !== this.state.aspectRatio) { | ||
this.updateAspectRatio(newState.aspectRatio); | ||
} | ||
this.state = _objectSpread({}, this.state, newState); | ||
@@ -319,4 +302,4 @@ this.render(); | ||
toRatio: this.state.toRatio, | ||
minYGlobal: this.state.minYGlobal, | ||
maxYGlobal: this.state.maxYGlobal, | ||
minY: this.state.minYGlobal, | ||
maxY: this.state.maxYGlobal, | ||
y: this.state.y, | ||
@@ -539,2 +522,18 @@ graphOpacity: this.state.graphOpacity, | ||
}, { | ||
key: "updateAspectRatio", | ||
value: function updateAspectRatio() { | ||
var aspectRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.aspectRatio; | ||
var canvasWidth = this.props.canvasWidth; // Set canvas `viewBox`. | ||
this.canvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(this.fixSvgCoordinate(canvasWidth / aspectRatio))); | ||
} | ||
}, { | ||
key: "updateGridLine", | ||
value: function updateGridLine(i, y) { | ||
var maxY = this.state.maxY; | ||
var line = this.gridLines[i]; | ||
line.setAttribute('y1', this.fixSvgCoordinate(this.mapY(maxY - y))); | ||
line.setAttribute('y2', this.fixSvgCoordinate(this.mapY(maxY - y))); | ||
} | ||
}, { | ||
key: "render", | ||
@@ -544,72 +543,116 @@ value: function render() { | ||
var _this$props2 = this.props, | ||
canvasWidth = _this$props2.canvasWidth, | ||
gaugeTickMarksCount = _this$props2.gaugeTickMarksCount; | ||
var _this$state5 = this.state, | ||
minX = _this$state5.minX, | ||
maxX = _this$state5.maxX, | ||
minY = _this$state5.minY, | ||
maxY = _this$state5.maxY, | ||
xGraphPoints = _this$state5.xGraphPoints, | ||
aspectRatio = _this$state5.aspectRatio, | ||
graphOpacity = _this$state5.graphOpacity; // Clear canvas. | ||
var gaugeTickMarksCount = this.props.gaugeTickMarksCount; | ||
var _this$state4 = this.state, | ||
y = _this$state4.y, | ||
minX = _this$state4.minX, | ||
maxX = _this$state4.maxX, | ||
minY = _this$state4.minY, | ||
maxY = _this$state4.maxY, | ||
graphOpacity = _this$state4.graphOpacity; // Calculate grid lines' coordinates. | ||
(0, _utility.clearElement)(this.canvas); // Set canvas `viewBox`. | ||
this.canvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(this.fixSvgCoordinate(canvasWidth / aspectRatio))); // Calculate grid lines' coordinates. | ||
var minY_ = minY; | ||
var maxY_ = (0, _utility.getLowerSiblingDivisibleBy)(maxY, 10); | ||
var yAxisScale = (maxY - minY) / (maxY_ - minY_); | ||
var yAxisTickMarks = (0, _utility.divideInterval)(minY_, maxY_, gaugeTickMarksCount); // Draw grid lines. | ||
var yAxisTickMarks = (0, _utility.divideInterval)(minY_, maxY_, gaugeTickMarksCount); // Update grid lines. | ||
for (var _iterator3 = yAxisTickMarks, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
var _ref3; | ||
yAxisTickMarks.forEach(function (y, i) { | ||
return _this3.updateGridLine(i, y); | ||
}); // Update graphs. | ||
if (_isArray3) { | ||
if (_i3 >= _iterator3.length) break; | ||
_ref3 = _iterator3[_i3++]; | ||
} else { | ||
_i3 = _iterator3.next(); | ||
if (_i3.done) break; | ||
_ref3 = _i3.value; | ||
var i = 0; | ||
while (i < y.length) { | ||
var _y$i = y[i], | ||
isShown = _y$i.isShown, | ||
graphPoints = _y$i.graphPoints, | ||
color = _y$i.color; | ||
var opacity = graphOpacity[i]; // Update graph. | ||
if (isShown || opacity > 0) { | ||
if (this.graphs[i]) { | ||
this.updateGraph(i, graphPoints, opacity); | ||
} else { | ||
this.mountGraph(i, graphPoints, color, opacity); | ||
} | ||
} else if (this.graphs[i]) { | ||
this.unmountGraph(i); | ||
} | ||
var y = _ref3; | ||
this.canvas.appendChild(this.createGridLine(y)); | ||
} // Draw charts. | ||
i++; | ||
} // Update gauges. | ||
this.updateGauges(minX, maxX, minY_, maxY_, yAxisScale); | ||
} | ||
}, { | ||
key: "renderGraph", | ||
value: function renderGraph(graphPoints, color) { | ||
var opacity = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; | ||
var graph = document.createElementNS(SVG_XMLNS, 'polyline'); | ||
graph.setAttribute('stroke', color); | ||
graph.classList.add('chartogram__graph'); | ||
this.updateGraph(graph, graphPoints, opacity); | ||
return graph; | ||
} | ||
}, { | ||
key: "mountGridLines", | ||
value: function mountGridLines() { | ||
var gaugeTickMarksCount = this.props.gaugeTickMarksCount; | ||
this.gridLines = []; | ||
var i = 0; | ||
while (i < this.state.y.length) { | ||
var _this$state$y$i = this.state.y[i], | ||
color = _this$state$y$i.color, | ||
graphPoints = _this$state$y$i.graphPoints, | ||
isShown = _this$state$y$i.isShown; | ||
var opacity = graphOpacity[i]; // Draw chart. | ||
while (i < gaugeTickMarksCount) { | ||
var line = this.renderGridLine(0); | ||
this.gridLines.push(line); | ||
this.canvas.appendChild(line); | ||
i++; | ||
} | ||
} | ||
}, { | ||
key: "mountGraphs", | ||
value: function mountGraphs() { | ||
var _this4 = this; | ||
if (isShown || opacity > 0) { | ||
var graph = document.createElement('polyline'); | ||
graph.setAttribute('stroke', color); | ||
graph.setAttribute('points', this.createPolylinePoints(xGraphPoints.map(this.mapX), graphPoints.map(function (y) { | ||
return _this3.mapY(maxY - y); | ||
})).join(' ')); | ||
graph.classList.add('chartogram__graph'); | ||
this.graphs = []; | ||
var y = this.state.y; | ||
y.forEach(function (_ref3, i) { | ||
var graphPoints = _ref3.graphPoints, | ||
color = _ref3.color; | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity; | ||
} | ||
_this4.mountGraph(i, graphPoints, color); | ||
}); | ||
} | ||
}, { | ||
key: "mountGraph", | ||
value: function mountGraph(i, graphPoints, color, opacity) { | ||
var graph = this.renderGraph(graphPoints, color, opacity); | ||
this.graphs[i] = graph; | ||
this.canvas.appendChild(graph); | ||
} | ||
}, { | ||
key: "unmountGraph", | ||
value: function unmountGraph(i) { | ||
this.canvas.removeChild(this.graphs[i]); | ||
this.graphs[i] = undefined; | ||
} | ||
}, { | ||
key: "updateGraph", | ||
value: function updateGraph(graph, graphPoints, opacity) { | ||
var _this5 = this; | ||
this.canvas.appendChild(graph); | ||
} | ||
var _this$state5 = this.state, | ||
xGraphPoints = _this$state5.xGraphPoints, | ||
maxY = _this$state5.maxY; | ||
i++; | ||
} // 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 | ||
if (typeof graph === 'number') { | ||
graph = this.graphs[graph]; | ||
} | ||
graph.setAttribute('points', this.createPolylinePoints(xGraphPoints.map(this.mapX), graphPoints.map(function (y) { | ||
return _this5.mapY(maxY - y); | ||
})).join(' ')); | ||
this.canvas.innerHTML += ''; // Draw gauges. | ||
this.drawGauges(minX, maxX, minY_, maxY_, yAxisScale); | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity; | ||
} | ||
} | ||
@@ -663,6 +706,66 @@ }, { | ||
this.setState(state); // Place in a `setState()` callback in case of React. | ||
var shouldUpdateTimeline = graphOpacity !== undefined || minYGlobal !== undefined; | ||
state.transitionUpdatesTimeline = shouldUpdateTimeline; | ||
this.setState(state, shouldUpdateTimeline); // Place the following in a `setState()` callback in case of React. | ||
this.transition = requestAnimationFrame(this.transitionStateTick); | ||
} | ||
}, { | ||
key: "renderGridLine", | ||
value: function renderGridLine(y) { | ||
var _this$state6 = this.state, | ||
minX = _this$state6.minX, | ||
maxX = _this$state6.maxX, | ||
minY = _this$state6.minY, | ||
maxY = _this$state6.maxY; | ||
var line = document.createElementNS(SVG_XMLNS, 'line'); | ||
line.classList.add('chartogram__grid-line'); | ||
line.setAttribute('x1', this.fixSvgCoordinate(this.mapX(minX))); | ||
line.setAttribute('x2', this.fixSvgCoordinate(this.mapX(maxX))); | ||
line.setAttribute('y1', this.fixSvgCoordinate(this.mapY(maxY - y))); | ||
line.setAttribute('y2', this.fixSvgCoordinate(this.mapY(maxY - y))); | ||
return line; | ||
} | ||
}, { | ||
key: "mountGauges", | ||
value: function mountGauges() { | ||
var gaugeTickMarksCount = this.props.gaugeTickMarksCount; | ||
var i = 0; | ||
while (i < gaugeTickMarksCount) { | ||
this.xAxis.appendChild(document.createElement('div')); | ||
this.yAxis.appendChild(document.createElement('div')); | ||
i++; | ||
} | ||
} | ||
}, { | ||
key: "updateGauges", | ||
value: function updateGauges(minX, maxX, minY, maxY, yAxisScale) { | ||
var _this$props = this.props, | ||
months = _this$props.months, | ||
gaugeTickMarksCount = _this$props.gaugeTickMarksCount; | ||
this.updateGauge(this.xAxis, minX, maxX, gaugeTickMarksCount, function (timestamp) { | ||
var date = new Date(timestamp); | ||
return "".concat(months[date.getMonth()], " ").concat(date.getDate()); | ||
}); | ||
this.updateGauge(this.yAxis, minY, maxY, gaugeTickMarksCount); | ||
this.yAxis.style.height = "".concat(100 / yAxisScale, "%"); | ||
} | ||
}, { | ||
key: "updateGauge", | ||
value: function updateGauge(gauge, min, max, tickMarksCount, transform) { | ||
var i = 0; | ||
while (i < tickMarksCount) { | ||
var tickMark = gauge.childNodes[i]; | ||
var value = min + i * (max - min) / (tickMarksCount - 1); | ||
if (transform) { | ||
value = transform(value); | ||
} | ||
tickMark.textContent = value; | ||
i++; | ||
} | ||
} | ||
}]); | ||
@@ -669,0 +772,0 @@ |
@@ -28,2 +28,5 @@ "use strict"; | ||
var TIMELINE_GRAPH_MAX_POINTS = 80; | ||
var SVG_XMLNS = 'http://www.w3.org/2000/svg'; | ||
var Timeline = | ||
@@ -46,2 +49,6 @@ /*#__PURE__*/ | ||
_defineProperty(this, "setState", function (newState) { | ||
if (newState.aspectRatio !== _this.state.aspectRatio) { | ||
_this.updateAspectRatio(newState.aspectRatio); | ||
} | ||
_this.state = _objectSpread({}, _this.state, newState); | ||
@@ -64,6 +71,6 @@ | ||
canvasWidth = _this$props2.canvasWidth, | ||
minYGlobal = _this$props2.minYGlobal, | ||
maxYGlobal = _this$props2.maxYGlobal; | ||
minY = _this$props2.minY, | ||
maxY = _this$props2.maxY; | ||
var aspectRatio = _this.state.aspectRatio; | ||
return (y - minYGlobal) / (maxYGlobal - minYGlobal) * canvasWidth / aspectRatio; | ||
return (y - minY) / (maxY - minY) * canvasWidth / aspectRatio; | ||
}); | ||
@@ -176,2 +183,3 @@ | ||
}; | ||
this.updateAspectRatio(); | ||
this.setUpTimelineWindowHandle('left'); | ||
@@ -183,2 +191,3 @@ this.setUpTimelineWindowHandle('right'); | ||
this.onChangeBounds(this.props.fromRatio, this.props.toRatio); | ||
this.mountGraphs(); | ||
this.render(); | ||
@@ -193,2 +202,12 @@ } | ||
}, { | ||
key: "updateAspectRatio", | ||
value: function updateAspectRatio() { | ||
var aspectRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.aspectRatio; | ||
var _this$props3 = this.props, | ||
canvasWidth = _this$props3.canvasWidth, | ||
fixSvgCoordinate = _this$props3.fixSvgCoordinate; // Set canvas `viewBox`. | ||
this.timelineCanvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(fixSvgCoordinate(canvasWidth / aspectRatio))); | ||
} | ||
}, { | ||
key: "getCanvasAspectRatio", | ||
@@ -204,16 +223,7 @@ value: function getCanvasAspectRatio() { | ||
var _this$props3 = this.props, | ||
canvasWidth = _this$props3.canvasWidth, | ||
y = _this$props3.y, | ||
data = _this$props3.data, | ||
maxYGlobal = _this$props3.maxYGlobal, | ||
fixSvgCoordinate = _this$props3.fixSvgCoordinate, | ||
createPolylinePoints = _this$props3.createPolylinePoints, | ||
graphOpacity = _this$props3.graphOpacity; | ||
var aspectRatio = this.state.aspectRatio; // Clear canvas. | ||
var _this$props4 = this.props, | ||
y = _this$props4.y, | ||
data = _this$props4.data, | ||
graphOpacity = _this$props4.graphOpacity; // Update graphs. | ||
(0, _utility.clearElement)(this.timelineCanvas); // Set canvas `viewBox`. | ||
this.timelineCanvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(fixSvgCoordinate(canvasWidth / aspectRatio))); // Draw graphs. | ||
var i = 0; | ||
@@ -224,11 +234,11 @@ | ||
id = _data$y$i.id, | ||
color = _data$y$i.color, | ||
points = _data$y$i.points; | ||
var opacity = graphOpacity[i]; | ||
points = _data$y$i.points, | ||
color = _data$y$i.color; | ||
var isShown = y.find(function (_) { | ||
return _.id === id; | ||
}).isShown; | ||
var opacity = graphOpacity[i]; // Update graph. | ||
if (isShown || opacity > 0) { | ||
var _simplifyGraph = (0, _utility.simplifyGraph)(data.x.points, points, 80), | ||
var _simplifyGraph = (0, _utility.simplifyGraph)(data.x.points, points, TIMELINE_GRAPH_MAX_POINTS), | ||
_simplifyGraph2 = _slicedToArray(_simplifyGraph, 2), | ||
@@ -238,14 +248,9 @@ _x = _simplifyGraph2[0], | ||
var graph = document.createElement('polyline'); | ||
graph.setAttribute('stroke', color); | ||
graph.setAttribute('points', createPolylinePoints(_x.map(_this2.mapX), _y.map(function (y) { | ||
return _this2.mapY(maxYGlobal - y); | ||
})).join(' ')); | ||
graph.classList.add('chartogram__graph'); | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity; | ||
if (_this2.graphs[i]) { | ||
_this2.updateGraph(i, _x, _y, opacity); | ||
} else { | ||
_this2.mountGraph(i, _x, _y, color, opacity); | ||
} | ||
_this2.timelineCanvas.appendChild(graph); | ||
} else if (_this2.graphs[i]) { | ||
_this2.unmountGraph(i); | ||
} | ||
@@ -258,9 +263,63 @@ | ||
_loop(); | ||
} // 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 | ||
} | ||
} | ||
}, { | ||
key: "renderGraph", | ||
value: function renderGraph(x, y, color) { | ||
var opacity = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; | ||
var graph = document.createElementNS(SVG_XMLNS, 'polyline'); | ||
graph.setAttribute('stroke', color); | ||
this.updateGraph(graph, x, y, opacity); | ||
graph.classList.add('chartogram__graph'); | ||
return graph; | ||
} | ||
}, { | ||
key: "mountGraphs", | ||
value: function mountGraphs() { | ||
var _this3 = this; | ||
this.graphs = []; | ||
var data = this.props.data; | ||
data.y.forEach(function (_ref, i) { | ||
var points = _ref.points, | ||
color = _ref.color; | ||
this.timelineCanvas.innerHTML += ''; | ||
_this3.mountGraph(i, data.x.points, points, color); | ||
}); | ||
} | ||
}, { | ||
key: "mountGraph", | ||
value: function mountGraph(i, x, y, color, opacity) { | ||
var graph = this.renderGraph(x, y, color, opacity); | ||
this.graphs[i] = graph; | ||
this.timelineCanvas.appendChild(graph); | ||
} | ||
}, { | ||
key: "unmountGraph", | ||
value: function unmountGraph(i) { | ||
this.timelineCanvas.removeChild(this.graphs[i]); | ||
this.graphs[i] = undefined; | ||
} | ||
}, { | ||
key: "updateGraph", | ||
value: function updateGraph(graph, x, y, opacity) { | ||
var _this4 = this; | ||
var _this$props5 = this.props, | ||
maxY = _this$props5.maxY, | ||
createPolylinePoints = _this$props5.createPolylinePoints; | ||
if (typeof graph === 'number') { | ||
graph = this.graphs[graph]; | ||
} | ||
graph.setAttribute('points', createPolylinePoints(x.map(this.mapX), y.map(function (y) { | ||
return _this4.mapY(maxY - y); | ||
})).join(' ')); | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity; | ||
} | ||
} | ||
}, { | ||
key: "onChangeBounds", | ||
@@ -267,0 +326,0 @@ value: function onChangeBounds(from, to) { |
@@ -18,2 +18,4 @@ "use strict"; | ||
var SVG_XMLNS = 'http://www.w3.org/2000/svg'; | ||
var Tooltip = | ||
@@ -283,4 +285,3 @@ /*#__PURE__*/ | ||
value: function renderLine() { | ||
var xmlns = 'http://www.w3.org/2000/svg'; | ||
var line = document.createElementNS(xmlns, 'line'); | ||
var line = document.createElementNS(SVG_XMLNS, 'line'); | ||
line.setAttribute('class', 'chartogram__tooltip-line'); | ||
@@ -287,0 +288,0 @@ return line; |
@@ -10,3 +10,2 @@ "use strict"; | ||
exports.divideInterval = divideInterval; | ||
exports.renderGaugeLabels = renderGaugeLabels; | ||
exports.throttle = throttle; | ||
@@ -65,19 +64,2 @@ exports.simplifyGraph = simplifyGraph; | ||
function renderGaugeLabels(element, min, max, GAUGE_TICK_MARKS_COUNT, transform) { | ||
var i = 0; | ||
while (i < GAUGE_TICK_MARKS_COUNT) { | ||
var tickMark = document.createElement('div'); | ||
var value = min + i * (max - min) / (GAUGE_TICK_MARKS_COUNT - 1); | ||
if (transform) { | ||
value = transform(value); | ||
} | ||
tickMark.appendChild(document.createTextNode(value)); | ||
element.appendChild(tickMark); | ||
i++; | ||
} | ||
} | ||
function throttle(func, interval) { | ||
@@ -84,0 +66,0 @@ var timeout; |
@@ -19,6 +19,7 @@ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
import { clearElement, commaJoin, getLowerSiblingDivisibleBy, divideInterval, throttle, renderGaugeLabels } from './utility'; | ||
import { clearElement, commaJoin, getLowerSiblingDivisibleBy, divideInterval, throttle } from './utility'; | ||
import Timeline from './Timeline'; | ||
import Togglers from './Togglers'; | ||
import Tooltip from './Tooltip'; | ||
var SVG_XMLNS = 'http://www.w3.org/2000/svg'; | ||
@@ -124,2 +125,3 @@ var Chartogram = | ||
transitionDuration = _this$state3.transitionDuration, | ||
transitionUpdatesTimeline = _this$state3.transitionUpdatesTimeline, | ||
graphOpacityFrom = _this$state3.graphOpacityFrom, | ||
@@ -175,3 +177,3 @@ graphOpacityTo = _this$state3.graphOpacityTo, | ||
_this.setState(state); | ||
_this.setState(state, transitionUpdatesTimeline); | ||
@@ -185,31 +187,2 @@ if (ratio < 1) { | ||
_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; | ||
var line = document.createElement('line'); | ||
line.classList.add('chartogram__grid-line'); | ||
line.setAttribute('x1', _this.fixSvgCoordinate(_this.mapX(minX))); | ||
line.setAttribute('x2', _this.fixSvgCoordinate(_this.mapX(maxX))); | ||
line.setAttribute('y1', _this.fixSvgCoordinate(_this.mapY(maxY - y))); | ||
line.setAttribute('y2', _this.fixSvgCoordinate(_this.mapY(maxY - y))); | ||
return line; | ||
}); | ||
_defineProperty(this, "drawGauges", function (minX, maxX, minY, maxY, yAxisScale) { | ||
var _this$props = _this.props, | ||
gaugeTickMarksCount = _this$props.gaugeTickMarksCount, | ||
months = _this$props.months; | ||
clearElement(_this.xAxis); | ||
clearElement(_this.yAxis); | ||
renderGaugeLabels(_this.xAxis, minX, maxX, gaugeTickMarksCount, function (timestamp) { | ||
var date = new Date(timestamp); | ||
return "".concat(months[date.getMonth()], " ").concat(date.getDate()); | ||
}); | ||
renderGaugeLabels(_this.yAxis, minY, maxY, gaugeTickMarksCount); | ||
_this.yAxis.style.height = "".concat(100 / yAxisScale, "%"); | ||
}); | ||
this.props = _objectSpread({ | ||
@@ -251,2 +224,3 @@ title: title, | ||
this.state = this.getInitialState(); | ||
this.updateAspectRatio(); | ||
this.timeline = new Timeline(this.getTimelineProps()); | ||
@@ -257,3 +231,6 @@ this.timeline.componentDidMount(); | ||
this.tooltip = new Tooltip(this.getTooltipProps()); | ||
this.tooltip.componentDidMount(); // Add window resize event listener. | ||
this.tooltip.componentDidMount(); | ||
this.mountGridLines(); | ||
this.mountGauges(); | ||
this.mountGraphs(); // Add window resize event listener. | ||
@@ -286,2 +263,7 @@ window.addEventListener('resize', this.onResizeThrottled); | ||
var renderTimeline = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; | ||
if (newState.aspectRatio !== this.state.aspectRatio) { | ||
this.updateAspectRatio(newState.aspectRatio); | ||
} | ||
this.state = _objectSpread({}, this.state, newState); | ||
@@ -307,4 +289,4 @@ this.render(); | ||
toRatio: this.state.toRatio, | ||
minYGlobal: this.state.minYGlobal, | ||
maxYGlobal: this.state.maxYGlobal, | ||
minY: this.state.minYGlobal, | ||
maxY: this.state.maxYGlobal, | ||
y: this.state.y, | ||
@@ -527,2 +509,18 @@ graphOpacity: this.state.graphOpacity, | ||
}, { | ||
key: "updateAspectRatio", | ||
value: function updateAspectRatio() { | ||
var aspectRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.aspectRatio; | ||
var canvasWidth = this.props.canvasWidth; // Set canvas `viewBox`. | ||
this.canvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(this.fixSvgCoordinate(canvasWidth / aspectRatio))); | ||
} | ||
}, { | ||
key: "updateGridLine", | ||
value: function updateGridLine(i, y) { | ||
var maxY = this.state.maxY; | ||
var line = this.gridLines[i]; | ||
line.setAttribute('y1', this.fixSvgCoordinate(this.mapY(maxY - y))); | ||
line.setAttribute('y2', this.fixSvgCoordinate(this.mapY(maxY - y))); | ||
} | ||
}, { | ||
key: "render", | ||
@@ -532,72 +530,116 @@ value: function render() { | ||
var _this$props2 = this.props, | ||
canvasWidth = _this$props2.canvasWidth, | ||
gaugeTickMarksCount = _this$props2.gaugeTickMarksCount; | ||
var _this$state5 = this.state, | ||
minX = _this$state5.minX, | ||
maxX = _this$state5.maxX, | ||
minY = _this$state5.minY, | ||
maxY = _this$state5.maxY, | ||
xGraphPoints = _this$state5.xGraphPoints, | ||
aspectRatio = _this$state5.aspectRatio, | ||
graphOpacity = _this$state5.graphOpacity; // Clear canvas. | ||
var gaugeTickMarksCount = this.props.gaugeTickMarksCount; | ||
var _this$state4 = this.state, | ||
y = _this$state4.y, | ||
minX = _this$state4.minX, | ||
maxX = _this$state4.maxX, | ||
minY = _this$state4.minY, | ||
maxY = _this$state4.maxY, | ||
graphOpacity = _this$state4.graphOpacity; // Calculate grid lines' coordinates. | ||
clearElement(this.canvas); // Set canvas `viewBox`. | ||
this.canvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(this.fixSvgCoordinate(canvasWidth / aspectRatio))); // Calculate grid lines' coordinates. | ||
var minY_ = minY; | ||
var maxY_ = getLowerSiblingDivisibleBy(maxY, 10); | ||
var yAxisScale = (maxY - minY) / (maxY_ - minY_); | ||
var yAxisTickMarks = divideInterval(minY_, maxY_, gaugeTickMarksCount); // Draw grid lines. | ||
var yAxisTickMarks = divideInterval(minY_, maxY_, gaugeTickMarksCount); // Update grid lines. | ||
for (var _iterator3 = yAxisTickMarks, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { | ||
var _ref3; | ||
yAxisTickMarks.forEach(function (y, i) { | ||
return _this3.updateGridLine(i, y); | ||
}); // Update graphs. | ||
if (_isArray3) { | ||
if (_i3 >= _iterator3.length) break; | ||
_ref3 = _iterator3[_i3++]; | ||
} else { | ||
_i3 = _iterator3.next(); | ||
if (_i3.done) break; | ||
_ref3 = _i3.value; | ||
var i = 0; | ||
while (i < y.length) { | ||
var _y$i = y[i], | ||
isShown = _y$i.isShown, | ||
graphPoints = _y$i.graphPoints, | ||
color = _y$i.color; | ||
var opacity = graphOpacity[i]; // Update graph. | ||
if (isShown || opacity > 0) { | ||
if (this.graphs[i]) { | ||
this.updateGraph(i, graphPoints, opacity); | ||
} else { | ||
this.mountGraph(i, graphPoints, color, opacity); | ||
} | ||
} else if (this.graphs[i]) { | ||
this.unmountGraph(i); | ||
} | ||
var y = _ref3; | ||
this.canvas.appendChild(this.createGridLine(y)); | ||
} // Draw charts. | ||
i++; | ||
} // Update gauges. | ||
this.updateGauges(minX, maxX, minY_, maxY_, yAxisScale); | ||
} | ||
}, { | ||
key: "renderGraph", | ||
value: function renderGraph(graphPoints, color) { | ||
var opacity = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; | ||
var graph = document.createElementNS(SVG_XMLNS, 'polyline'); | ||
graph.setAttribute('stroke', color); | ||
graph.classList.add('chartogram__graph'); | ||
this.updateGraph(graph, graphPoints, opacity); | ||
return graph; | ||
} | ||
}, { | ||
key: "mountGridLines", | ||
value: function mountGridLines() { | ||
var gaugeTickMarksCount = this.props.gaugeTickMarksCount; | ||
this.gridLines = []; | ||
var i = 0; | ||
while (i < this.state.y.length) { | ||
var _this$state$y$i = this.state.y[i], | ||
color = _this$state$y$i.color, | ||
graphPoints = _this$state$y$i.graphPoints, | ||
isShown = _this$state$y$i.isShown; | ||
var opacity = graphOpacity[i]; // Draw chart. | ||
while (i < gaugeTickMarksCount) { | ||
var line = this.renderGridLine(0); | ||
this.gridLines.push(line); | ||
this.canvas.appendChild(line); | ||
i++; | ||
} | ||
} | ||
}, { | ||
key: "mountGraphs", | ||
value: function mountGraphs() { | ||
var _this4 = this; | ||
if (isShown || opacity > 0) { | ||
var graph = document.createElement('polyline'); | ||
graph.setAttribute('stroke', color); | ||
graph.setAttribute('points', this.createPolylinePoints(xGraphPoints.map(this.mapX), graphPoints.map(function (y) { | ||
return _this3.mapY(maxY - y); | ||
})).join(' ')); | ||
graph.classList.add('chartogram__graph'); | ||
this.graphs = []; | ||
var y = this.state.y; | ||
y.forEach(function (_ref3, i) { | ||
var graphPoints = _ref3.graphPoints, | ||
color = _ref3.color; | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity; | ||
} | ||
_this4.mountGraph(i, graphPoints, color); | ||
}); | ||
} | ||
}, { | ||
key: "mountGraph", | ||
value: function mountGraph(i, graphPoints, color, opacity) { | ||
var graph = this.renderGraph(graphPoints, color, opacity); | ||
this.graphs[i] = graph; | ||
this.canvas.appendChild(graph); | ||
} | ||
}, { | ||
key: "unmountGraph", | ||
value: function unmountGraph(i) { | ||
this.canvas.removeChild(this.graphs[i]); | ||
this.graphs[i] = undefined; | ||
} | ||
}, { | ||
key: "updateGraph", | ||
value: function updateGraph(graph, graphPoints, opacity) { | ||
var _this5 = this; | ||
this.canvas.appendChild(graph); | ||
} | ||
var _this$state5 = this.state, | ||
xGraphPoints = _this$state5.xGraphPoints, | ||
maxY = _this$state5.maxY; | ||
i++; | ||
} // 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 | ||
if (typeof graph === 'number') { | ||
graph = this.graphs[graph]; | ||
} | ||
graph.setAttribute('points', this.createPolylinePoints(xGraphPoints.map(this.mapX), graphPoints.map(function (y) { | ||
return _this5.mapY(maxY - y); | ||
})).join(' ')); | ||
this.canvas.innerHTML += ''; // Draw gauges. | ||
this.drawGauges(minX, maxX, minY_, maxY_, yAxisScale); | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity; | ||
} | ||
} | ||
@@ -651,6 +693,66 @@ }, { | ||
this.setState(state); // Place in a `setState()` callback in case of React. | ||
var shouldUpdateTimeline = graphOpacity !== undefined || minYGlobal !== undefined; | ||
state.transitionUpdatesTimeline = shouldUpdateTimeline; | ||
this.setState(state, shouldUpdateTimeline); // Place the following in a `setState()` callback in case of React. | ||
this.transition = requestAnimationFrame(this.transitionStateTick); | ||
} | ||
}, { | ||
key: "renderGridLine", | ||
value: function renderGridLine(y) { | ||
var _this$state6 = this.state, | ||
minX = _this$state6.minX, | ||
maxX = _this$state6.maxX, | ||
minY = _this$state6.minY, | ||
maxY = _this$state6.maxY; | ||
var line = document.createElementNS(SVG_XMLNS, 'line'); | ||
line.classList.add('chartogram__grid-line'); | ||
line.setAttribute('x1', this.fixSvgCoordinate(this.mapX(minX))); | ||
line.setAttribute('x2', this.fixSvgCoordinate(this.mapX(maxX))); | ||
line.setAttribute('y1', this.fixSvgCoordinate(this.mapY(maxY - y))); | ||
line.setAttribute('y2', this.fixSvgCoordinate(this.mapY(maxY - y))); | ||
return line; | ||
} | ||
}, { | ||
key: "mountGauges", | ||
value: function mountGauges() { | ||
var gaugeTickMarksCount = this.props.gaugeTickMarksCount; | ||
var i = 0; | ||
while (i < gaugeTickMarksCount) { | ||
this.xAxis.appendChild(document.createElement('div')); | ||
this.yAxis.appendChild(document.createElement('div')); | ||
i++; | ||
} | ||
} | ||
}, { | ||
key: "updateGauges", | ||
value: function updateGauges(minX, maxX, minY, maxY, yAxisScale) { | ||
var _this$props = this.props, | ||
months = _this$props.months, | ||
gaugeTickMarksCount = _this$props.gaugeTickMarksCount; | ||
this.updateGauge(this.xAxis, minX, maxX, gaugeTickMarksCount, function (timestamp) { | ||
var date = new Date(timestamp); | ||
return "".concat(months[date.getMonth()], " ").concat(date.getDate()); | ||
}); | ||
this.updateGauge(this.yAxis, minY, maxY, gaugeTickMarksCount); | ||
this.yAxis.style.height = "".concat(100 / yAxisScale, "%"); | ||
} | ||
}, { | ||
key: "updateGauge", | ||
value: function updateGauge(gauge, min, max, tickMarksCount, transform) { | ||
var i = 0; | ||
while (i < tickMarksCount) { | ||
var tickMark = gauge.childNodes[i]; | ||
var value = min + i * (max - min) / (tickMarksCount - 1); | ||
if (transform) { | ||
value = transform(value); | ||
} | ||
tickMark.textContent = value; | ||
i++; | ||
} | ||
} | ||
}]); | ||
@@ -657,0 +759,0 @@ |
@@ -20,2 +20,4 @@ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
import { clearElement, commaJoin, simplifyGraph, throttle, setUpDrag } from './utility'; | ||
var TIMELINE_GRAPH_MAX_POINTS = 80; | ||
var SVG_XMLNS = 'http://www.w3.org/2000/svg'; | ||
@@ -39,2 +41,6 @@ var Timeline = | ||
_defineProperty(this, "setState", function (newState) { | ||
if (newState.aspectRatio !== _this.state.aspectRatio) { | ||
_this.updateAspectRatio(newState.aspectRatio); | ||
} | ||
_this.state = _objectSpread({}, _this.state, newState); | ||
@@ -57,6 +63,6 @@ | ||
canvasWidth = _this$props2.canvasWidth, | ||
minYGlobal = _this$props2.minYGlobal, | ||
maxYGlobal = _this$props2.maxYGlobal; | ||
minY = _this$props2.minY, | ||
maxY = _this$props2.maxY; | ||
var aspectRatio = _this.state.aspectRatio; | ||
return (y - minYGlobal) / (maxYGlobal - minYGlobal) * canvasWidth / aspectRatio; | ||
return (y - minY) / (maxY - minY) * canvasWidth / aspectRatio; | ||
}); | ||
@@ -169,2 +175,3 @@ | ||
}; | ||
this.updateAspectRatio(); | ||
this.setUpTimelineWindowHandle('left'); | ||
@@ -176,2 +183,3 @@ this.setUpTimelineWindowHandle('right'); | ||
this.onChangeBounds(this.props.fromRatio, this.props.toRatio); | ||
this.mountGraphs(); | ||
this.render(); | ||
@@ -186,2 +194,12 @@ } | ||
}, { | ||
key: "updateAspectRatio", | ||
value: function updateAspectRatio() { | ||
var aspectRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.aspectRatio; | ||
var _this$props3 = this.props, | ||
canvasWidth = _this$props3.canvasWidth, | ||
fixSvgCoordinate = _this$props3.fixSvgCoordinate; // Set canvas `viewBox`. | ||
this.timelineCanvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(fixSvgCoordinate(canvasWidth / aspectRatio))); | ||
} | ||
}, { | ||
key: "getCanvasAspectRatio", | ||
@@ -197,16 +215,7 @@ value: function getCanvasAspectRatio() { | ||
var _this$props3 = this.props, | ||
canvasWidth = _this$props3.canvasWidth, | ||
y = _this$props3.y, | ||
data = _this$props3.data, | ||
maxYGlobal = _this$props3.maxYGlobal, | ||
fixSvgCoordinate = _this$props3.fixSvgCoordinate, | ||
createPolylinePoints = _this$props3.createPolylinePoints, | ||
graphOpacity = _this$props3.graphOpacity; | ||
var aspectRatio = this.state.aspectRatio; // Clear canvas. | ||
var _this$props4 = this.props, | ||
y = _this$props4.y, | ||
data = _this$props4.data, | ||
graphOpacity = _this$props4.graphOpacity; // Update graphs. | ||
clearElement(this.timelineCanvas); // Set canvas `viewBox`. | ||
this.timelineCanvas.setAttribute('viewBox', "0 0 ".concat(canvasWidth, " ").concat(fixSvgCoordinate(canvasWidth / aspectRatio))); // Draw graphs. | ||
var i = 0; | ||
@@ -217,11 +226,11 @@ | ||
id = _data$y$i.id, | ||
color = _data$y$i.color, | ||
points = _data$y$i.points; | ||
var opacity = graphOpacity[i]; | ||
points = _data$y$i.points, | ||
color = _data$y$i.color; | ||
var isShown = y.find(function (_) { | ||
return _.id === id; | ||
}).isShown; | ||
var opacity = graphOpacity[i]; // Update graph. | ||
if (isShown || opacity > 0) { | ||
var _simplifyGraph = simplifyGraph(data.x.points, points, 80), | ||
var _simplifyGraph = simplifyGraph(data.x.points, points, TIMELINE_GRAPH_MAX_POINTS), | ||
_simplifyGraph2 = _slicedToArray(_simplifyGraph, 2), | ||
@@ -231,14 +240,9 @@ _x = _simplifyGraph2[0], | ||
var graph = document.createElement('polyline'); | ||
graph.setAttribute('stroke', color); | ||
graph.setAttribute('points', createPolylinePoints(_x.map(_this2.mapX), _y.map(function (y) { | ||
return _this2.mapY(maxYGlobal - y); | ||
})).join(' ')); | ||
graph.classList.add('chartogram__graph'); | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity; | ||
if (_this2.graphs[i]) { | ||
_this2.updateGraph(i, _x, _y, opacity); | ||
} else { | ||
_this2.mountGraph(i, _x, _y, color, opacity); | ||
} | ||
_this2.timelineCanvas.appendChild(graph); | ||
} else if (_this2.graphs[i]) { | ||
_this2.unmountGraph(i); | ||
} | ||
@@ -251,9 +255,63 @@ | ||
_loop(); | ||
} // 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 | ||
} | ||
} | ||
}, { | ||
key: "renderGraph", | ||
value: function renderGraph(x, y, color) { | ||
var opacity = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; | ||
var graph = document.createElementNS(SVG_XMLNS, 'polyline'); | ||
graph.setAttribute('stroke', color); | ||
this.updateGraph(graph, x, y, opacity); | ||
graph.classList.add('chartogram__graph'); | ||
return graph; | ||
} | ||
}, { | ||
key: "mountGraphs", | ||
value: function mountGraphs() { | ||
var _this3 = this; | ||
this.graphs = []; | ||
var data = this.props.data; | ||
data.y.forEach(function (_ref, i) { | ||
var points = _ref.points, | ||
color = _ref.color; | ||
this.timelineCanvas.innerHTML += ''; | ||
_this3.mountGraph(i, data.x.points, points, color); | ||
}); | ||
} | ||
}, { | ||
key: "mountGraph", | ||
value: function mountGraph(i, x, y, color, opacity) { | ||
var graph = this.renderGraph(x, y, color, opacity); | ||
this.graphs[i] = graph; | ||
this.timelineCanvas.appendChild(graph); | ||
} | ||
}, { | ||
key: "unmountGraph", | ||
value: function unmountGraph(i) { | ||
this.timelineCanvas.removeChild(this.graphs[i]); | ||
this.graphs[i] = undefined; | ||
} | ||
}, { | ||
key: "updateGraph", | ||
value: function updateGraph(graph, x, y, opacity) { | ||
var _this4 = this; | ||
var _this$props5 = this.props, | ||
maxY = _this$props5.maxY, | ||
createPolylinePoints = _this$props5.createPolylinePoints; | ||
if (typeof graph === 'number') { | ||
graph = this.graphs[graph]; | ||
} | ||
graph.setAttribute('points', createPolylinePoints(x.map(this.mapX), y.map(function (y) { | ||
return _this4.mapY(maxY - y); | ||
})).join(' ')); | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity; | ||
} | ||
} | ||
}, { | ||
key: "onChangeBounds", | ||
@@ -260,0 +318,0 @@ value: function onChangeBounds(from, to) { |
@@ -10,2 +10,3 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
import { setUpTouchMove } from './utility'; | ||
var SVG_XMLNS = 'http://www.w3.org/2000/svg'; | ||
@@ -276,4 +277,3 @@ var Tooltip = | ||
value: function renderLine() { | ||
var xmlns = 'http://www.w3.org/2000/svg'; | ||
var line = document.createElementNS(xmlns, 'line'); | ||
var line = document.createElementNS(SVG_XMLNS, 'line'); | ||
line.setAttribute('class', 'chartogram__tooltip-line'); | ||
@@ -280,0 +280,0 @@ return line; |
@@ -45,18 +45,2 @@ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
} | ||
export function renderGaugeLabels(element, min, max, GAUGE_TICK_MARKS_COUNT, transform) { | ||
var i = 0; | ||
while (i < GAUGE_TICK_MARKS_COUNT) { | ||
var tickMark = document.createElement('div'); | ||
var value = min + i * (max - min) / (GAUGE_TICK_MARKS_COUNT - 1); | ||
if (transform) { | ||
value = transform(value); | ||
} | ||
tickMark.appendChild(document.createTextNode(value)); | ||
element.appendChild(tickMark); | ||
i++; | ||
} | ||
} | ||
export function throttle(func, interval) { | ||
@@ -63,0 +47,0 @@ var timeout; |
{ | ||
"name": "chartogram", | ||
"version": "0.1.10", | ||
"version": "0.1.11", | ||
"description": "Charts in JS with no dependencies", | ||
@@ -5,0 +5,0 @@ "main": "index.commonjs.js", |
@@ -6,4 +6,3 @@ import { | ||
divideInterval, | ||
throttle, | ||
renderGaugeLabels | ||
throttle | ||
} from './utility' | ||
@@ -15,2 +14,4 @@ | ||
const SVG_XMLNS = 'http://www.w3.org/2000/svg' | ||
export default class Chartogram { | ||
@@ -62,2 +63,3 @@ constructor(rootNode, data, title = 'Title', props = {}) { | ||
this.state = this.getInitialState() | ||
this.updateAspectRatio() | ||
@@ -73,2 +75,6 @@ this.timeline = new Timeline(this.getTimelineProps()) | ||
this.mountGridLines() | ||
this.mountGauges() | ||
this.mountGraphs() | ||
// Add window resize event listener. | ||
@@ -105,2 +111,5 @@ window.addEventListener('resize', this.onResizeThrottled) | ||
setState(newState, renderTimeline = true) { | ||
if (newState.aspectRatio !== this.state.aspectRatio) { | ||
this.updateAspectRatio(newState.aspectRatio) | ||
} | ||
this.state = { | ||
@@ -126,4 +135,4 @@ ...this.state, | ||
toRatio: this.state.toRatio, | ||
minYGlobal: this.state.minYGlobal, | ||
maxYGlobal: this.state.maxYGlobal, | ||
minY: this.state.minYGlobal, | ||
maxY: this.state.maxYGlobal, | ||
y: this.state.y, | ||
@@ -339,9 +348,18 @@ graphOpacity: this.state.graphOpacity, | ||
render() { | ||
const { canvasWidth, gaugeTickMarksCount } = this.props | ||
const { minX, maxX, minY, maxY, xGraphPoints, aspectRatio, graphOpacity } = this.state | ||
// Clear canvas. | ||
clearElement(this.canvas) | ||
updateAspectRatio(aspectRatio = this.state.aspectRatio) { | ||
const { canvasWidth } = this.props | ||
// Set canvas `viewBox`. | ||
this.canvas.setAttribute('viewBox', `0 0 ${canvasWidth} ${this.fixSvgCoordinate(canvasWidth / aspectRatio)}`) | ||
} | ||
updateGridLine(i, y) { | ||
const { maxY } = this.state | ||
const line = this.gridLines[i] | ||
line.setAttribute('y1', this.fixSvgCoordinate(this.mapY(maxY - y))) | ||
line.setAttribute('y2', this.fixSvgCoordinate(this.mapY(maxY - y))) | ||
} | ||
render() { | ||
const { gaugeTickMarksCount } = this.props | ||
const { y, minX, maxX, minY, maxY, graphOpacity } = this.state | ||
// Calculate grid lines' coordinates. | ||
@@ -352,32 +370,23 @@ const minY_ = minY | ||
const yAxisTickMarks = divideInterval(minY_, maxY_, gaugeTickMarksCount) | ||
// Draw grid lines. | ||
for (const y of yAxisTickMarks) { | ||
this.canvas.appendChild(this.createGridLine(y)) | ||
} | ||
// Draw charts. | ||
// Update grid lines. | ||
yAxisTickMarks.forEach((y, i) => this.updateGridLine(i, y)) | ||
// Update graphs. | ||
let i = 0 | ||
while (i < this.state.y.length) { | ||
const { color, graphPoints, isShown } = this.state.y[i] | ||
while (i < y.length) { | ||
const { isShown, graphPoints, color } = y[i] | ||
const opacity = graphOpacity[i] | ||
// Draw chart. | ||
// Update graph. | ||
if (isShown || opacity > 0) { | ||
const graph = document.createElement('polyline') | ||
graph.setAttribute('stroke', color) | ||
graph.setAttribute('points', this.createPolylinePoints( | ||
xGraphPoints.map(this.mapX), | ||
graphPoints.map(y => this.mapY(maxY - y)) | ||
).join(' ')) | ||
graph.classList.add('chartogram__graph') | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity | ||
if (this.graphs[i]) { | ||
this.updateGraph(i, graphPoints, opacity) | ||
} else { | ||
this.mountGraph(i, graphPoints, color, opacity) | ||
} | ||
this.canvas.appendChild(graph) | ||
} else if (this.graphs[i]) { | ||
this.unmountGraph(i) | ||
} | ||
i++ | ||
} | ||
// 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.canvas.innerHTML += '' | ||
// Draw gauges. | ||
this.drawGauges( | ||
// Update gauges. | ||
this.updateGauges( | ||
minX, | ||
@@ -391,2 +400,55 @@ maxX, | ||
renderGraph(graphPoints, color, opacity = 1) { | ||
const graph = document.createElementNS(SVG_XMLNS, 'polyline') | ||
graph.setAttribute('stroke', color) | ||
graph.classList.add('chartogram__graph') | ||
this.updateGraph(graph, graphPoints, opacity) | ||
return graph | ||
} | ||
mountGridLines() { | ||
const { gaugeTickMarksCount } = this.props | ||
this.gridLines = [] | ||
let i = 0 | ||
while (i < gaugeTickMarksCount) { | ||
const line = this.renderGridLine(0) | ||
this.gridLines.push(line) | ||
this.canvas.appendChild(line) | ||
i++ | ||
} | ||
} | ||
mountGraphs() { | ||
this.graphs = [] | ||
const { y } = this.state | ||
y.forEach(({ graphPoints, color }, i) => { | ||
this.mountGraph(i, graphPoints, color) | ||
}) | ||
} | ||
mountGraph(i, graphPoints, color, opacity) { | ||
const graph = this.renderGraph(graphPoints, color, opacity) | ||
this.graphs[i] = graph | ||
this.canvas.appendChild(graph) | ||
} | ||
unmountGraph(i) { | ||
this.canvas.removeChild(this.graphs[i]) | ||
this.graphs[i] = undefined | ||
} | ||
updateGraph(graph, graphPoints, opacity) { | ||
const { xGraphPoints, maxY } = this.state | ||
if (typeof graph === 'number') { | ||
graph = this.graphs[graph] | ||
} | ||
graph.setAttribute('points', this.createPolylinePoints( | ||
xGraphPoints.map(this.mapX), | ||
graphPoints.map(y => this.mapY(maxY - y)) | ||
).join(' ')) | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity | ||
} | ||
} | ||
transitionState(minY, maxY, minYGlobal, maxYGlobal, graphOpacity) { | ||
@@ -428,4 +490,6 @@ const { transitionDuration: maxTransitionDuration } = this.props | ||
} | ||
this.setState(state) | ||
// Place in a `setState()` callback in case of React. | ||
const shouldUpdateTimeline = graphOpacity !== undefined || minYGlobal !== undefined | ||
state.transitionUpdatesTimeline = shouldUpdateTimeline | ||
this.setState(state, shouldUpdateTimeline) | ||
// Place the following in a `setState()` callback in case of React. | ||
this.transition = requestAnimationFrame(this.transitionStateTick) | ||
@@ -441,2 +505,3 @@ } | ||
transitionDuration, | ||
transitionUpdatesTimeline, | ||
graphOpacityFrom, | ||
@@ -484,3 +549,3 @@ graphOpacityTo, | ||
} | ||
this.setState(state) | ||
this.setState(state, transitionUpdatesTimeline) | ||
if (ratio < 1) { | ||
@@ -493,5 +558,5 @@ this.transition = requestAnimationFrame(this.transitionStateTick) | ||
createGridLine = (y) => { | ||
renderGridLine(y) { | ||
const { minX, maxX, minY, maxY } = this.state | ||
const line = document.createElement('line') | ||
const line = document.createElementNS(SVG_XMLNS, 'line') | ||
line.classList.add('chartogram__grid-line') | ||
@@ -505,13 +570,34 @@ line.setAttribute('x1', this.fixSvgCoordinate(this.mapX(minX))) | ||
drawGauges = (minX, maxX, minY, maxY, yAxisScale) => { | ||
const { gaugeTickMarksCount, months } = this.props | ||
clearElement(this.xAxis) | ||
clearElement(this.yAxis) | ||
renderGaugeLabels(this.xAxis, minX, maxX, gaugeTickMarksCount, (timestamp) => { | ||
mountGauges() { | ||
const { gaugeTickMarksCount } = this.props | ||
let i = 0 | ||
while (i < gaugeTickMarksCount) { | ||
this.xAxis.appendChild(document.createElement('div')) | ||
this.yAxis.appendChild(document.createElement('div')) | ||
i++ | ||
} | ||
} | ||
updateGauges(minX, maxX, minY, maxY, yAxisScale) { | ||
const { months, gaugeTickMarksCount } = this.props | ||
this.updateGauge(this.xAxis, minX, maxX, gaugeTickMarksCount, (timestamp) => { | ||
const date = new Date(timestamp) | ||
return `${months[date.getMonth()]} ${date.getDate()}` | ||
}) | ||
renderGaugeLabels(this.yAxis, minY, maxY, gaugeTickMarksCount) | ||
this.updateGauge(this.yAxis, minY, maxY, gaugeTickMarksCount) | ||
this.yAxis.style.height = `${100 / yAxisScale}%` | ||
} | ||
updateGauge(gauge, min, max, tickMarksCount, transform) { | ||
let i = 0 | ||
while (i < tickMarksCount) { | ||
const tickMark = gauge.childNodes[i] | ||
let value = min + i * (max - min) / (tickMarksCount - 1) | ||
if (transform) { | ||
value = transform(value) | ||
} | ||
tickMark.textContent = value | ||
i++ | ||
} | ||
} | ||
} | ||
@@ -518,0 +604,0 @@ |
@@ -9,2 +9,5 @@ import { | ||
const TIMELINE_GRAPH_MAX_POINTS = 80 | ||
const SVG_XMLNS = 'http://www.w3.org/2000/svg' | ||
export default class Timeline { | ||
@@ -42,2 +45,4 @@ constructor(props) { | ||
this.updateAspectRatio() | ||
this.setUpTimelineWindowHandle('left') | ||
@@ -51,2 +56,5 @@ this.setUpTimelineWindowHandle('right') | ||
this.onChangeBounds(this.props.fromRatio, this.props.toRatio) | ||
this.mountGraphs() | ||
this.render() | ||
@@ -69,2 +77,5 @@ } | ||
setState = (newState) => { | ||
if (newState.aspectRatio !== this.state.aspectRatio) { | ||
this.updateAspectRatio(newState.aspectRatio) | ||
} | ||
this.state = { | ||
@@ -77,2 +88,8 @@ ...this.state, | ||
updateAspectRatio(aspectRatio = this.state.aspectRatio) { | ||
const { canvasWidth, fixSvgCoordinate } = this.props | ||
// Set canvas `viewBox`. | ||
this.timelineCanvas.setAttribute('viewBox', `0 0 ${canvasWidth} ${fixSvgCoordinate(canvasWidth / aspectRatio)}`) | ||
} | ||
getCanvasAspectRatio() { | ||
@@ -84,35 +101,65 @@ const timelineCanvasDimensions = this.timelineCanvas.getBoundingClientRect() | ||
render() { | ||
const { canvasWidth, y, data, maxYGlobal, fixSvgCoordinate, createPolylinePoints, graphOpacity } = this.props | ||
const { aspectRatio } = this.state | ||
// Clear canvas. | ||
clearElement(this.timelineCanvas) | ||
// Set canvas `viewBox`. | ||
this.timelineCanvas.setAttribute('viewBox', `0 0 ${canvasWidth} ${fixSvgCoordinate(canvasWidth / aspectRatio)}`) | ||
// Draw graphs. | ||
const { y, data, graphOpacity } = this.props | ||
// Update graphs. | ||
let i = 0 | ||
while (i < data.y.length) { | ||
const { id, color, points } = data.y[i] | ||
const { id, points, color } = data.y[i] | ||
const isShown = y.find(_ => _.id === id).isShown | ||
const opacity = graphOpacity[i] | ||
const isShown = y.find(_ => _.id === id).isShown | ||
// Update graph. | ||
if (isShown || opacity > 0) { | ||
const [_x, _y] = simplifyGraph(data.x.points, points, 80) | ||
const graph = document.createElement('polyline') | ||
graph.setAttribute('stroke', color) | ||
graph.setAttribute('points', createPolylinePoints( | ||
_x.map(this.mapX), | ||
_y.map(y => this.mapY(maxYGlobal - y)) | ||
).join(' ')) | ||
graph.classList.add('chartogram__graph') | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity | ||
const [_x, _y] = simplifyGraph(data.x.points, points, TIMELINE_GRAPH_MAX_POINTS) | ||
if (this.graphs[i]) { | ||
this.updateGraph(i, _x, _y, opacity) | ||
} else { | ||
this.mountGraph(i, _x, _y, color, opacity) | ||
} | ||
this.timelineCanvas.appendChild(graph) | ||
} else if (this.graphs[i]) { | ||
this.unmountGraph(i) | ||
} | ||
i++ | ||
} | ||
// 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 += '' | ||
} | ||
renderGraph(x, y, color, opacity = 1) { | ||
const graph = document.createElementNS(SVG_XMLNS, 'polyline') | ||
graph.setAttribute('stroke', color) | ||
this.updateGraph(graph, x, y, opacity) | ||
graph.classList.add('chartogram__graph') | ||
return graph | ||
} | ||
mountGraphs() { | ||
this.graphs = [] | ||
const { data } = this.props | ||
data.y.forEach(({ points, color }, i) => { | ||
this.mountGraph(i, data.x.points, points, color) | ||
}) | ||
} | ||
mountGraph(i, x, y, color, opacity) { | ||
const graph = this.renderGraph(x, y, color, opacity) | ||
this.graphs[i] = graph | ||
this.timelineCanvas.appendChild(graph) | ||
} | ||
unmountGraph(i) { | ||
this.timelineCanvas.removeChild(this.graphs[i]) | ||
this.graphs[i] = undefined | ||
} | ||
updateGraph(graph, x, y, opacity) { | ||
const { maxY, createPolylinePoints } = this.props | ||
if (typeof graph === 'number') { | ||
graph = this.graphs[graph] | ||
} | ||
graph.setAttribute('points', createPolylinePoints( | ||
x.map(this.mapX), | ||
y.map(y => this.mapY(maxY - y)) | ||
).join(' ')) | ||
if (opacity !== 1) { | ||
graph.style.opacity = opacity | ||
} | ||
} | ||
onChangeBounds(from, to) { | ||
@@ -137,5 +184,5 @@ this.setTimelineWindowLeft(from) | ||
mapY = (y) => { | ||
const { canvasWidth, minYGlobal, maxYGlobal } = this.props | ||
const { canvasWidth, minY, maxY } = this.props | ||
const { aspectRatio } = this.state | ||
return ((y - minYGlobal) / (maxYGlobal - minYGlobal)) * canvasWidth / aspectRatio | ||
return ((y - minY) / (maxY - minY)) * canvasWidth / aspectRatio | ||
} | ||
@@ -142,0 +189,0 @@ |
import { setUpTouchMove } from './utility' | ||
const SVG_XMLNS = 'http://www.w3.org/2000/svg' | ||
export default class Tooltip { | ||
@@ -155,4 +157,3 @@ constructor(props) { | ||
renderLine() { | ||
const xmlns = 'http://www.w3.org/2000/svg' | ||
const line = document.createElementNS(xmlns, 'line') | ||
const line = document.createElementNS(SVG_XMLNS, 'line') | ||
line.setAttribute('class', 'chartogram__tooltip-line') | ||
@@ -159,0 +160,0 @@ return line |
@@ -34,16 +34,2 @@ export function clearElement(element) { | ||
export function renderGaugeLabels(element, min, max, GAUGE_TICK_MARKS_COUNT, transform) { | ||
let i = 0 | ||
while (i < GAUGE_TICK_MARKS_COUNT) { | ||
const tickMark = document.createElement('div') | ||
let value = min + i * (max - min) / (GAUGE_TICK_MARKS_COUNT - 1) | ||
if (transform) { | ||
value = transform(value) | ||
} | ||
tickMark.appendChild(document.createTextNode(value)) | ||
element.appendChild(tickMark) | ||
i++ | ||
} | ||
} | ||
export function throttle(func, interval) { | ||
@@ -50,0 +36,0 @@ let timeout |
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
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
1154851
5007