API Reference
@tecack/frontend
createTecack()
Creates Tecack instance for drawing on canvas.
Type
tsfunction createTecack(options?: TecackOptions): Tecack;
function createTecack(options?: TecackOptions): Tecack;
Example
tsimport { createTecack } from "@tecack/frontend"; const tecack = createTecack();
import { createTecack } from "@tecack/frontend"; const tecack = createTecack();
TecackOptions.backgroundPainter
Type
tsexport interface TecackOptions { backgroundPainter?: (el: HTMLCanvasElement) => void; }
export interface TecackOptions { backgroundPainter?: (el: HTMLCanvasElement) => void; }
Example
if you want to paint fixed background, configure background painter
tsimport { createTecack } from "@tecack/frontend"; const tecack = createTecack({ backgroundPainter: canvas => { const ctx = canvas.getContext("2d"); if (!ctx) return; const [w, h] = [el.width, el.height]; ctx.fillStyle = "#ccc"; ctx.fillRect(0, 0, w, h); }, });
import { createTecack } from "@tecack/frontend"; const tecack = createTecack({ backgroundPainter: canvas => { const ctx = canvas.getContext("2d"); if (!ctx) return; const [w, h] = [el.width, el.height]; ctx.fillStyle = "#ccc"; ctx.fillRect(0, 0, w, h); }, });
Tecack.mount()
Mounts Tecack instance to canvas element.
Type
tsfunction mount(selector: string): void | InitializeError;
function mount(selector: string): void | InitializeError;
Example
tsimport { createTecack, InitializeError } from "@tecack/frontend"; const tecack = createTecack(); const res = tecack.mount("#my-canvas"); if (res instanceof InitializeError) { // handle error }
import { createTecack, InitializeError } from "@tecack/frontend"; const tecack = createTecack(); const res = tecack.mount("#my-canvas"); if (res instanceof InitializeError) { // handle error }
Tecack.unmount()
unmounts canvas element from Tecack instance.
The contents of the tecack instance are retained, only the association with the DOM is removed.
(Discard retention of event listeners and $el's.)
In the default state, canvas is cleaned up and the drawing content is overwritten in the background if backgroundPainter is set.
Type
tsfunction unmount(options?: { /** default: `true` */ cleanCanvas?: boolean; /** * default: `false` * * When this option is enabled, the cleanCanvas option is ignored. */ force?: boolean; }): void;
function unmount(options?: { /** default: `true` */ cleanCanvas?: boolean; /** * default: `false` * * When this option is enabled, the cleanCanvas option is ignored. */ force?: boolean; }): void;
Example
tsimport { createTecack, InitializeError } from "@tecack/frontend"; const tecack = createTecack(); tecack.mount("#my-canvas"); tecack.unmount();
import { createTecack, InitializeError } from "@tecack/frontend"; const tecack = createTecack(); tecack.mount("#my-canvas"); tecack.unmount();
ts// setting cleanCanvas to false will keep the current canvas drawing state tecack.unmount({ cleanCanvas: false });
// setting cleanCanvas to false will keep the current canvas drawing state tecack.unmount({ cleanCanvas: false });
ts// umount the canvas with a complete cleanup (Background is not rendered.) tecack.unmount({ force: false });
// umount the canvas with a complete cleanup (Background is not rendered.) tecack.unmount({ force: false });
Tecack.deleteLast()
Deletes last stroke from canvas and instance internal data.
Type
tsfunction deleteLast(): void | CanvasCtxNotFoundError;
function deleteLast(): void | CanvasCtxNotFoundError;
Example
tsimport { createTecack, CanvasCtxNotFoundError } from "@tecack/frontend"; const tecack = createTecack(); tecack.mount("#my-canvas"); const deleteLastButton = document.getElementById("delete-last"); deleteLastButton.addEventListener("click", () => { const res = tecack.deleteLast(); if (res instanceof CanvasCtxNotFoundError) { // handle error } });
import { createTecack, CanvasCtxNotFoundError } from "@tecack/frontend"; const tecack = createTecack(); tecack.mount("#my-canvas"); const deleteLastButton = document.getElementById("delete-last"); deleteLastButton.addEventListener("click", () => { const res = tecack.deleteLast(); if (res instanceof CanvasCtxNotFoundError) { // handle error } });
Tecack.erase()
Erases all strokes from canvas and instance internal data.
Type
tsfunction erase(): void | CanvasCtxNotFoundError;
function erase(): void | CanvasCtxNotFoundError;
Example
tsimport { createTecack, CanvasCtxNotFoundError } from "@tecack/frontend"; const tecack = createTecack(); tecack.mount("#my-canvas"); const eraseButton = document.getElementById("erase"); eraseButton.addEventListener("click", () => { const res = tecack.erase(); if (res instanceof CanvasCtxNotFoundError) { // handle error } });
import { createTecack, CanvasCtxNotFoundError } from "@tecack/frontend"; const tecack = createTecack(); tecack.mount("#my-canvas"); const eraseButton = document.getElementById("erase"); eraseButton.addEventListener("click", () => { const res = tecack.erase(); if (res instanceof CanvasCtxNotFoundError) { // handle error } });
Tecack.getStrokes()
Get strokes data from instance internal.
You can use this data for restore strokes or backend recognition.
Type
tsfunction getStrokes(): Readonly<Array<TecackStroke>>;
function getStrokes(): Readonly<Array<TecackStroke>>;
Example
tsimport { createTecack } from "@tecack/frontend"; const tecack = createTecack(); tecack.mount("#my-canvas"); const strokes = tecack.getStrokes(); console.log(strokes);
import { createTecack } from "@tecack/frontend"; const tecack = createTecack(); tecack.mount("#my-canvas"); const strokes = tecack.getStrokes(); console.log(strokes);
tsimport { recognize } from "@tecack/backend"; const strokes = tecack.getStrokes(); const candidates = recognize(strokes);
import { recognize } from "@tecack/backend"; const strokes = tecack.getStrokes(); const candidates = recognize(strokes);
Tecack.restoreFromStrokes()
Restores canvas strokes and internal data from existing strokes data.
Type
tsfunction restoreFromStrokes( strokesMut: Readonly<Array<TecackStroke>>, options?: { /** default: `true` */ withDraw: boolean; }, ): void;
function restoreFromStrokes( strokesMut: Readonly<Array<TecackStroke>>, options?: { /** default: `true` */ withDraw: boolean; }, ): void;
Example
tsconst strokes = JSON.parse(localStorage.getItem("strokes")); tecack.restoreFromStrokes(strokes);
const strokes = JSON.parse(localStorage.getItem("strokes")); tecack.restoreFromStrokes(strokes);
Tecack.drawStrokeOrder()
It draws the stroke order on the strokes entered into the Canvas.
Type
tsfunction drawStrokeOrder(options?: DrawStrokeOrderOptions): void | CanvasCtxNotFoundError;
function drawStrokeOrder(options?: DrawStrokeOrderOptions): void | CanvasCtxNotFoundError;
Example
tstecack.drawStrokeOrder();
tecack.drawStrokeOrder();
DrawStrokeOrderOptions
Options for Tecack.drawStrokeOrder()
Type
tsexport interface DrawStrokeOrderOptions { withColor?: boolean; colorSet?: Array<string>; font?: { family?: string; size?: string; }; }
export interface DrawStrokeOrderOptions { withColor?: boolean; colorSet?: Array<string>; font?: { family?: string; size?: string; }; }
DrawStrokeOrderOptions.withColor
When withColor
is enabled, it draws each stroke in a different color.
This is to make it easier to understand which stroke order corresponds to which stroke.
Please refer to the colorSet
to see which colors will be used for the drawing.
default: false
DrawStrokeOrderOptions.colorSet
This is the set of colors used when withColor
is enabled.
The index of the color set (array) corresponds to the stroke order, and if the stroke order exceeds the length of the color set, it will cycle through.
WARNING
Please note that the colors (strings) registered as colorSet
must be six-digit hexadecimal numbers starting with #
.
(Shortened three-digit notation, specific color names, and rgb notation cannot be used.)
default:
// prettier-ignore
/** based on https://kanjivg.tagaini.net/viewer.html */
[
"#bf0000", "#bf5600", "#bfac00", "#7cbf00", "#26bf00",
"#00bf2f", "#00bf85", "#00a2bf", "#004cbf", "#0900bf",
"#5f00bf", "#b500bf", "#bf0072", "#bf001c", "#bf2626",
"#bf6b26", "#bfaf26", "#89bf26", "#44bf26", "#26bf4c",
"#26bf91", "#26a8bf", "#2663bf", "#2d26bf", "#7226bf",
"#b726bf", "#bf2682", "#bf263d", "#bf4c4c", "#bf804c",
]
// prettier-ignore
/** based on https://kanjivg.tagaini.net/viewer.html */
[
"#bf0000", "#bf5600", "#bfac00", "#7cbf00", "#26bf00",
"#00bf2f", "#00bf85", "#00a2bf", "#004cbf", "#0900bf",
"#5f00bf", "#b500bf", "#bf0072", "#bf001c", "#bf2626",
"#bf6b26", "#bfaf26", "#89bf26", "#44bf26", "#26bf4c",
"#26bf91", "#26a8bf", "#2663bf", "#2d26bf", "#7226bf",
"#b726bf", "#bf2682", "#bf263d", "#bf4c4c", "#bf804c",
]
DrawStrokeOrderOptions.font
This is the font used when drawing the stroke order.
default:
{
family: "helvetica", // inspired by https://kanjivg.tagaini.net
size: "16px",
}
{
family: "helvetica", // inspired by https://kanjivg.tagaini.net
size: "16px",
}
@tecack/backend
recognize()
Recognizes strokes data and returns candidates.
Type
tsfunction recognize( input: Readonly<Array<TecackStroke>>, dataset: Readonly<Array<TecackDataset>> ): string[];
function recognize( input: Readonly<Array<TecackStroke>>, dataset: Readonly<Array<TecackDataset>> ): string[];
Example
tsimport { recognize } from "@tecack/backend"; import { KANJI_DATASET } from "@tecack/dataset"; const candidates = recognize(strokes, [...KANJI_DATASET, ...myDataset]);
import { recognize } from "@tecack/backend"; import { KANJI_DATASET } from "@tecack/dataset"; const candidates = recognize(strokes, [...KANJI_DATASET, ...myDataset]);
@tecack/shared
encodeStroke() / decodeStroke()
Encodes Array<TecackStroke>
data to minimize size.
And, decodes encoded string.
Type
tsfunction encodeStroke(strokes: Readonly<Array<TecackStroke>>): string; function decodeStroke(encoded: string): Array<TecackStroke> | DecodeError;
function encodeStroke(strokes: Readonly<Array<TecackStroke>>): string; function decodeStroke(encoded: string): Array<TecackStroke> | DecodeError;
Example
ts// on client import { encodeStroke } from "@tecack/shared"; const recBtn = document.getElementById("recognize-btn"); recBtn.addEventListener("click", async () => { const strokes = tecack.getStrokes(); const encoded = encodeStroke(strokes); // here const res = await fetch("http://my-api.dev/recognize", { method: "POST", body: JSON.stringify({ strokes: encoded }), }); });
// on client import { encodeStroke } from "@tecack/shared"; const recBtn = document.getElementById("recognize-btn"); recBtn.addEventListener("click", async () => { const strokes = tecack.getStrokes(); const encoded = encodeStroke(strokes); // here const res = await fetch("http://my-api.dev/recognize", { method: "POST", body: JSON.stringify({ strokes: encoded }), }); });
ts// on server import { decodeStroke } from "@tecack/shared"; import { recognize } from "@tecack/backend"; import { KANJI_DATASET } from "@tecack/dataset"; // ex1: recognize app.post("/recognize", async c => { const req = await c.req.json(); const decoded = decodeStroke(req.strokes); // here if (decoded instanceof DecodeError) { return c.json({ error: decoded.message }); } const candidate = recognize(decoded, KANJI_DATA_SET); return c.json(candidate); }); // ex2: save to database as encoded text data app.post("/save-stroke", async c => { const req = await c.req.json(); await myDb.save(req.strokes); // save to database as encoded text data return c.json({ ok: true }); });
// on server import { decodeStroke } from "@tecack/shared"; import { recognize } from "@tecack/backend"; import { KANJI_DATASET } from "@tecack/dataset"; // ex1: recognize app.post("/recognize", async c => { const req = await c.req.json(); const decoded = decodeStroke(req.strokes); // here if (decoded instanceof DecodeError) { return c.json({ error: decoded.message }); } const candidate = recognize(decoded, KANJI_DATA_SET); return c.json(candidate); }); // ex2: save to database as encoded text data app.post("/save-stroke", async c => { const req = await c.req.json(); await myDb.save(req.strokes); // save to database as encoded text data return c.json({ ok: true }); });