realchart
Version:
Wooritech charting library
8 lines (6 loc) • 10.8 kB
JavaScript
/**
* RealChart Wordcloud v1.3.17
* Copyright (C) 2023-2025 WooriTech Inc.
* All Rights Reserved.
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("realchart")):"function"==typeof define&&define.amd?define(["exports","realchart"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).RealChartWordCloud={},t.RealChart)}(this,(function(t,e){"use strict";function i(t){var e=Object.create(null);return t&&Object.keys(t).forEach((function(i){if("default"!==i){var s=Object.getOwnPropertyDescriptor(t,i);Object.defineProperty(e,i,s.get?s:{enumerable:!0,get:function(){return t[i]}})}})),e.default=t,Object.freeze(e)}var s=i(e);class n extends e.WidgetSeriesPoint{}class r extends n{constructor(t,e){super(t),this.points=e}}class o extends e.WidgetSeries{$_denormalizeFontSize(t,i,s){let n,r;return"min"==t?(n=e.calcPercent(e.parsePercentSize(o.MinFontSize,!1),i),r=e.calcPercent(e.parsePercentSize(o.MaxMinFontSize,!1),i)):(n=e.calcPercent(e.parsePercentSize(o.MinMaxFontSize,!1),i),r=e.calcPercent(e.parsePercentSize(o.MaxFontSize,!1),i)),s>1?r:s<0?n:s*(r-n)+n}calcFontRatio(t,i,s,n){return e.calcPercent(i,s,n)}getMinFontSize(t,i){const{fixed:s,size:n}=this._minFontSizeDim,r=s&&n<=1?this.$_denormalizeFontSize("min",t,n):e.calcPercent(this._minFontSizeDim,t,i);return Math.max(e.calcPercent(e.parsePercentSize(o.MinFontSize,!1),t),r)}getMaxFontSize(t,i){const{fixed:s,size:n}=this._maxFontSizeDim,r=s&&n<=1?this.$_denormalizeFontSize("max",t,n):e.calcPercent(this._maxFontSizeDim,t,i);return Math.min(e.calcPercent(e.parsePercentSize(o.MaxFontSize,!1),t),r)}getLogFunc(){const t=this._op.logBase;return t>=2?function(e){return Math.max(Math.log(e)/Math.log(t))}:function(t){return t}}_colorByPoint(){return this._op.colorByPoint}_createPoint(t){return new n(t)}_createOthersPoint(t,e){return t.y=e.map((t=>t.y)).reduce(((t,e)=>t+e)),new r(t,e)}_doApply(t){var i;super._doApply(t),(t.text!==this._text||e.Utils.equalArrays(this._excludes,t.excludes))&&(this._text=t.text,this._excludes=null===(i=t.excludes)||void 0===i?void 0:i.slice(),this._dataSourceDirty=!0),this._setDims(t,"minFontSize","maxFontSize")}_doLoadPoints(t){const i=this._op,s=i.text;let n=[];if(s){const t=Math.max(i.minLength||1,1),e={};let r=i.excludes,o=s.split(/\s+/g);Array.isArray(r)&&r.length>0&&(o=o.filter((t=>r.indexOf(t)<0))),o.forEach((i=>{i.length>=t&&(i in e?e[i]++:e[i]=1)}));for(const t in e)n.push({x:t,y:e[t]})}else if(Array.isArray(t)&&!(t.length>0&&"object"==typeof t[0]&&null!==t[0]))for(let i=0;i<t.length;i+=2)n.push({x:e.toStr(t[i]),y:t[i+1]||0});n.length>0&&(t=n.sort(((t,e)=>e.y-t.y))),super._doLoadPoints(t)}isPointLabelVisible(t){return!1}_prepareRender(){super._prepareRender(),this.collectValues(null,null),this.prepareReferents(null),this.collectRanges(null)}}o.type=e.WordCloudSeriesType,o.MinFontSize=8,o.MaxMinFontSize=15,o.MaxFontSize="15%",o.MinMaxFontSize="5%",o.defaults=e.extend(e.WidgetSeries.defaults,{frame:"rectangle",maxCount:100,maxFontSize:1,minFontSize:0,colorByPoint:!0,autoScale:!0});const a=Math.floor;class h{constructor(t){this._options=t}start(t,i,s,n,r,o){this._container=t;const a="circle"===s.frame||"ellipse"===s.frame,h=s.autoScale,l=e.pickNum(s.seed,0)*Math.PI*2/360,c=Math.max(0,e.pickNum(s.wordGap,0));let d=n,u=0,_=r,x=0,p=0;this.$_prepare(s,n,r),this._unit,i.forEach((t=>{const e=t.point;if(this.$_findPos(t,a,s.shuffle,this._radius,l,c)){const{x:i,y:s,width:n,height:r}=t.box.bounds;this.$_placeWord(t),e.xPos=i+n/2,e.yPos=s,d=Math.min(d,i),u=Math.max(u,i+n),_=Math.min(_,s),x=Math.max(x,s+r),p++}else t.setVis(!1)})),e.Utils.log("Words placed.",p,"of",i.length);const m=u-d,f=x-_,g=n/2,y=r/2,M=h?1/(Math.max(m/n,f/r)+.02):1,w=~~((d+m/2-g)*M),P=~~((_+f/2-y)*M);return this._trans={x:w,y:P,cx:g,cy:y,rate:M},i.forEach((t=>{const e=t.point;e.xPos=g-w+(e.xPos-g)*M,e.yPos=y-P+(e.yPos-y)*M})),this.$_transform(),null==o||o(i),this}stop(){}$_transform(t=1){let{x:e,y:i,cx:s,cy:n,rate:r}=this._trans;e=~~(e*t),i=~~(i*t),this._container.dom.setAttribute("transform-origin",`${s} ${n}`),this._container.trans(-e,-i),this._container.scale(r*t)}$_prepare(t,e,i){const s=this._unit=8;this._grid=[],this._cols=a(e/s),this._rows=a(i/s),this._radius=a(Math.sqrt(this._cols*this._cols+this._rows*this._rows)/2);const n=2*this._radius;this._center={c:this._radius,r:this._radius};for(let t=0;t<n;t++)this._grid.push([]);this._rdPoints=[],this._ellipticity="ellipse"===t.frame||"rectangle"===t.frame?i/e:1}$_isOverlapping(t){const e=this._grid;for(let i=t.r1;i<=t.r2;i++)for(let s=t.c1;s<=t.c2;s++)if(e[i]||(e[i]=[]),e[i][s])return!0;return!1}$_placeWord(t){const e=this._grid,i=t.box;for(let s=i.r1;s<=i.r2;s++)for(let n=i.c1;n<=i.c2;n++)e[s][n]=t}$_getPoints(t,e,i){if(this._rdPoints[t])return this._rdPoints[t];const s=this._center,n=this._ellipticity,r=t*this._unit;let o=0,a=[];for(0===t&&a.push([s.c,s.r]);o<r;){const h=o/r*2*Math.PI+i;let l=t*Math.cos(h)/n,c=t*Math.sin(h);if(!e){const t=Math.max(Math.abs(Math.cos(h)),Math.abs(Math.sin(h)));l/=t,c/=t}a.push([~~(s.c+l),~~(s.r+c)]),o++}return this._rdPoints[t]=a}$_rotatePoint(t,e,i){const s=e*Math.PI/180,n=Math.cos(s),r=Math.sin(s),{x:o,y:a,width:h,height:l}=t,c=o+h,d=a+l,u=o+h/2,_=a+l/2,x=[{x:o,y:a},{x:c,y:a},{x:o,y:d},{x:c,y:d}].map((t=>({x:u+(t.x-u)*n-(t.y-_)*r,y:_+(t.x-u)*r+(t.y-_)*n}))),p=Math.min(...x.map((t=>t.x))),m=Math.min(...x.map((t=>t.y))),f=Math.max(...x.map((t=>t.x))),g=Math.max(...x.map((t=>t.y))),y=this._unit,M=f-p,w=g-m;return{c1:Math.max(0,~~(p/y)),r1:Math.max(0,~~(m/y)),c2:~~(f/y),r2:~~(g/y)+i,bounds:{x:p,y:m,width:M,height:w}}}$_getBox(t,e,i,s,n=0){const r=this._unit,{width:o}=t.getBBox(),a=t.hText,h=o/r,l=a/r,c=Math.ceil(h/2),d=Math.ceil(l/2),u=Math.max(0,e-c),_=Math.max(0,i-d),x=u+Math.ceil(h),p=_+Math.ceil(l),m={x:(e-c)*r,y:(i-d)*r,width:o,height:a};return n?this.$_rotatePoint(m,n,s):{c1:u,r1:_,c2:x+s,r2:p,bounds:m}}$_drawDebugBox(t,i){const{doc:s}=this._container,{x:n,y:r,width:o,height:a}=t.bounds,h=e.RectElement.create(s,"",n,r,o,a);h.setFill((null==i?void 0:i.fill)||"#ff000055"),h.setStroke((null==i?void 0:i.stroke)||"none"),h.setAttr("stroke-dasharray",(null==i?void 0:i.strokeDashArray)||"4"),this._container.add(h)}$_findPos(t,i,s,n,r,o){let a=0,h=0;n=Math.max(n,this._grid.length+1);const l=[0,-90],c=l.length;for(;a<n;){const n=this.$_getPoints(a,i,r+h++%4*(Math.PI/4));s&&e.Utils.shuffle(n);if(n.some(((i,s)=>{let n=this._options.rotation?l[~~(e.Utils.randomLike(s+r)*c)]:0;const a=this.$_getBox(t,i[0],i[1],o,n);if(!this.$_isOverlapping(a)){if(a.bounds.x<0||a.bounds.y<0)return!1;const e=this.$_getBox(t,i[0],i[1],o),{bounds:s}=e,r={x:s.width/2,y:s.height/2};return t.wx=s.x,t.wy=s.y,t.setRotation(r.x,r.y,n),t.box=a,!0}})))return!0;a++}}}class l extends h{$_findPos(t,e,i,s,n,r){if(this.$_getPoints(s,e,i?Math.random()*Math.PI*2:n).some((e=>{const i=this.$_getBox(t,e[0],e[1],r);if(!this.$_isOverlapping(i))return t.box=i,!0})))return!0}$_getPoints(t,e,i){const s=this._center,n=this._ellipticity,r=2*t*this._unit;let o=-1,a=[];0===t&&a.push([s.c,s.r]);const h=i>Math.PI?1:-1;if(e)for(;++o<r;){const e=o/r,l=i+o*e*h,c=t*e,d=c*Math.cos(l)/n,u=c*Math.sin(l),_=s.c+d,x=s.r+u;a.push([~~_,~~x])}else{let e=this._unit>>1,r=e/n,l=s.c+r*Math.cos(i),c=s.r+e*Math.sin(i);const d=Math.max(1,this._unit>>1),u=d-Math.max(1,d>>1),_=.99;for(;++o>=0;){e=1+u*Math.pow(_,o),r=e/n;switch(3&(h*Math.sqrt(1+8*o)-1)/2){case 0:l+=r;break;case 1:c+=e;break;case 2:l-=r;break;default:c-=e}if(Math.max(Math.abs(l-t),Math.abs(c-t))>t)break;a.push([~~l,~~c])}}return a}$_getBox(t,e,i,s){const n=this._unit,r=t.getBBox(),o=t.hText,h=Math.min(2*this._radius,Math.max(0,e-a(r.width/2/n))),l=Math.min(2*this._radius,Math.max(0,i-a(o/2/n)));return{c1:h,r1:l,c2:h+a(r.width/n)+s,r2:l+a(o/n),w:t.width,h:o}}}class c extends e.RcElement{constructor(t){super(t,e.SeriesView.POINT_CLASS),this.add(this.hintView=new e.RectElement(t)),this.hintView.setStyles({stroke:"none",fill:"transparent"}),this.add(this.textView=new e.TextElement(t)),this.textView.setStyle("pointerEvents","none")}layout(){const t=this.getBBox();this.hintView.setRect({x:0,y:this.yText*c.TOP_PAD,width:t.width,height:this.hText-this.yText}),this.textView.transY(-this.yText*c.TOP_PAD)}}c.TOP_PAD=.5;class d extends e.WidgetSeriesView{constructor(t){super(t,"rct-wordcloud-series"),this._pointContainer.add(this._wordContainer=new e.LayerElement(t,null)),this._words=new e.ElementPool(this._wordContainer,c)}_getPointPool(){return this._words}needFronting(){return!1}isEmptyView(){return this._empty}_renderSeries(t,i){const s=this.model.options,n=s.text;if(t!==this._wSave||i!==this._hSave||n!==this._tSave){const r=+new Date;let o=this._visPoints.slice();if(s.minWeight>0&&(o=o.filter((t=>t.yValue>=s.minWeight))),s.minLength>1&&(o=o.filter((t=>t.x.length>=s.minLength))),s.maxCount<o.length&&(o.length=Math.max(0,s.maxCount)),this.$_prepareWords(this.doc,this.model,o),"spiral"===s.placer)this._placer=new l(s).start(this._wordContainer,this._words._internalItems(),s,t,i,(e=>{this.$_layoutWords(t,i)}));else this._placer=new h(s).start(this._wordContainer,this._words._internalItems(),s,t,i,(e=>{this.$_layoutWords(t,i)}));this._wSave=t,this._hSave=i,this._tSave=n,this._empty=o.length<1,e.Utils.log(o.length+" words placed in "+(+new Date-r)+"ms.")}else this.$_layoutWords(t,i)}_runShowEffect(t){t&&e.SeriesAnimation.spread(this,(()=>{}))}_doPosRateChanged(t){this.$_layoutWords(this.width,this.height)}$_prepareWords(t,i,s){const n=i._minY,r=i._maxY,o=r-n,a=this.height,h=i.getMaxFontSize(a,1);let l=Math.min(h,i.getMinFontSize(a,0));const d=n===r||l===h,u=d?NaN:i.options.logBase,_=getComputedStyle(this._wordContainer.dom).fontFamily,x=Math.min(2,Math.max(.1,+i.options.textHeight)),p=isNaN(x)?t.createElement("canvas").getContext("2d"):null,m=1-c.TOP_PAD;let f;this._words.prepare(s.length,((r,a)=>{const c=r.point=s[a],g=r.textView;let y=(c.y-n)/o;u>1&&(y=1-(Math.pow(u,1-y)-1)/(u-1));let M=l+(d?(h-l)/2:y*(h-l));const w=c.x;this._preparePoint(t,i,c,r),delete r.box,g.text=w,g.anchor=e.TextAnchor.START,g.setStyles({fontSize:e.pixel(M)}),g.layoutText(),p?(p.font=`${e.pixel(M)} ${_}`,f=p.measureText(w),r.yText=.9*Math.max(0,f.fontBoundingBoxAscent-f.actualBoundingBoxAscent),r.hText=Math.ceil((f.actualBoundingBoxAscent+f.actualBoundingBoxDescent)*(M<=10?1.1:1.08)-.1)+r.yText*m):(r.yText=0,r.hText=r.getBBox().height*x),r.layout(),r.setVis(!0)}))}$_layoutWords(t,e){var i;let s=this._getPosRate();null===(i=this._placer)||void 0===i||i.$_transform(s),s=1-s,this._words.forEach((i=>{const{bounds:n}=i.box,r=n.width,o=n.height,a=(t-r)/2;let h=(e-o)/2;i.trans(i.wx-(i.wx-a)*s,i.wy-(i.wy-h)*s)}))}}function u(t){(function(t){return t.Series&&t.SeriesView})(t)&&(t.Series.register(o),t.SeriesView.register([o,d]))}u(s),t.WordCloudSeries=o,t.default=u,Object.defineProperty(t,"__esModule",{value:!0})}));