use canvas to measure text width
This commit is contained in:
1 parent
dab1d8ee8a
commit
18d9c2cefb
2 files changed
+61
-29
No files matched your search
@@ -2,8 +2,6 @@ import { useWorkspace } from "@/contexts/workspace-context";
|
|||||||
import { TreeGraphData, getNodeType } from "@/misc/b3type";
|
import { TreeGraphData, getNodeType } from "@/misc/b3type";
|
||||||
import { checkTreeData, cutWordTo, toBreakWord } from "@/misc/b3util";
|
import { checkTreeData, cutWordTo, toBreakWord } from "@/misc/b3util";
|
||||||
import i18n from "@/misc/i18n";
|
import i18n from "@/misc/i18n";
|
||||||
import { isMacos } from "@/misc/keys";
|
|
||||||
import Path from "@/misc/path";
|
|
||||||
import G6 from "@antv/g6";
|
import G6 from "@antv/g6";
|
||||||
|
|
||||||
const NODE_COLORS: any = {
|
const NODE_COLORS: any = {
|
||||||
@@ -250,7 +248,7 @@ G6.registerNode(
|
|||||||
let desc = (cfg.desc || nodeDef.desc) as string;
|
let desc = (cfg.desc || nodeDef.desc) as string;
|
||||||
if (desc) {
|
if (desc) {
|
||||||
desc = i18n.t("regnode.mark") + desc;
|
desc = i18n.t("regnode.mark") + desc;
|
||||||
desc = cutWordTo(desc, 33);
|
desc = cutWordTo(desc, w - 15);
|
||||||
addShape("text", {
|
addShape("text", {
|
||||||
attrs: {
|
attrs: {
|
||||||
textBaseline: "top",
|
textBaseline: "top",
|
||||||
@@ -267,7 +265,7 @@ G6.registerNode(
|
|||||||
|
|
||||||
const args: any = cfg.args;
|
const args: any = cfg.args;
|
||||||
if (nodeDef.args && args && Object.keys(args).length > 0) {
|
if (nodeDef.args && args && Object.keys(args).length > 0) {
|
||||||
const { str, line } = toBreakWord(`${i18n.t("regnode.args")}${JSON.stringify(args)}`, 36);
|
const { str, line } = toBreakWord(`${i18n.t("regnode.args")}${JSON.stringify(args)}`, 200);
|
||||||
addShape("text", {
|
addShape("text", {
|
||||||
attrs: {
|
attrs: {
|
||||||
textBaseline: "top",
|
textBaseline: "top",
|
||||||
@@ -285,7 +283,10 @@ G6.registerNode(
|
|||||||
|
|
||||||
const input: [] = cfg.input ? (cfg.input as []) : [];
|
const input: [] = cfg.input ? (cfg.input as []) : [];
|
||||||
if (nodeDef.input && input.length > 0) {
|
if (nodeDef.input && input.length > 0) {
|
||||||
const { str, line } = toBreakWord(`${i18n.t("regnode.input")}${JSON.stringify(input)}`, 35);
|
const { str, line } = toBreakWord(
|
||||||
|
`${i18n.t("regnode.input")}${JSON.stringify(input)}`,
|
||||||
|
200
|
||||||
|
);
|
||||||
if (cfg.highlightInput) {
|
if (cfg.highlightInput) {
|
||||||
addShape("rect", {
|
addShape("rect", {
|
||||||
attrs: {
|
attrs: {
|
||||||
@@ -322,7 +323,7 @@ G6.registerNode(
|
|||||||
if (nodeDef.output && output.length > 0) {
|
if (nodeDef.output && output.length > 0) {
|
||||||
const { str, line } = toBreakWord(
|
const { str, line } = toBreakWord(
|
||||||
`${i18n.t("regnode.output")}${JSON.stringify(output)}`,
|
`${i18n.t("regnode.output")}${JSON.stringify(output)}`,
|
||||||
35
|
200
|
||||||
);
|
);
|
||||||
if (cfg.highlightOutput) {
|
if (cfg.highlightOutput) {
|
||||||
addShape("rect", {
|
addShape("rect", {
|
||||||
@@ -358,7 +359,7 @@ G6.registerNode(
|
|||||||
|
|
||||||
if (cfg.path) {
|
if (cfg.path) {
|
||||||
let path = (i18n.t("regnode.subtree") + cfg.path) as string;
|
let path = (i18n.t("regnode.subtree") + cfg.path) as string;
|
||||||
path = cutWordTo(path, 35);
|
path = cutWordTo(path, w - 15);
|
||||||
addShape("text", {
|
addShape("text", {
|
||||||
attrs: {
|
attrs: {
|
||||||
textBaseline: "top",
|
textBaseline: "top",
|
||||||
|
|||||||
+53
-22
@@ -4,6 +4,45 @@ import * as fs from "fs";
|
|||||||
import { message } from "./hooks";
|
import { message } from "./hooks";
|
||||||
import Path from "./path";
|
import Path from "./path";
|
||||||
import { zhNodeDef } from "./template";
|
import { zhNodeDef } from "./template";
|
||||||
|
import i18n from "@/misc/i18n";
|
||||||
|
import { isMacos } from "./keys";
|
||||||
|
|
||||||
|
let ctx: CanvasRenderingContext2D | null = null;
|
||||||
|
let defaultFontSize = "";
|
||||||
|
const textWidthMap = new Map<string, number>();
|
||||||
|
|
||||||
|
const isAsciiChar = (c: number) => {
|
||||||
|
return (c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f);
|
||||||
|
};
|
||||||
|
|
||||||
|
const calcTextWith = (text: string, fontSize?: string) => {
|
||||||
|
fontSize = fontSize ?? defaultFontSize;
|
||||||
|
let b3Workspace: HTMLDivElement | null;
|
||||||
|
let css: CSSStyleDeclaration | null;
|
||||||
|
if (!fontSize) {
|
||||||
|
b3Workspace = document.querySelector(".b3-workspace");
|
||||||
|
if (b3Workspace) {
|
||||||
|
css = getComputedStyle(b3Workspace);
|
||||||
|
defaultFontSize = css.fontSize || "13px";
|
||||||
|
fontSize = defaultFontSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const key = `${text}-${fontSize}`;
|
||||||
|
let width = textWidthMap.get(key);
|
||||||
|
if (!width) {
|
||||||
|
b3Workspace ||= document.querySelector(".b3-workspace");
|
||||||
|
if (b3Workspace) {
|
||||||
|
css ||= getComputedStyle(b3Workspace);
|
||||||
|
ctx = ctx || document.createElement("canvas").getContext("2d")!;
|
||||||
|
ctx.font = `${fontSize} ${css.fontFamily}`;
|
||||||
|
const metrics = ctx.measureText(text);
|
||||||
|
width = metrics.width;
|
||||||
|
width = width - (isMacos ? 1.6 : 0.8);
|
||||||
|
textWidthMap.set(key, width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return width ?? 13;
|
||||||
|
};
|
||||||
|
|
||||||
export const isSubtreeRoot = (data: TreeGraphData) => {
|
export const isSubtreeRoot = (data: TreeGraphData) => {
|
||||||
return data.path && data.id.toString() !== "1";
|
return data.path && data.id.toString() !== "1";
|
||||||
@@ -395,8 +434,8 @@ export const refreshTreeDataId = (data: TreeGraphData, id?: number) => {
|
|||||||
export const calcTreeDataSize = (data: TreeGraphData) => {
|
export const calcTreeDataSize = (data: TreeGraphData) => {
|
||||||
let height = 50 + 2;
|
let height = 50 + 2;
|
||||||
const updateHeight = (obj: any) => {
|
const updateHeight = (obj: any) => {
|
||||||
if (Array.isArray(obj) || (obj && Object.keys(obj).length > 0)) {
|
if ((Array.isArray(obj) && obj.length) || (obj && Object.keys(obj).length > 0)) {
|
||||||
const { str, line } = toBreakWord(`参数:${JSON.stringify(obj)}`, 35);
|
const { line } = toBreakWord(`${i18n.t("regnode.args")}${JSON.stringify(obj)}`, 200);
|
||||||
height += 20 * line;
|
height += 20 * line;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -563,24 +602,16 @@ export const isTreeFile = (path: string) => {
|
|||||||
return path.toLocaleLowerCase().endsWith(".json");
|
return path.toLocaleLowerCase().endsWith(".json");
|
||||||
};
|
};
|
||||||
|
|
||||||
const isAsciiChar = (c: number) => {
|
export const toBreakWord = (str: string, maxWidth: number, fontSize?: string) => {
|
||||||
return (c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f);
|
|
||||||
};
|
|
||||||
|
|
||||||
const isUppercase = (c: number) => {
|
|
||||||
return c >= 0x0041 && c <= 0x005a;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toBreakWord = (str: string, maxlen: number) => {
|
|
||||||
const chars: string[] = [];
|
const chars: string[] = [];
|
||||||
let line = 1;
|
let line = str.length > 0 ? 1 : 0;
|
||||||
let len = 0;
|
let width = maxWidth;
|
||||||
for (let i = 0; i < str.length; i++) {
|
for (let i = 0; i < str.length; i++) {
|
||||||
const c = str.charCodeAt(i);
|
width -= calcTextWith(str.charAt(i), fontSize);
|
||||||
len += isAsciiChar(c) ? (isUppercase(c) ? 1.5 : 1) : 2;
|
if (width > 0) {
|
||||||
chars.push(String.fromCharCode(c));
|
chars.push(str.charAt(i));
|
||||||
if (len >= maxlen && i < str.length - 1) {
|
} else {
|
||||||
len = 0;
|
width = maxWidth;
|
||||||
line++;
|
line++;
|
||||||
chars.push("\n");
|
chars.push("\n");
|
||||||
}
|
}
|
||||||
@@ -591,12 +622,12 @@ export const toBreakWord = (str: string, maxlen: number) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cutWordTo = (str: string, maxlen: number) => {
|
export const cutWordTo = (str: string, maxWidth: number, fontSize?: string) => {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (; i < str.length; i++) {
|
for (; i < str.length; i++) {
|
||||||
const c = str.charCodeAt(i);
|
maxWidth -= calcTextWith(str.charAt(i), fontSize);
|
||||||
maxlen -= isAsciiChar(c) ? (isUppercase(c) ? 1.5 : 1) : 2;
|
if (maxWidth < 0) {
|
||||||
if (maxlen <= 0) {
|
i--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user