pathfinder.js 11.5 KB
/*
 Highcharts JS v6.2.0 (2018-10-17)
 Pathfinder

 (c) 2016 ystein Moseng

 --- WORK IN PROGRESS ---

 License: www.highcharts.com/license
*/
(function(u){"object"===typeof module&&module.exports?module.exports=u:"function"===typeof define&&define.amd?define(function(){return u}):u(Highcharts)})(function(u){var I=function(g){function v(d,h,e){e=e||0;var g=d.length-1;h-=1e-7;for(var l,q;e<=g;)if(l=g+e>>1,q=h-d[l].xMin,0<q)e=l+1;else if(0>q)g=l-1;else return l;return 0<e?e-1:0}function l(d,h){for(var e=v(d,h.x+1)+1;e--;){var g;if(g=d[e].xMax>=h.x)g=d[e],g=h.x<=g.xMax&&h.x>=g.xMin&&h.y<=g.yMax&&h.y>=g.yMin;if(g)return e}return-1}function r(d){var h=
[];if(d.length){h.push("M",d[0].start.x,d[0].start.y);for(var e=0;e<d.length;++e)h.push("L",d[e].end.x,d[e].end.y)}return h}function n(d,h){d.yMin=z(d.yMin,h.yMin);d.yMax=t(d.yMax,h.yMax);d.xMin=z(d.xMin,h.xMin);d.xMax=t(d.xMax,h.xMax)}var t=Math.min,z=Math.max,w=Math.abs,u=g.pick;return{straight:function(d,h){return{path:["M",d.x,d.y,"L",h.x,h.y],obstacles:[{start:d,end:h}]}},simpleConnect:g.extend(function(d,h,e){function g(a,b,c,f,k){a={x:a.x,y:a.y};a[b]=c[f||b]+(k||0);return a}function v(a,b,
c){var f=w(b[c]-a[c+"Min"])>w(b[c]-a[c+"Max"]);return g(b,c,a,c+(f?"Max":"Min"),f?1:-1)}var q=[],b,a=u(e.startDirectionX,w(h.x-d.x)>w(h.y-d.y))?"x":"y",c=e.chartObstacles,k=l(c,d);e=l(c,h);var f;-1<e?(b=c[e],e=v(b,h,a),b={start:e,end:h},f=e):f=h;-1<k&&(c=c[k],e=v(c,d,a),q.push({start:d,end:e}),e[a]>d[a]===e[a]>f[a]&&(a="y"===a?"x":"y",h=d[a]<h[a],q.push({start:e,end:g(e,a,c,a+(h?"Max":"Min"),h?1:-1)}),a="y"===a?"x":"y"));d=q.length?q[q.length-1].end:d;e=g(d,a,f);q.push({start:d,end:e});a=g(e,"y"===
a?"x":"y",f);q.push({start:e,end:a});q.push(b);return{path:r(q),obstacles:q}},{requiresObstacles:!0}),fastAvoid:g.extend(function(d,h,e){function g(a,b,c){var f,k,d,h,g,e=a.x<b.x?1:-1;a.x<b.x?(f=a,k=b):(f=b,k=a);a.y<b.y?(h=a,d=b):(h=b,d=a);for(g=0>e?t(v(m,k.x),m.length-1):0;m[g]&&(0<e&&m[g].xMin<=k.x||0>e&&m[g].xMax>=f.x);){if(m[g].xMin<=k.x&&m[g].xMax>=f.x&&m[g].yMin<=d.y&&m[g].yMax>=h.y)return c?{y:a.y,x:a.x<b.x?m[g].xMin-1:m[g].xMax+1,obstacle:m[g]}:{x:a.x,y:a.y<b.y?m[g].yMin-1:m[g].yMax+1,obstacle:m[g]};
g+=e}return b}function y(a,b,c,f,k){var d=k.soft,h=k.hard,e=f?"x":"y",x={x:b.x,y:b.y},p={x:b.x,y:b.y};k=a[e+"Max"]>=d[e+"Max"];var d=a[e+"Min"]<=d[e+"Min"],F=a[e+"Max"]>=h[e+"Max"],h=a[e+"Min"]<=h[e+"Min"],m=w(a[e+"Min"]-b[e]),l=w(a[e+"Max"]-b[e]);c=10>w(m-l)?b[e]<c[e]:l<m;p[e]=a[e+"Min"];x[e]=a[e+"Max"];a=g(b,p,f)[e]!==p[e];b=g(b,x,f)[e]!==x[e];c=a?b?c:!0:b?!1:c;c=d?k?c:!0:k?!1:c;return h?F?c:!0:F?!1:c}function q(a,b,c){if(a.x===b.x&&a.y===b.y)return[];var f=c?"x":"y",k,d,h,x,p=e.obstacleOptions.margin;
k={soft:{xMin:D,xMax:E,yMin:G,yMax:H},hard:e.hardBounds};d=l(m,a);-1<d?(d=m[d],k=y(d,a,b,c,k),n(d,e.hardBounds),x=c?{y:a.y,x:d[k?"xMax":"xMin"]+(k?1:-1)}:{x:a.x,y:d[k?"yMax":"yMin"]+(k?1:-1)},h=l(m,x),-1<h&&(h=m[h],n(h,e.hardBounds),x[f]=k?z(d[f+"Max"]-p+1,(h[f+"Min"]+d[f+"Max"])/2):t(d[f+"Min"]+p-1,(h[f+"Max"]+d[f+"Min"])/2),a.x===x.x&&a.y===x.y?(A&&(x[f]=k?z(d[f+"Max"],h[f+"Max"])+1:t(d[f+"Min"],h[f+"Min"])-1),A=!A):A=!1),a=[{start:a,end:x}]):(f=g(a,{x:c?b.x:a.x,y:c?a.y:b.y},c),a=[{start:a,end:{x:f.x,
y:f.y}}],f[c?"x":"y"]!==b[c?"x":"y"]&&(k=y(f.obstacle,f,b,!c,k),n(f.obstacle,e.hardBounds),k={x:c?f.x:f.obstacle[k?"xMax":"xMin"]+(k?1:-1),y:c?f.obstacle[k?"yMax":"yMin"]+(k?1:-1):f.y},c=!c,a=a.concat(q({x:f.x,y:f.y},k,c))));return a=a.concat(q(a[a.length-1].end,b,!c))}function b(a,b,c){var f=t(a.xMax-b.x,b.x-a.xMin)<t(a.yMax-b.y,b.y-a.yMin);c=y(a,b,c,f,{soft:e.hardBounds,hard:e.hardBounds});return f?{y:b.y,x:a[c?"xMax":"xMin"]+(c?1:-1)}:{x:b.x,y:a[c?"yMax":"yMin"]+(c?1:-1)}}var a=u(e.startDirectionX,
w(h.x-d.x)>w(h.y-d.y)),c=a?"x":"y",k,f,x=[],A=!1,p=e.obstacleMetrics,D=t(d.x,h.x)-p.maxWidth-10,E=z(d.x,h.x)+p.maxWidth+10,G=t(d.y,h.y)-p.maxHeight-10,H=z(d.y,h.y)+p.maxHeight+10,m=e.chartObstacles;k=v(m,D);p=v(m,E);m=m.slice(k,p+1);-1<(p=l(m,h))&&(f=b(m[p],h,d),x.push({end:h,start:f}),h=f);for(;-1<(p=l(m,h));)k=0>h[c]-d[c],f={x:h.x,y:h.y},f[c]=m[p][k?c+"Max":c+"Min"]+(k?1:-1),x.push({end:h,start:f}),h=f;d=q(d,h,a);d=d.concat(x.reverse());return{path:r(d),obstacles:d}},{requiresObstacles:!0})}}(u);
(function(g){g.SVGRenderer.prototype.symbols.arrow=function(g,l,r,n){return["M",g,l+n/2,"L",g+r,l,"L",g,l+n/2,"L",g+r,l+n]};g.SVGRenderer.prototype.symbols["arrow-half"]=function(v,l,r,n){return g.SVGRenderer.prototype.symbols.arrow(v,l,r/2,n)};g.SVGRenderer.prototype.symbols["triangle-left"]=function(g,l,r,n){return["M",g+r,l,"L",g,l+n/2,"L",g+r,l+n,"Z"]};g.SVGRenderer.prototype.symbols["arrow-filled"]=g.SVGRenderer.prototype.symbols["triangle-left"];g.SVGRenderer.prototype.symbols["triangle-left-half"]=
function(v,l,r,n){return g.SVGRenderer.prototype.symbols["triangle-left"](v,l,r/2,n)};g.SVGRenderer.prototype.symbols["arrow-filled-half"]=g.SVGRenderer.prototype.symbols["triangle-left-half"]})(u);(function(g,v){function l(b){var a=b.shapeArgs;return a?{xMin:a.x,xMax:a.x+a.width,yMin:a.y,yMax:a.y+a.height}:(a=b.graphic&&b.graphic.getBBox())?{xMin:b.plotX-a.width/2,xMax:b.plotX+a.width/2,yMin:b.plotY-a.height/2,yMax:b.plotY+a.height/2}:null}function r(b){for(var a=b.length,c=0,k,f,d=[],e=function(a,
b,c){c=B(c,10);var f=a.yMax+c>b.yMin-c&&a.yMin-c<b.yMax+c,k=a.xMax+c>b.xMin-c&&a.xMin-c<b.xMax+c,d=f?a.xMin>b.xMax?a.xMin-b.xMax:b.xMin-a.xMax:Infinity,g=k?a.yMin>b.yMax?a.yMin-b.yMax:b.yMin-a.yMax:Infinity;return k&&f?c?e(a,b,Math.floor(c/2)):Infinity:q(d,g)};c<a;++c)for(k=c+1;k<a;++k)f=e(b[c],b[k]),80>f&&d.push(f);d.push(80);return y(Math.floor(d.sort(function(a,b){return a-b})[Math.floor(d.length/10)]/2-1),1)}function n(b,a,c){this.init(b,a,c)}function t(b){this.init(b)}var u=g.defined,w=g.deg2rad,
C=g.extend,d=g.each,h=g.addEvent,e=g.merge,B=g.pick,y=Math.max,q=Math.min;C(g.defaultOptions,{pathfinder:{type:"straight",lineWidth:1,marker:{enabled:!1,align:"center",verticalAlign:"middle",inside:!1,lineWidth:1},startMarker:{symbol:"diamond"},endMarker:{symbol:"arrow-filled"}}});n.prototype={init:function(b,a,c){this.fromPoint=b;this.toPoint=a;this.options=c;this.chart=b.series.chart;this.pathfinder=this.chart.pathfinder},renderPath:function(b,a,c){var k=this.chart,f=k.pathfinder,d=!k.options.chart.forExport&&
!1!==c,e=this.graphics&&this.graphics.path;f.group||(f.group=k.renderer.g().addClass("highcharts-pathfinder-group").attr({zIndex:-1}).add(k.seriesGroup));f.group.translate(k.plotLeft,k.plotTop);e&&e.renderer||(e=k.renderer.path().add(f.group));e.attr(a);e[d?"animate":"attr"]({d:b},c);this.graphics=this.graphics||{};this.graphics.path=e},addMarker:function(b,a,c){var k=this.fromPoint.series.chart,f=k.pathfinder,k=k.renderer,d="start"===b?this.fromPoint:this.toPoint,e=d.getPathfinderAnchorPoint(a),
g;a.enabled&&(c="start"===b?{x:c[4],y:c[5]}:{x:c[c.length-5],y:c[c.length-4]},c=d.getRadiansToVector(c,e),d=d.getMarkerVector(c,a.radius,e),e=-c/w,a.width&&a.height?(c=a.width,g=a.height):c=g=2*a.radius,this.graphics=this.graphics||{},d={x:d.x-c/2,y:d.y-g/2,width:c,height:g,rotation:e,rotationOriginX:d.x,rotationOriginY:d.y},this.graphics[b]?this.graphics[b].animate(d):this.graphics[b]=k.symbol(a.symbol).addClass("highcharts-point-connecting-path-"+b+"-marker").attr(d).add(f.group))},getPath:function(b){var a=
this.pathfinder,c=this.chart,d=a.algorithms[b.type],f=a.chartObstacles;if("function"!==typeof d)g.error('"'+b.type+'" is not a Pathfinder algorithm.');else return d.requiresObstacles&&!f&&(f=a.chartObstacles=a.getChartObstacles(b),c.options.pathfinder.algorithmMargin=b.algorithmMargin,a.chartObstacleMetrics=a.getObstacleMetrics(f)),d(this.fromPoint.getPathfinderAnchorPoint(b.startMarker),this.toPoint.getPathfinderAnchorPoint(b.endMarker),e({chartObstacles:f,lineObstacles:a.lineObstacles||[],obstacleMetrics:a.chartObstacleMetrics,
hardBounds:{xMin:0,xMax:c.plotWidth,yMin:0,yMax:c.plotHeight},obstacleOptions:{margin:b.algorithmMargin},startDirectionX:a.getAlgorithmStartDirection(b.startMarker)},b))},render:function(){var b=this.fromPoint,a=b.series,c=a.chart,d=c.pathfinder,f,c=e(c.options.pathfinder,a.options.pathfinder,b.options.pathfinder,this.options),g={};g.class="highcharts-point-connecting-path highcharts-color-"+b.colorIndex;c=e(g,c);u(c.marker.radius)||(c.marker.radius=q(y(Math.ceil((c.algorithmMargin||8)/2)-1,1),5));
b=this.getPath(c);f=b.path;b.obstacles&&(d.lineObstacles=d.lineObstacles||[],d.lineObstacles=d.lineObstacles.concat(b.obstacles));this.renderPath(f,g,a.options.animation);this.addMarker("start",e(c.marker,c.startMarker),f);this.addMarker("end",e(c.marker,c.endMarker),f)},destroy:function(){this.graphics&&(g.objectEach(this.graphics,function(b){b.destroy()}),delete this.graphics)}};t.prototype={algorithms:v,init:function(b){this.chart=b;this.connections=[];h(b,"redraw",function(){this.pathfinder.update()})},
update:function(b){var a=this.chart,c=this,e=c.connections;c.connections=[];d(a.series,function(b){b.visible&&d(b.points,function(b){var f,e=b.options&&b.options.connect&&g.splat(b.options.connect);b.visible&&!1!==b.isInside&&e&&d(e,function(d){f=a.get("string"===typeof d?d:d.to);f instanceof g.Point&&f.series.visible&&f.visible&&!1!==f.isInside&&c.connections.push(new n(b,f,"string"===typeof d?{}:d))})})});for(var f=0,h,l,p=e.length,q=c.connections.length;f<p;++f){l=!1;for(h=0;h<q;++h)if(e[f].fromPoint===
c.connections[h].fromPoint&&e[f].toPoint===c.connections[h].toPoint){c.connections[h].graphics=e[f].graphics;l=!0;break}l||e[f].destroy()}delete this.chartObstacles;delete this.lineObstacles;c.renderConnections(b)},renderConnections:function(b){b?d(this.chart.series,function(a){var b=function(){var b=a.chart.pathfinder;d(b&&b.connections||[],function(b){b.fromPoint&&b.fromPoint.series===a&&b.render()});a.pathfinderRemoveRenderEvent&&(a.pathfinderRemoveRenderEvent(),delete a.pathfinderRemoveRenderEvent)};
!1===a.options.animation?b():a.pathfinderRemoveRenderEvent=h(a,"afterAnimate",b)}):d(this.connections,function(a){a.render()})},getChartObstacles:function(b){for(var a=[],c=this.chart.series,e=B(b.algorithmMargin,0),f,g=0,h=c.length;g<h;++g)if(c[g].visible)for(var p=0,q=c[g].points.length,n;p<q;++p)n=c[g].points[p],n.visible&&(n=l(n))&&a.push({xMin:n.xMin-e,xMax:n.xMax+e,yMin:n.yMin-e,yMax:n.yMax+e});a=a.sort(function(a,b){return a.xMin-b.xMin});u(b.algorithmMargin)||(f=b.algorithmMargin=r(a),d(a,
function(a){a.xMin-=f;a.xMax+=f;a.yMin-=f;a.yMax+=f}));return a},getObstacleMetrics:function(b){for(var a=0,c=0,d,f,e=b.length;e--;)d=b[e].xMax-b[e].xMin,f=b[e].yMax-b[e].yMin,a<d&&(a=d),c<f&&(c=f);return{maxHeight:c,maxWidth:a}},getAlgorithmStartDirection:function(b){var a="top"!==b.verticalAlign&&"bottom"!==b.verticalAlign;return"left"!==b.align&&"right"!==b.align?a?void 0:!1:a?!0:void 0}};g.Connection=n;g.Pathfinder=t;C(g.Point.prototype,{getPathfinderAnchorPoint:function(b){var a=l(this),c,d;
switch(b.align){case "right":c="xMax";break;case "left":c="xMin"}switch(b.verticalAlign){case "top":d="yMin";break;case "bottom":d="yMax"}return{x:c?a[c]:(a.xMin+a.xMax)/2,y:d?a[d]:(a.yMin+a.yMax)/2}},getRadiansToVector:function(b,a){u(a)||(a=l(this),a={x:(a.xMin+a.xMax)/2,y:(a.yMin+a.yMax)/2});return Math.atan2(a.y-b.y,b.x-a.x)},getMarkerVector:function(b,a,c){for(var d=2*Math.PI,e=l(this),g=e.xMax-e.xMin,h=e.yMax-e.yMin,p=Math.atan2(h,g),n=!1,g=g/2,q=h/2,u=e.xMin+g,e=e.yMin+q,r=u,m=e,v={},t=1,w=
1;b<-Math.PI;)b+=d;for(;b>Math.PI;)b-=d;d=Math.tan(b);b>-p&&b<=p?(w=-1,n=!0):b>p&&b<=Math.PI-p?w=-1:b>Math.PI-p||b<=-(Math.PI-p)?(t=-1,n=!0):t=-1;n?(r+=t*g,m+=w*g*d):(r+=h/(2*d)*t,m+=w*q);c.x!==u&&(r=c.x);c.y!==e&&(m=c.y);v.x=r+a*Math.cos(b);v.y=m-a*Math.sin(b);return v}});g.Chart.prototype.callbacks.push(function(b){!1!==b.options.pathfinder.enabled&&(this.pathfinder=new t(this),this.pathfinder.update(!0))})})(u,I)});
//# sourceMappingURL=pathfinder.js.map