-
Notifications
You must be signed in to change notification settings - Fork 129
feat(partition): treemap group text in grooves #652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
0ec59a4
5115abb
cb141a6
91013f9
6d3acea
b2da71b
1dc6e50
e203903
af0c010
9c30090
9af1378
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,7 @@ import { Layer } from '../../specs/index'; | |
| import { stringToRGB } from '../utils/d3_utils'; | ||
| import { colorIsDark } from '../utils/calcs'; | ||
| import { ValueFormatter } from '../../../../utils/commons'; | ||
| import { RectangleConstruction, VerticalAlignment, VerticalAlignments } from './viewmodel'; | ||
|
|
||
| const INFINITY_RADIUS = 1e4; // far enough for a sub-2px precision on a 4k screen, good enough for text bounds; 64 bit floats still work well with it | ||
|
|
||
|
|
@@ -73,16 +74,6 @@ export function nodeId(node: ShapeTreeNode): string { | |
| return `${node.x0}|${node.y0}`; | ||
| } | ||
|
|
||
| /** @internal */ | ||
| export function rectangleConstruction(node: ShapeTreeNode) { | ||
| return { | ||
| x0: node.x0, | ||
| y0: node.y0px, | ||
| x1: node.x1, | ||
| y1: node.y1px, | ||
| }; | ||
| } | ||
|
|
||
| /** @internal */ | ||
| export function ringSectorConstruction(config: Config, innerRadius: Radius, ringThickness: Distance) { | ||
| return (ringSector: ShapeTreeNode): RingSector => { | ||
|
|
@@ -183,32 +174,35 @@ export function getSectorRowGeometry( | |
|
|
||
| /** @internal */ | ||
| export function getRectangleRowGeometry( | ||
| container: any, | ||
| container: RectangleConstruction, | ||
| cx: number, | ||
| cy: number, | ||
| totalRowCount: number, | ||
| linePitch: Pixels, | ||
| rowIndex: number, | ||
| fontSize: Pixels, | ||
| _rotation: Radian, | ||
| verticalAlignment: VerticalAlignment, | ||
| ): RowSpace { | ||
| const wordSpacing = getWordSpacing(fontSize); | ||
| const x0 = container.x0 + wordSpacing; | ||
| const y0 = container.y0 + linePitch / 2; | ||
| const x1 = container.x1 - wordSpacing; | ||
| const y1 = container.y1 - linePitch / 2; | ||
|
|
||
| // prettier-ignore | ||
| const offset = | ||
| (totalRowCount / 2) * fontSize | ||
| + fontSize / 2 | ||
| - linePitch * rowIndex | ||
|
|
||
| const rowCentroidX = cx; | ||
| const rowCentroidY = cy - offset; | ||
| const overhang = 0.05; | ||
| const padding = fontSize < 6 ? 0 : Math.max(1, Math.min(2, fontSize / 16)); // taper out padding with small fonts | ||
| if ((container.y1 - container.y0 - 2 * padding) / totalRowCount < linePitch) { | ||
| return { | ||
| rowCentroidX: NaN, | ||
nickofthyme marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| rowCentroidY: NaN, | ||
| maximumRowLength: 0, | ||
| }; | ||
| } | ||
| const rowCentroidY = | ||
| verticalAlignment === VerticalAlignments.top | ||
| ? -(container.y0 + linePitch * rowIndex + padding + fontSize * overhang) | ||
| : verticalAlignment === VerticalAlignments.bottom | ||
| ? -(container.y1 - linePitch * (totalRowCount - 1 - rowIndex) - fontSize * overhang) | ||
| : -((container.y0 + container.y1) / 2 + (linePitch * (rowIndex - totalRowCount)) / 2); | ||
|
||
| return { | ||
| rowCentroidX, | ||
| rowCentroidY: -rowCentroidY, | ||
| maximumRowLength: rowCentroidY - linePitch / 2 < y0 || rowCentroidY + linePitch / 2 > y1 ? 0 : x1 - x0, | ||
| rowCentroidX: cx, | ||
| rowCentroidY, | ||
| maximumRowLength: container.x1 - container.x0 - 2 * padding, | ||
| }; | ||
| } | ||
|
|
||
|
|
@@ -223,6 +217,8 @@ function identityRowSet(): RowSet { | |
| fontSize: NaN, | ||
| fillTextColor: '', | ||
| rotation: NaN, | ||
| verticalAlignment: VerticalAlignments.middle, | ||
| leftAlign: false, | ||
| }; | ||
| } | ||
|
|
||
|
|
@@ -251,7 +247,7 @@ function getWordSpacing(fontSize: number) { | |
| function fill( | ||
| config: Config, | ||
| layers: Layer[], | ||
| fontSizes: string | any[], | ||
| allFontSizes: string | any[], | ||
| measure: TextMeasure, | ||
| rawTextGetter: RawTextGetter, | ||
| valueGetter: ValueGetterFunction, | ||
|
|
@@ -260,11 +256,19 @@ function fill( | |
| shapeConstructor: (n: ShapeTreeNode) => any, | ||
| getShapeRowGeometry: (...args: any[]) => RowSpace, | ||
| getRotation: Function, | ||
| leftAlign: boolean, | ||
| middleAlign: boolean, | ||
| ) { | ||
| return (node: QuadViewModel, index: number) => { | ||
| const { maxRowCount, fillLabel } = config; | ||
|
|
||
| const layer = layers[node.depth - 1] || {}; | ||
| const verticalAlignment = middleAlign | ||
| ? VerticalAlignments.middle | ||
| : node.depth < layers.length | ||
| ? VerticalAlignments.bottom | ||
| : VerticalAlignments.top; | ||
| const fontSizes = allFontSizes[Math.min(node.depth, allFontSizes.length) - 1]; | ||
| const { textColor, textInvertible, fontStyle, fontVariant, fontFamily, fontWeight, valueFormatter } = Object.assign( | ||
| { fontFamily: config.fontFamily, fontWeight: 'normal' }, | ||
| fillLabel, | ||
|
|
@@ -337,13 +341,16 @@ function fill( | |
| : `rgba(${255 - tr}, ${255 - tg}, ${255 - tb}, ${to})` | ||
| : textColor, | ||
| rotation, | ||
| verticalAlignment, | ||
| leftAlign: leftAlign, | ||
| rows: [...Array(targetRowCount)].map(() => ({ | ||
| rowWords: [], | ||
| rowCentroidX: NaN, | ||
| rowCentroidY: NaN, | ||
| maximumLength: NaN, | ||
| length: NaN, | ||
| })), | ||
| container, | ||
| }; | ||
|
|
||
| let currentRowIndex = 0; | ||
|
|
@@ -361,6 +368,7 @@ function fill( | |
| currentRowIndex, | ||
| fontSize, | ||
| rotation, | ||
| verticalAlignment, | ||
| ); | ||
|
|
||
| currentRow.rowCentroidX = rowCentroidX; | ||
|
|
@@ -430,24 +438,34 @@ export function fillTextLayout( | |
| shapeConstructor: (n: ShapeTreeNode) => any, | ||
| getShapeRowGeometry: (...args: any[]) => RowSpace, | ||
| getRotation: Function, | ||
| leftAlign: boolean, | ||
| middleAlign: boolean, | ||
| ) { | ||
| const { minFontSize, maxFontSize, idealFontSizeJump } = config; | ||
| const fontSizeMagnification = maxFontSize / minFontSize; | ||
| const fontSizeJumpCount = Math.round(logarithm(idealFontSizeJump, fontSizeMagnification)); | ||
| const realFontSizeJump = Math.pow(fontSizeMagnification, 1 / fontSizeJumpCount); | ||
| const fontSizes: Pixels[] = []; | ||
| for (let i = 0; i <= fontSizeJumpCount; i++) { | ||
| const fontSize = Math.round(minFontSize * Math.pow(realFontSizeJump, i)); | ||
| if (fontSizes.indexOf(fontSize) === -1) { | ||
| fontSizes.push(fontSize); | ||
| const allFontSizes: Pixels[][] = []; | ||
| for (let l = 0; l <= layers.length; l++) { | ||
| // get font size spec from config, which layer.fillLabel properties can override | ||
| const { minFontSize, maxFontSize, idealFontSizeJump } = { | ||
| ...config, | ||
| ...(l < layers.length && layers[l].fillLabel), | ||
| }; | ||
| const fontSizeMagnification = maxFontSize / minFontSize; | ||
| const fontSizeJumpCount = Math.round(logarithm(idealFontSizeJump, fontSizeMagnification)); | ||
| const realFontSizeJump = Math.pow(fontSizeMagnification, 1 / fontSizeJumpCount); | ||
| const fontSizes: Pixels[] = []; | ||
| for (let i = 0; i <= fontSizeJumpCount; i++) { | ||
| const fontSize = Math.round(minFontSize * Math.pow(realFontSizeJump, i)); | ||
| if (fontSizes.indexOf(fontSize) === -1) { | ||
| fontSizes.push(fontSize); | ||
| } | ||
| } | ||
| allFontSizes.push(fontSizes); | ||
| } | ||
|
|
||
| return childNodes.map( | ||
| fill( | ||
| config, | ||
| layers, | ||
| fontSizes, | ||
| allFontSizes, | ||
| measure, | ||
| rawTextGetter, | ||
| valueGetter, | ||
|
|
@@ -456,6 +474,8 @@ export function fillTextLayout( | |
| shapeConstructor, | ||
| getShapeRowGeometry, | ||
| getRotation, | ||
| leftAlign, | ||
| middleAlign, | ||
| ), | ||
| ); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.