mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-07 09:08:13 +08:00
Bezier-rs: Refactor interactive demo to remove Vue (#959)
* Converted bezier example to vanilla js component * Indent with tabs * Add sliders * Converted bezier example pane to vanilla js * Implement the radio buttons + fixes * Converted SubpathExample to vanilla js * Converted SubpathExamplePane to vanilla js * Removed vue components * Remove App.vue * Remove vue and other dependencies * Minor fix in main.ts * Added insert to subpath features * Entry point tweaks * Rename "example" to "demo" * Kebab-case file names (except classes) Co-authored-by: Hannah Li <hannahli2010@gmail.com> Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
co-authored by
Hannah Li
Keavon Chambers
parent
05a2cd32a5
commit
2f7c45771e
@@ -0,0 +1,23 @@
|
||||
export const tSliderOptions = {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
default: 0.5,
|
||||
variable: "t",
|
||||
};
|
||||
|
||||
export const tErrorOptions = {
|
||||
variable: "error",
|
||||
min: 0.1,
|
||||
max: 2,
|
||||
step: 0.1,
|
||||
default: 0.5,
|
||||
};
|
||||
|
||||
export const tMinimumSeperationOptions = {
|
||||
variable: "minimum_seperation",
|
||||
min: 0.001,
|
||||
max: 0.25,
|
||||
step: 0.001,
|
||||
default: 0.05,
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
import { ComputeType, Demo, DemoPane, SliderOption } from "@/utils/types";
|
||||
|
||||
export function renderDemo(demo: Demo): void {
|
||||
const header = document.createElement("h4");
|
||||
header.className = "demo-header";
|
||||
header.innerText = demo.title;
|
||||
|
||||
const figure = document.createElement("figure");
|
||||
figure.className = "demo-figure";
|
||||
figure.addEventListener("mousedown", demo.onMouseDown.bind(demo));
|
||||
figure.addEventListener("mouseup", demo.onMouseUp.bind(demo));
|
||||
figure.addEventListener("mousemove", demo.onMouseMove.bind(demo));
|
||||
|
||||
demo.append(header);
|
||||
demo.append(figure);
|
||||
|
||||
demo.sliderOptions.forEach((sliderOption: SliderOption) => {
|
||||
const sliderLabel = document.createElement("div");
|
||||
const sliderData = demo.sliderData[sliderOption.variable];
|
||||
const sliderUnit = demo.getSliderUnit(sliderData, sliderOption.variable);
|
||||
sliderLabel.className = "slider-label";
|
||||
sliderLabel.innerText = `${sliderOption.variable} = ${sliderData}${sliderUnit}`;
|
||||
demo.append(sliderLabel);
|
||||
|
||||
const sliderInput = document.createElement("input");
|
||||
sliderInput.className = "slider-input";
|
||||
sliderInput.type = "range";
|
||||
sliderInput.max = String(sliderOption.max);
|
||||
sliderInput.min = String(sliderOption.min);
|
||||
sliderInput.step = String(sliderOption.step);
|
||||
sliderInput.value = String(sliderOption.default);
|
||||
sliderInput.addEventListener("input", (event: Event): void => {
|
||||
demo.sliderData[sliderOption.variable] = Number((event.target as HTMLInputElement).value);
|
||||
sliderLabel.innerText = `${sliderOption.variable} = ${demo.sliderData[sliderOption.variable]}${sliderUnit}`;
|
||||
demo.drawDemo(figure);
|
||||
});
|
||||
demo.append(sliderInput);
|
||||
});
|
||||
}
|
||||
|
||||
export function renderDemoPane(demoPane: DemoPane): void {
|
||||
const container = document.createElement("div");
|
||||
container.className = "demo-pane-container";
|
||||
|
||||
const header = document.createElement("h3");
|
||||
header.innerText = demoPane.name;
|
||||
header.className = "demo-pane-header";
|
||||
|
||||
const computeTypeContainer = document.createElement("div");
|
||||
computeTypeContainer.className = "compute-type-choice";
|
||||
|
||||
const computeTypeLabel = document.createElement("strong");
|
||||
computeTypeLabel.innerText = "ComputeType:";
|
||||
computeTypeContainer.append(computeTypeLabel);
|
||||
|
||||
const radioInputs = ["Parametric", "Euclidean"].map((computeType) => {
|
||||
const id = `${demoPane.id}-${computeType}`;
|
||||
const radioInput = document.createElement("input");
|
||||
radioInput.type = "radio";
|
||||
radioInput.id = id;
|
||||
radioInput.value = computeType;
|
||||
radioInput.name = "ComputeType";
|
||||
radioInput.checked = computeType === "Parametric";
|
||||
computeTypeContainer.append(radioInput);
|
||||
|
||||
const label = document.createElement("label");
|
||||
label.htmlFor = id;
|
||||
label.innerText = computeType;
|
||||
computeTypeContainer.append(label);
|
||||
return radioInput;
|
||||
});
|
||||
|
||||
const demoRow = document.createElement("div");
|
||||
demoRow.className = "demo-row";
|
||||
|
||||
demoPane.demos.forEach((demo) => {
|
||||
if (demo.disabled) {
|
||||
return;
|
||||
}
|
||||
const demoComponent = demoPane.buildDemo(demo);
|
||||
|
||||
radioInputs.forEach((radioInput: HTMLElement) => {
|
||||
radioInput.addEventListener("input", (event: Event): void => {
|
||||
demoPane.computeType = (event.target as HTMLInputElement).value as ComputeType;
|
||||
demoComponent.setAttribute("computetype", demoPane.computeType);
|
||||
});
|
||||
});
|
||||
demoRow.append(demoComponent);
|
||||
});
|
||||
|
||||
container.append(header);
|
||||
if (demoPane.chooseComputeType) {
|
||||
container.append(computeTypeContainer);
|
||||
}
|
||||
container.append(demoRow);
|
||||
|
||||
demoPane.append(container);
|
||||
}
|
||||
@@ -16,11 +16,11 @@ export type ComputeType = "Euclidean" | "Parametric";
|
||||
export type BezierCallback = (bezier: WasmBezierInstance, options: Record<string, number>, mouseLocation?: [number, number], computeType?: ComputeType) => string;
|
||||
export type SubpathCallback = (subpath: WasmSubpathInstance, options: Record<string, number>, mouseLocation?: [number, number], computeType?: ComputeType) => string;
|
||||
|
||||
export type ExampleOptions = {
|
||||
export type BezierDemoOptions = {
|
||||
[key in BezierCurveType]: {
|
||||
disabled: boolean;
|
||||
sliderOptions: SliderOption[];
|
||||
customPoints: number[][];
|
||||
disabled?: boolean;
|
||||
sliderOptions?: SliderOption[];
|
||||
customPoints?: number[][];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -53,3 +53,39 @@ export function getConstructorKey(bezierCurveType: BezierCurveType): WasmBezierC
|
||||
};
|
||||
return mapping[bezierCurveType];
|
||||
}
|
||||
|
||||
export interface DemoArgs {
|
||||
title: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export interface BezierDemoArgs extends DemoArgs {
|
||||
points: number[][];
|
||||
sliderOptions: SliderOption[];
|
||||
}
|
||||
|
||||
export interface SubpathDemoArgs extends DemoArgs {
|
||||
triples: (number[] | undefined)[][];
|
||||
closed: boolean;
|
||||
}
|
||||
|
||||
export interface Demo extends HTMLElement {
|
||||
sliderOptions: SliderOption[];
|
||||
sliderData: Record<string, number>;
|
||||
sliderUnits: Record<string, string | string[]>;
|
||||
|
||||
drawDemo(figure: HTMLElement, mouseLocation?: [number, number]): void;
|
||||
onMouseDown(event: MouseEvent): void;
|
||||
onMouseUp(): void;
|
||||
onMouseMove(event: MouseEvent): void;
|
||||
getSliderUnit(sliderValue: number, variable: string): string;
|
||||
}
|
||||
|
||||
export interface DemoPane extends HTMLElement {
|
||||
name: string;
|
||||
demos: DemoArgs[];
|
||||
id: string;
|
||||
chooseComputeType: boolean;
|
||||
computeType: ComputeType;
|
||||
buildDemo(demo: DemoArgs): Demo;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user