mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: introduce font picker (#8012)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
4c5408263c
commit
62228e0bbb
120 changed files with 3390 additions and 1106 deletions
|
@ -321,7 +321,6 @@ import {
|
|||
getBoundTextElement,
|
||||
getContainerCenter,
|
||||
getContainerElement,
|
||||
getDefaultLineHeight,
|
||||
getLineHeightInPx,
|
||||
getMinTextElementWidth,
|
||||
isMeasureTextSupported,
|
||||
|
@ -337,7 +336,7 @@ import {
|
|||
import { isLocalLink, normalizeLink, toValidURL } from "../data/url";
|
||||
import { shouldShowBoundingBox } from "../element/transformHandles";
|
||||
import { actionUnlockAllElements } from "../actions/actionElementLock";
|
||||
import { Fonts } from "../scene/Fonts";
|
||||
import { Fonts, getLineHeight } from "../fonts";
|
||||
import {
|
||||
getFrameChildren,
|
||||
isCursorInFrame,
|
||||
|
@ -532,8 +531,8 @@ class App extends React.Component<AppProps, AppState> {
|
|||
private excalidrawContainerRef = React.createRef<HTMLDivElement>();
|
||||
|
||||
public scene: Scene;
|
||||
public fonts: Fonts;
|
||||
public renderer: Renderer;
|
||||
private fonts: Fonts;
|
||||
private resizeObserver: ResizeObserver | undefined;
|
||||
private nearestScrollableContainer: HTMLElement | Document | undefined;
|
||||
public library: AppClassProperties["library"];
|
||||
|
@ -2335,11 +2334,6 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}),
|
||||
};
|
||||
}
|
||||
// FontFaceSet loadingdone event we listen on may not always fire
|
||||
// (looking at you Safari), so on init we manually load fonts for current
|
||||
// text elements on canvas, and rerender them once done. This also
|
||||
// seems faster even in browsers that do fire the loadingdone event.
|
||||
this.fonts.loadFontsForElements(scene.elements);
|
||||
|
||||
this.resetStore();
|
||||
this.resetHistory();
|
||||
|
@ -2347,6 +2341,12 @@ class App extends React.Component<AppProps, AppState> {
|
|||
...scene,
|
||||
storeAction: StoreAction.UPDATE,
|
||||
});
|
||||
|
||||
// FontFaceSet loadingdone event we listen on may not always
|
||||
// fire (looking at you Safari), so on init we manually load all
|
||||
// fonts and rerender scene text elements once done. This also
|
||||
// seems faster even in browsers that do fire the loadingdone event.
|
||||
this.fonts.load();
|
||||
};
|
||||
|
||||
private isMobileBreakpoint = (width: number, height: number) => {
|
||||
|
@ -2439,6 +2439,10 @@ class App extends React.Component<AppProps, AppState> {
|
|||
configurable: true,
|
||||
value: this.store,
|
||||
},
|
||||
fonts: {
|
||||
configurable: true,
|
||||
value: this.fonts,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2576,7 +2580,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
// rerender text elements on font load to fix #637 && #1553
|
||||
addEventListener(document.fonts, "loadingdone", (event) => {
|
||||
const loadedFontFaces = (event as FontFaceSetLoadEvent).fontfaces;
|
||||
this.fonts.onFontsLoaded(loadedFontFaces);
|
||||
this.fonts.onLoaded(loadedFontFaces);
|
||||
}),
|
||||
// Safari-only desktop pinch zoom
|
||||
addEventListener(
|
||||
|
@ -3379,7 +3383,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
fontSize: textElementProps.fontSize,
|
||||
fontFamily: textElementProps.fontFamily,
|
||||
});
|
||||
const lineHeight = getDefaultLineHeight(textElementProps.fontFamily);
|
||||
const lineHeight = getLineHeight(textElementProps.fontFamily);
|
||||
const [x1, , x2] = getVisibleSceneBounds(this.state);
|
||||
// long texts should not go beyond 800 pixels in width nor should it go below 200 px
|
||||
const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.5, 800), 200);
|
||||
|
@ -3397,13 +3401,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||
});
|
||||
|
||||
let metrics = measureText(originalText, fontString, lineHeight);
|
||||
const isTextWrapped = metrics.width > maxTextWidth;
|
||||
const isTextUnwrapped = metrics.width > maxTextWidth;
|
||||
|
||||
const text = isTextWrapped
|
||||
const text = isTextUnwrapped
|
||||
? wrapText(originalText, fontString, maxTextWidth)
|
||||
: originalText;
|
||||
|
||||
metrics = isTextWrapped
|
||||
metrics = isTextUnwrapped
|
||||
? measureText(text, fontString, lineHeight)
|
||||
: metrics;
|
||||
|
||||
|
@ -3417,7 +3421,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
text,
|
||||
originalText,
|
||||
lineHeight,
|
||||
autoResize: !isTextWrapped,
|
||||
autoResize: !isTextUnwrapped,
|
||||
frameId: topLayerFrame ? topLayerFrame.id : null,
|
||||
});
|
||||
acc.push(element);
|
||||
|
@ -4107,6 +4111,36 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!event[KEYS.CTRL_OR_CMD] &&
|
||||
event.shiftKey &&
|
||||
event.key.toLowerCase() === KEYS.F
|
||||
) {
|
||||
const selectedElements = this.scene.getSelectedElements(this.state);
|
||||
|
||||
if (
|
||||
this.state.activeTool.type === "selection" &&
|
||||
!selectedElements.length
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
this.state.activeTool.type === "text" ||
|
||||
selectedElements.find(
|
||||
(element) =>
|
||||
isTextElement(element) ||
|
||||
getBoundTextElement(
|
||||
element,
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
),
|
||||
)
|
||||
) {
|
||||
event.preventDefault();
|
||||
this.setState({ openPopup: "fontFamily" });
|
||||
}
|
||||
}
|
||||
|
||||
if (event.key === KEYS.K && !event.altKey && !event[KEYS.CTRL_OR_CMD]) {
|
||||
if (this.state.activeTool.type === "laser") {
|
||||
this.setActiveTool({ type: "selection" });
|
||||
|
@ -4761,7 +4795,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
existingTextElement?.fontFamily || this.state.currentItemFontFamily;
|
||||
|
||||
const lineHeight =
|
||||
existingTextElement?.lineHeight || getDefaultLineHeight(fontFamily);
|
||||
existingTextElement?.lineHeight || getLineHeight(fontFamily);
|
||||
const fontSize = this.state.currentItemFontSize;
|
||||
|
||||
if (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue