UNPKG

@visactor/vgrammar-wordcloud

Version:

WordCloud layout transform for VGrammar

65 lines (60 loc) 3.11 kB
import { getTextBounds } from "@visactor/vrender-core"; import { BaseLayout } from "./base"; import { merge } from "@visactor/vutils"; export class FastLayout extends BaseLayout { constructor(options) { super(merge({}, FastLayout.defaultOptions, options)), this.random = this.options.random ? Math.random : () => 0, this.aspectRatio = 1; } fit(word) { for (let i = 0, len = this.result.length; i < len; i++) if (isOverlap(word, this.result[i])) return !1; return !0; } getTextInfo(datum, index) { const info = { datum: datum, fontSize: this.getTextFontSize(datum), fontWeight: this.getTextFontWeight(datum), fontStyle: this.getTextFontStyle(datum), fontFamily: this.getTextFontFamily(datum), angle: this.getTextRotate(datum, index), text: this.getText(datum) + "", x: this.center[0], y: this.center[1] }, bounds = getTextBounds(info); return info.width = bounds.width(), info.height = bounds.height(), info.top = this.center[1] - info.height + .21 * info.height, info.left = this.center[0] - info.width / 2, info; } layoutWord(index) { const info = this.getTextInfo(this.data[index], index); let angle = 2 * Math.PI, radius = 0, left = info.left, top = info.top; const width = info.width, height = info.height; let rx = 1, isFit = this.fit(info); for (;!isFit && radius < this.maxRadius; ) radius += .5, rx = this.shape(radius / this.maxRadius * 2 * Math.PI), angle += .5 * (this.options.random ? this.random() > .5 ? 1 : -1 : index % 2 == 0 ? 1 : -1), left = this.center[0] - width / 2 + radius * rx * Math.cos(angle) * this.aspectRatio, top = this.center[1] - height / 2 + radius * rx * Math.sin(angle), info.left = left, info.top = top, info.x = left + width / 2, info.y = top + height / 2, isFit = this.fit(info); return !!isFit && (!!(this.options.clip || info.left >= 0 && info.left + info.width <= this.width && info.top >= 0 && info.top + info.height <= this.height) && (this.result.push(info), !0)); } layout(data, config) { if (!(null == data ? void 0 : data.length)) return []; this.initProgressive(), this.result = [], this.maxRadius = Math.sqrt(config.width * config.width + config.height * config.height) / 2, this.center = [ config.width / 2, config.height / 2 ], this.width = config.width, this.height = config.height, this.data = data.sort(((a, b) => this.getTextFontSize(b) - this.getTextFontSize(a))); let i = 0; for (;i < data.length; ) { this.layoutWord(i); if (i++, this.progressiveIndex = i, this.exceedTime()) break; } return this.result; } } function isOverlap(a, b) { return !(a.left + a.width < b.left || a.top + a.height < b.top || a.left > b.left + b.width || a.top > b.top + b.height); } //# sourceMappingURL=fast-layout.js.map FastLayout.defaultOptions = { enlarge: !1 };