Skip to content

Commit

Permalink
feat: add options for configuring auto scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
sgratzl committed Mar 2, 2024
1 parent 75de4e2 commit f26566b
Showing 1 changed file with 39 additions and 4 deletions.
43 changes: 39 additions & 4 deletions src/controllers/WordCloudController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ export class WordCloudController extends DatasetController<'wordCloud', WordElem
*/
update(mode: UpdateMode): void {
super.update(mode);
this.rand = rnd(this.chart.id);
const dsOptions = (this as any).options as IWordCloudControllerDatasetOptions;
this.rand = rnd(dsOptions.randomRotationSeed ?? this.chart.id);
const meta = this._cachedMeta;

const elems = (meta.data || []) as unknown as WordElement[];
Expand All @@ -104,13 +105,21 @@ export class WordCloudController extends DatasetController<'wordCloud', WordElem
*/
updateElements(elems: WordElement[], start: number, count: number, mode: UpdateMode): void {
this.wordLayout.stop();
const dsOptions = (this as any).options as IWordCloudControllerDatasetOptions;
const xScale = this._cachedMeta.xScale as { left: number; right: number };
const yScale = this._cachedMeta.yScale as { top: number; bottom: number };

const w = xScale.right - xScale.left;
const h = yScale.bottom - yScale.top;
const labels = this.chart.data.labels as string[];

const growOptions: IAutoGrowOptions = {
maxTries: 3,
scalingFactor: 1.2,
};
// update with configured options
Object.assign(growOptions, dsOptions?.autoGrow ?? {});

const words: (ICloudWord & Record<string, unknown>)[] = [];
for (let i = start; i < start + count; i += 1) {
const o = this.resolveDataElementOptions(i, mode) as unknown as IWordElementOptions;
Expand Down Expand Up @@ -138,14 +147,18 @@ export class WordCloudController extends DatasetController<'wordCloud', WordElem
// syncish since no time limit is set
this.wordLayout.random(this.rand).words(words);

const run = (factor = 1, tries = 3): void => {
const run = (factor = 1, tries = growOptions.maxTries): void => {
this.wordLayout
.size([w * factor, h * factor])
.on('end', (tags, bounds) => {
if (tags.length < labels.length) {
if (tries > 0) {
// try again with a factor of 1.2
run(factor * 1.2, tries - 1);
const f =
typeof growOptions.scalingFactor === 'function'
? growOptions.scalingFactor(factor, tags, labels.length)
: factor * growOptions.scalingFactor;
run(f, tries - 1);
return;
}
// eslint-disable-next-line no-console
Expand All @@ -154,7 +167,6 @@ export class WordCloudController extends DatasetController<'wordCloud', WordElem
const wb = bounds[1].x - bounds[0].x;
const hb = bounds[1].y - bounds[0].y;

const dsOptions = (this as any).options as IWordCloudControllerDatasetOptions;
const scale = dsOptions.fit ? Math.min(w / wb, h / hb) : 1;
const indices = new Set(labels.map((_, i) => i));
tags.forEach((tag) => {
Expand Down Expand Up @@ -202,6 +214,17 @@ export class WordCloudController extends DatasetController<'wordCloud', WordElem
}
}

export interface IAutoGrowOptions {
/**
* @default 3
*/
maxTries: number;
/**
* @default 1.2
*/
scalingFactor: number | ((currentFactor: number, fitted: ICloudWord[], total: number) => number);
}

export interface IWordCloudControllerDatasetOptions
extends ControllerDatasetOptions,
ScriptableAndArrayOptions<IWordElementOptions, ScriptableContext<'wordCloud'>>,
Expand All @@ -212,6 +235,18 @@ export interface IWordCloudControllerDatasetOptions
* @default false
*/
fit: boolean;

/**
* configures the automatic growing of the canvas in case not all words can be fitted onto the screen
* @default { maxTries: 3, scalingFactor: 1.2}
*/
autoGrow: IAutoGrowOptions;

/**
* specifies the random seed that should be used for randomly rotating words if needed
* @default the current chart id
*/
randomRotationSeed: string;
}

declare module 'chart.js' {
Expand Down

0 comments on commit f26566b

Please sign in to comment.