-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cd449ae
commit 8784aac
Showing
9 changed files
with
111 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export { Rectangle } from "./rectangle"; | ||
export { Line } from "./line"; | ||
export { HandDrawn } from "./handdrawn"; | ||
export { Text } from "./text"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { nanoid } from "nanoid"; | ||
import Shape from "./shape"; | ||
import { Point, getCorrectCoordOrder } from "@/utils"; | ||
import { FontTypeOptions, TextOptions, TextRequiredOptions } from "@/types/general"; | ||
import { useStore } from "@/store"; | ||
const { getElementConfigState: getConfigState } = useStore.getState(); | ||
export class Text extends Shape<TextOptions & TextRequiredOptions> { | ||
// todo add a cache canvas for text | ||
protected options!: TextOptions & TextRequiredOptions; | ||
protected text!: string[]; | ||
protected boundingRect!: [Point, Point]; | ||
constructor(options: Partial<TextOptions> & TextRequiredOptions) { | ||
super(nanoid(), "rectangle"); | ||
this.generate(options); | ||
} | ||
public generate(options: Partial<TextOptions> & TextRequiredOptions) { | ||
const normalizedOptions = this.normalizeOptions(options); | ||
const tempCanvas = document.createElement("canvas"); | ||
const ctx = tempCanvas.getContext("2d"); | ||
if (!ctx) throw new Error("GENERATE TEXT: must have ctx to be able to create new text"); | ||
const lines = options.text.split("\n"); | ||
// text element width is the largest line width | ||
let largestLineIndex = 0; | ||
let tempLen = lines[0].length; | ||
lines.forEach((val, i) => { | ||
if (val.length > tempLen) { | ||
tempLen = val.length; | ||
largestLineIndex = i; | ||
} | ||
}); | ||
ctx.save(); | ||
ctx.font = `${normalizedOptions.fontSize}px ` + FontTypeOptions[normalizedOptions.font]; | ||
const width = ctx.measureText(lines[largestLineIndex]).width; | ||
ctx.restore(); | ||
// note using font-size as line height | ||
// calc height = number of lines * lineHeight | ||
const height = lines.length * normalizedOptions.fontSize; | ||
const text = lines; | ||
const endPos = [options.point1[0] + width, options.point1[1] + height]; | ||
const { x, y, endX, endY } = getCorrectCoordOrder(options.point1, endPos as Point); | ||
this.boundingRect = [ | ||
[x, y], | ||
[endX, endY], | ||
]; | ||
this.text = text; | ||
this.options = normalizedOptions; | ||
return this; | ||
} | ||
public regenerate(options: Partial<TextOptions & TextRequiredOptions>) { | ||
return this.generate({ | ||
...this.options, | ||
...options, | ||
}); | ||
} | ||
private normalizeOptions( | ||
options: Partial<TextOptions> & TextRequiredOptions, | ||
): TextOptions & TextRequiredOptions { | ||
const globalConfig = getConfigState(); | ||
const zoom = useStore.getState().zoomLevel; | ||
return { | ||
...options, | ||
opacity: options.opacity || globalConfig.opacity, | ||
stroke: options.stroke || globalConfig.stroke, | ||
strokeWidth: options.strokeWidth || globalConfig.strokeWidth, | ||
font: options.font || globalConfig.font, | ||
fontSize: options.fontSize || globalConfig.fontSize, | ||
zoom: options.zoom || zoom, | ||
}; | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
public render(ctx: CanvasRenderingContext2D, zoom: number): void { | ||
ctx.save(); | ||
ctx.font = `${this.options.fontSize}px ` + FontTypeOptions[this.options.font]; | ||
ctx.fillStyle = this.options.stroke; | ||
ctx.textBaseline = "top"; | ||
this.text.forEach((val, i) => | ||
ctx.fillText( | ||
val, | ||
this.boundingRect[0][0], | ||
this.boundingRect[0][1] + i * this.options.fontSize, | ||
), | ||
); | ||
ctx.restore(); | ||
} | ||
public copy() { | ||
return { ...this.options, shape: this.shape }; | ||
} | ||
public move(walkX: number, walkY: number) { | ||
const newStart = [this.options.point1[0] + walkX, this.options.point1[1] + walkY] as Point; | ||
return this.regenerate({ | ||
point1: newStart, | ||
}); | ||
} | ||
} |