diff options
author | Thomas F. K. Jorna <[email protected]> | 2021-10-15 20:46:04 +0200 |
---|---|---|
committer | Thomas F. K. Jorna <[email protected]> | 2021-10-15 20:46:15 +0200 |
commit | 35dd8336b5a56ee95e54700df322d53df2f56e85 (patch) | |
tree | 1c38cc6a4d734b1c49bc0332a7e4bce2a3698e5f | |
parent | ad692d23912a82778a15974e11f578422037b0c1 (diff) |
feat(labels): separate labeldrawing
-rw-r--r-- | components/Graph/drawLabels.ts | 104 | ||||
-rw-r--r-- | pages/index.tsx | 84 |
2 files changed, 118 insertions, 70 deletions
diff --git a/components/Graph/drawLabels.ts b/components/Graph/drawLabels.ts new file mode 100644 index 0000000..d2d84f8 --- /dev/null +++ b/components/Graph/drawLabels.ts @@ -0,0 +1,104 @@ +import { OrgRoamNode } from '../../api' +import { NodeObject } from 'force-graph' +import { initialVisuals } from '../config' +import { hexToRGBA } from '../../pages' +import wrap from 'word-wrap' + +export interface drawLabelsProps { + labelBackgroundColor: string + labelTextColor: string + node: NodeObject + ctx: any + globalScale: number + highlightedNodes: { [id: string]: {} } + previouslyHighlightedNodes: { [id: string]: {} } + visuals: typeof initialVisuals + opacity: number + nodeSize: (node: NodeObject) => number +} +export function drawLabels(props: drawLabelsProps) { + const { + labelBackgroundColor, + labelTextColor, + node, + ctx, + globalScale, + highlightedNodes, + previouslyHighlightedNodes, + visuals, + opacity, + nodeSize, + } = props + + if (!node) { + return + } + //if (dragging) { + // return + //} + + if (!visuals.labels) { + return + } + const wasHighlightedNode = previouslyHighlightedNodes[node.id!] + + if ( + (globalScale <= visuals.labelScale || visuals.labels === 1) && + !highlightedNodes[node.id!] && + !wasHighlightedNode + ) { + return + } + + const nodeTitle = (node as OrgRoamNode).title! + const label = nodeTitle.substring(0, visuals.labelLength) + const fontSize = visuals.labelFontSize / (0.75 * Math.min(Math.max(0.5, globalScale), 3)) + const textWidth = ctx.measureText(label).width + const bckgDimensions = [textWidth * 1.1, fontSize].map((n) => n + fontSize * 0.5) as [ + number, + number, + ] // some padding + + const fadeFactor = Math.min((3 * (globalScale - visuals.labelScale)) / visuals.labelScale, 1) + + // draw label background + const getLabelOpacity = () => { + if (visuals.labels === 1) { + return opacity + } + if (globalScale <= visuals.labelScale) { + return opacity + } + return highlightedNodes[node.id!] || previouslyHighlightedNodes[node.id!] + ? Math.max(fadeFactor, opacity) + : 1 * fadeFactor * (-1 * (visuals.highlightFade * opacity - 1)) + } + const nodeS = 8 * Math.cbrt(nodeSize(node) * visuals.nodeRel) + if (visuals.labelBackgroundColor && visuals.labelBackgroundOpacity) { + const backgroundOpacity = getLabelOpacity() * visuals.labelBackgroundOpacity + const labelBackground = hexToRGBA(labelBackgroundColor, backgroundOpacity) + ctx.fillStyle = labelBackground + ctx.fillRect( + node.x! - bckgDimensions[0] / 2, + node.y! - bckgDimensions[1] / 2 + nodeS, + ...bckgDimensions, + ) + } + + // draw label text + const textOpacity = getLabelOpacity() + ctx.textAlign = 'center' + ctx.textBaseline = 'middle' + const labelText = hexToRGBA(labelTextColor, textOpacity) + ctx.fillStyle = labelText + ctx.font = `${fontSize}px Sans-Serif` + const wordsArray = wrap(label, { width: visuals.labelWordWrap }).split('\n') + + const truncatedWords = + nodeTitle.length > visuals.labelLength + ? [...wordsArray.slice(0, -1), `${wordsArray.slice(-1)}...`] + : wordsArray + truncatedWords.forEach((word, index) => { + ctx.fillText(word, node.x!, node.y! + nodeS + visuals.labelLineSpace * fontSize * index) + }) +} diff --git a/pages/index.tsx b/pages/index.tsx index 2b8b6c7..ab4a96d 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -52,6 +52,7 @@ import { Tweaks } from '../components/Tweaks' import { usePersistantState } from '../util/persistant-state' import { ThemeContext, ThemeContextProps } from '../util/themecontext' import { openNodeInEmacs } from '../util/webSocketFunctions' +import { drawLabels } from '../components/Graph/drawLabels' const d3promise = import('d3-force-3d') @@ -1217,76 +1218,19 @@ export const Graph = function (props: GraphProps) { return nodeSize(node) / Math.pow(scaleRef.current, visuals.nodeZoomSize) }, nodeCanvasObject: (node, ctx, globalScale) => { - if (!node) { - return - } - if (dragging) { - return - } - - if (!visuals.labels) { - return - } - const wasHighlightedNode = previouslyHighlightedNodes[node.id!] - - if ( - (globalScale <= visuals.labelScale || visuals.labels === 1) && - !highlightedNodes[node.id!] && - !wasHighlightedNode - ) { - return - } - - const nodeTitle = (node as OrgRoamNode).title! - const label = nodeTitle.substring(0, visuals.labelLength) - const fontSize = visuals.labelFontSize / (0.75 * Math.min(Math.max(0.5, globalScale), 3)) - const textWidth = ctx.measureText(label).width - const bckgDimensions = [textWidth * 1.1, fontSize].map((n) => n + fontSize * 0.5) as [ - number, - number, - ] // some padding - - const fadeFactor = Math.min((3 * (globalScale - visuals.labelScale)) / visuals.labelScale, 1) - - // draw label background - const getLabelOpacity = () => { - if (visuals.labels === 1) { - return opacity - } - if (globalScale <= visuals.labelScale) { - return opacity - } - return highlightedNodes[node.id!] || previouslyHighlightedNodes[node.id!] - ? Math.max(fadeFactor, opacity) - : 1 * fadeFactor * (-1 * (visuals.highlightFade * opacity - 1)) - } - const nodeS = 8 * Math.cbrt(nodeSize(node) * visuals.nodeRel) - if (visuals.labelBackgroundColor && visuals.labelBackgroundOpacity) { - const backgroundOpacity = getLabelOpacity() * visuals.labelBackgroundOpacity - const labelBackground = hexToRGBA(labelBackgroundColor, backgroundOpacity) - ctx.fillStyle = labelBackground - ctx.fillRect( - node.x! - bckgDimensions[0] / 2, - node.y! - bckgDimensions[1] / 2 + nodeS, - ...bckgDimensions, - ) - } - - // draw label text - const textOpacity = getLabelOpacity() - ctx.textAlign = 'center' - ctx.textBaseline = 'middle' - const labelText = hexToRGBA(labelTextColor, textOpacity) - ctx.fillStyle = labelText - ctx.font = `${fontSize}px Sans-Serif` - const wordsArray = wrap(label, { width: visuals.labelWordWrap }).split('\n') - - const truncatedWords = - nodeTitle.length > visuals.labelLength - ? [...wordsArray.slice(0, -1), `${wordsArray.slice(-1)}...`] - : wordsArray - truncatedWords.forEach((word, index) => { - ctx.fillText(word, node.x!, node.y! + nodeS + visuals.labelLineSpace * fontSize * index) + drawLabels({ + ...{ + node, + ctx, + globalScale, + highlightedNodes, + previouslyHighlightedNodes, + visuals, + opacity, + nodeSize, + labelTextColor, + labelBackgroundColor, + }, }) }, nodeCanvasObjectMode: () => 'after', |