Refactor
This commit is contained in:
@@ -64,7 +64,7 @@ export class Main extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.destroyed = true;
|
this.destroyed = true;
|
||||||
this.actualSave({collapsed: this.state.collapsed, opacity: this.state .opacity});
|
this.actualSave({collapsed: this.state.collapsed, opacity: this.state.opacity});
|
||||||
}
|
}
|
||||||
actualSave(settings: StoreSettings) {
|
actualSave(settings: StoreSettings) {
|
||||||
return this.props.storage.setItem(this.STORAGE_KEY, settings);
|
return this.props.storage.setItem(this.STORAGE_KEY, settings);
|
||||||
@@ -122,9 +122,28 @@ export class Main extends React.Component<Props, State> {
|
|||||||
/>
|
/>
|
||||||
</MovableWindow>
|
</MovableWindow>
|
||||||
{this.renderMap()}
|
{this.renderMap()}
|
||||||
{this.state.overlays.map((o, i) => <Overlay key={i} storage={this.props.storage} opacity={this.state.opacity} cords={this.props.cords} palette={this.props.palette} mural={this.props.store.murals[o]}/> )}
|
{this.state.overlays.map((o, i) => <Overlay
|
||||||
{this.props.store.murals[this.state.phantomOverlay] ? <Overlay storage={this.props.storage} opacity={50} cords={this.props.cords} palette={this.props.palette} mural={this.props.store.murals[this.state.phantomOverlay]}/> : null }
|
key={i} storage={this.props.storage}
|
||||||
{this.state.overlayModify ? <Overlay muralObj={this.state.overlayModify.muralObj} opacity={this.state.opacity} storage={this.props.storage} cords={this.props.cords} palette={this.props.palette} mural={this.props.store.overlayModify!.pixels} onChange={(name, x, y, confirm) => {
|
opacity={this.state.opacity}
|
||||||
|
cords={this.props.cords}
|
||||||
|
palette={this.props.palette}
|
||||||
|
mural={this.props.store.murals[o]}
|
||||||
|
/> )}
|
||||||
|
{this.props.store.murals[this.state.phantomOverlay] ? <Overlay
|
||||||
|
storage={this.props.storage}
|
||||||
|
opacity={50}
|
||||||
|
cords={this.props.cords}
|
||||||
|
palette={this.props.palette}
|
||||||
|
mural={this.props.store.murals[this.state.phantomOverlay]}
|
||||||
|
/> : null }
|
||||||
|
{this.state.overlayModify ? <Overlay
|
||||||
|
muralObj={this.state.overlayModify.muralObj}
|
||||||
|
opacity={this.state.opacity}
|
||||||
|
storage={this.props.storage}
|
||||||
|
cords={this.props.cords}
|
||||||
|
palette={this.props.palette}
|
||||||
|
mural={this.props.store.overlayModify!.pixels}
|
||||||
|
onChange={(name, x, y, confirm) => {
|
||||||
this.state.overlayModify!.cb(name, x, y, confirm);
|
this.state.overlayModify!.cb(name, x, y, confirm);
|
||||||
}} /> : null}
|
}} /> : null}
|
||||||
</>;
|
</>;
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import { Coordinates, CordType } from "../../lib/coordinates";
|
|||||||
import { SelectedMural } from "../../interfaces";
|
import { SelectedMural } from "../../interfaces";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Btn, SELECTED_COLOR } from "../styles";
|
import { Btn, SELECTED_COLOR } from "../styles";
|
||||||
import { faCrosshairs, faMagnifyingGlassMinus, faMagnifyingGlassPlus } from "@fortawesome/free-solid-svg-icons";
|
import {
|
||||||
|
faCrosshairs, faMagnifyingGlassMinus, faMagnifyingGlassPlus
|
||||||
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { createCanvas, drawPixelsOntoCanvas } from "../../lib/utils";
|
import { createCanvas, drawPixelsOntoCanvas } from "../../lib/utils";
|
||||||
@@ -123,7 +125,10 @@ export class Minimap extends React.Component<Props, Stats> {
|
|||||||
|
|
||||||
onCords = (x: number, y: number) => {
|
onCords = (x: number, y: number) => {
|
||||||
const store = this.props.store;
|
const store = this.props.store;
|
||||||
if (store.selected && store.selected.m.x < x && store.selected.m.y < y && store.selected.w + store.selected.m.x > x && store.selected.h + store.selected.m.y > y) {
|
if (
|
||||||
|
store.selected && store.selected.m.x < x && store.selected.m.y < y &&
|
||||||
|
store.selected.w + store.selected.m.x > x &&
|
||||||
|
store.selected.h + store.selected.m.y > y) {
|
||||||
const xx = x - store.selected.m.x;
|
const xx = x - store.selected.m.x;
|
||||||
const yy = y - store.selected.m.y;
|
const yy = y - store.selected.m.y;
|
||||||
const colorIndex = store.selected.m.pixels[yy][xx];
|
const colorIndex = store.selected.m.pixels[yy][xx];
|
||||||
@@ -246,11 +251,16 @@ export class Minimap extends React.Component<Props, Stats> {
|
|||||||
render() {
|
render() {
|
||||||
return <div>
|
return <div>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Btn onClick={this.up}><FontAwesomeIcon icon={ faMagnifyingGlassPlus }></FontAwesomeIcon></Btn>
|
<Btn
|
||||||
|
onClick={this.up}><FontAwesomeIcon icon={ faMagnifyingGlassPlus } /></Btn>
|
||||||
<Scale>{this.state.size}</Scale>
|
<Scale>{this.state.size}</Scale>
|
||||||
<Btn onClick={this.down}><FontAwesomeIcon icon={ faMagnifyingGlassMinus }></FontAwesomeIcon></Btn>
|
<Btn onClick={this.down}><FontAwesomeIcon icon={ faMagnifyingGlassMinus } /></Btn>
|
||||||
<span style={{flex: 1}}>
|
<span style={{flex: 1}}>
|
||||||
<Btn title="Color assistant" style={{ borderColor: this.state.colorAssistant ? SELECTED_COLOR : ""} } onClick={() => this.toggleColorAssistant()}>Assist<FontAwesomeIcon icon={faCrosshairs} /> </Btn>
|
<Btn
|
||||||
|
title="Color assistant"
|
||||||
|
style={{ borderColor: this.state.colorAssistant ? SELECTED_COLOR : ""} }
|
||||||
|
onClick={() => this.toggleColorAssistant()}>Assist<FontAwesomeIcon
|
||||||
|
icon={faCrosshairs} /> </Btn>
|
||||||
</span>
|
</span>
|
||||||
{this.renderColor()}
|
{this.renderColor()}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -155,7 +155,9 @@ export class MovableWindow extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
||||||
this.setMoving(event.clientX,event.clientY, event.nativeEvent.offsetX, event.nativeEvent.offsetY);
|
this.setMoving(
|
||||||
|
event.clientX,event.clientY, event.nativeEvent.offsetX, event.nativeEvent.offsetY
|
||||||
|
);
|
||||||
this.setState({moving: true});
|
this.setState({moving: true});
|
||||||
};
|
};
|
||||||
onTouchStart = (event: React.TouchEvent<HTMLDivElement>) => {
|
onTouchStart = (event: React.TouchEvent<HTMLDivElement>) => {
|
||||||
@@ -173,7 +175,10 @@ export class MovableWindow extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
return <Movable ref={this.ref} style={{left: `${this.state.x}px`, top: `${this.state.y}px`}}>
|
return <Movable ref={this.ref} style={{left: `${this.state.x}px`, top: `${this.state.y}px`}}>
|
||||||
<DragArea ref={this.dragRef} style={{cursor: this.state.moving ? "grabbing" : ""}} onMouseDown={this.onMouseDown} onTouchStart={this.onTouchStart} > <h2>{this.props.title}</h2> </DragArea>
|
<DragArea ref={this.dragRef}
|
||||||
|
style={{cursor: this.state.moving ? "grabbing" : ""}}
|
||||||
|
onMouseDown={this.onMouseDown}
|
||||||
|
onTouchStart={this.onTouchStart}> <h2>{this.props.title}</h2> </DragArea>
|
||||||
|
|
||||||
|
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
|
|||||||
@@ -18,16 +18,24 @@ export class MuralEditor extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
return <Border>
|
return <Border>
|
||||||
<div>
|
<div>
|
||||||
<span>Name</span> <Input type="text" value={this.props.name} onChange={e => this.props.onName(e.target.value)} />
|
<span>Name</span> <Input
|
||||||
|
type="text"
|
||||||
|
value={this.props.name} onChange={e => this.props.onName(e.target.value)} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>X</span> <Input type="number" value={this.props.x} onChange={e => processNumberEvent(e, this.props.onX)}/>
|
<span>X</span> <Input
|
||||||
|
type="number"
|
||||||
|
value={this.props.x} onChange={e => processNumberEvent(e, this.props.onX)}/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>Y</span> <Input type="number" value={this.props.y} onChange={e => processNumberEvent(e, this.props.onY)} />
|
<span>Y</span> <Input
|
||||||
|
type="number"
|
||||||
|
value={this.props.y} onChange={e => processNumberEvent(e, this.props.onY)} />
|
||||||
</div>
|
</div>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Btn onClick={() => this.props.onConfirm()} style={{flex: 1}}>Confirm</Btn><Btn onClick={() => this.props.onCancel()} style={{flex: 1}}>Cancel</Btn>
|
<Btn onClick={() => this.props.onConfirm()}
|
||||||
|
style={{flex: 1}}>Confirm</Btn><Btn
|
||||||
|
onClick={() => this.props.onCancel()} style={{flex: 1}}>Cancel</Btn>
|
||||||
</Flex>
|
</Flex>
|
||||||
<small>Overlay does not work on scale -1. To fix that zoom in.</small>
|
<small>Overlay does not work on scale -1. To fix that zoom in.</small>
|
||||||
</Border>;
|
</Border>;
|
||||||
|
|||||||
@@ -63,7 +63,9 @@ export class MuralList extends React.Component<Props, State> {
|
|||||||
};
|
};
|
||||||
render() {
|
render() {
|
||||||
return <ScrollContainer> {this.state.murals.map((m,i) => {
|
return <ScrollContainer> {this.state.murals.map((m,i) => {
|
||||||
return <MuralView key={i} mural={m} cords={this.props.cords} palette={this.props.palette} store={this.props.store} selected={m === this.state.selected?.m} />;
|
return <MuralView key={i} mural={m} cords={this.props.cords}
|
||||||
|
palette={this.props.palette} store={this.props.store}
|
||||||
|
selected={m === this.state.selected?.m} />;
|
||||||
})}</ScrollContainer>;
|
})}</ScrollContainer>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import styled from "styled-components";
|
|||||||
import { Border, Btn, Flex, SELECTED_COLOR } from "../styles";
|
import { Border, Btn, Flex, SELECTED_COLOR } from "../styles";
|
||||||
import { CanvasToCanvasJSX } from "./canvasToCanvasJSX";
|
import { CanvasToCanvasJSX } from "./canvasToCanvasJSX";
|
||||||
import { formatNumber, getMuralHeight, getMuralWidth, getPixelStatusMural } from "../../lib/utils";
|
import { formatNumber, getMuralHeight, getMuralWidth, getPixelStatusMural } from "../../lib/utils";
|
||||||
import { IconDefinition, faDownload, faLayerGroup, faLocation, faPenToSquare, faRefresh, faTrash } from "@fortawesome/free-solid-svg-icons";
|
import {
|
||||||
|
IconDefinition, faDownload, faLayerGroup, faLocation, faPenToSquare, faRefresh, faTrash
|
||||||
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { Coordinates } from "../../lib/coordinates";
|
import { Coordinates } from "../../lib/coordinates";
|
||||||
import { TEXT_FORMATS } from "../importMural";
|
import { TEXT_FORMATS } from "../importMural";
|
||||||
@@ -129,7 +131,8 @@ export class MuralView extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
btn(context: string, icon: IconDefinition, onClick: () => void, selected?: boolean) {
|
btn(context: string, icon: IconDefinition, onClick: () => void, selected?: boolean) {
|
||||||
return <Btn style={{ borderColor: selected ? SELECTED_COLOR : "" }} onClick={() => onClick()}>{context} <FontAwesomeIcon icon={icon} /> </Btn>;
|
return <Btn style={{ borderColor: selected ? SELECTED_COLOR : "" }}
|
||||||
|
onClick={() => onClick()}>{context} <FontAwesomeIcon icon={icon} /> </Btn>;
|
||||||
}
|
}
|
||||||
get s() {
|
get s() {
|
||||||
return this.props.store;
|
return this.props.store;
|
||||||
@@ -263,7 +266,11 @@ export class MuralView extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <Border onClick={this.onLoad} style={{ border: this.props.selected ? "3px solid black" : "3px dotted black", cursor: "pointer" }} onMouseEnter={this.onEnter} onMouseLeave={this.onLeave}>
|
return <Border onClick={this.onLoad}
|
||||||
|
style={{
|
||||||
|
border: this.props.selected ? "3px solid black" : "3px dotted black",
|
||||||
|
cursor: "pointer" }}
|
||||||
|
onMouseEnter={this.onEnter} onMouseLeave={this.onLeave}>
|
||||||
<Flex>
|
<Flex>
|
||||||
<CanvasToCanvasJSX canvas={this.props.mural.ref} height={this.state.height} width={this.state.width}/>
|
<CanvasToCanvasJSX canvas={this.props.mural.ref} height={this.state.height} width={this.state.width}/>
|
||||||
<Margin style={{flex: "1"}}>
|
<Margin style={{flex: "1"}}>
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ export class Overlay extends React.Component<Props, State> {
|
|||||||
renderModifyWindow() {
|
renderModifyWindow() {
|
||||||
if (this.props.onChange) {
|
if (this.props.onChange) {
|
||||||
const copy = {...this.state};
|
const copy = {...this.state};
|
||||||
return <MovableWindow storage={this.props.storage} storageKey="overlay-set" title="Position editor">
|
return <MovableWindow storage={this.props.storage}
|
||||||
|
storageKey="overlay-set" title="Position editor">
|
||||||
<MuralEditor
|
<MuralEditor
|
||||||
name={this.state.name}
|
name={this.state.name}
|
||||||
x={this.state.x}
|
x={this.state.x}
|
||||||
|
|||||||
+14
-5
@@ -161,7 +161,9 @@ async function imageToMural(image: HTMLImageElement, palette: Palette) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
export async function getImageSettingFromUser(image: HTMLImageElement): Promise<ImageToMuralOptions> {
|
export async function getImageSettingFromUser(
|
||||||
|
image: HTMLImageElement
|
||||||
|
): Promise<ImageToMuralOptions> {
|
||||||
let width = image.width;
|
let width = image.width;
|
||||||
let height = image.height;
|
let height = image.height;
|
||||||
let useQuantizer: DitherSetting = "show-all";
|
let useQuantizer: DitherSetting = "show-all";
|
||||||
@@ -307,7 +309,9 @@ export async function getImageSettingFromUser(image: HTMLImageElement): Promise<
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function imageToQuantized(image: HTMLImageElement, options: ImageToMuralOptions, palette: Palette) {
|
export async function imageToQuantized(
|
||||||
|
image: HTMLImageElement, options: ImageToMuralOptions, palette: Palette
|
||||||
|
) {
|
||||||
if (!options.noShrinking) {
|
if (!options.noShrinking) {
|
||||||
image = await resize(image, options.width, options.height);
|
image = await resize(image, options.width, options.height);
|
||||||
}
|
}
|
||||||
@@ -347,7 +351,9 @@ export function quantizeAll(canvas: HTMLCanvasElement, palette: Palette) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function quantizeOne(canvas: HTMLCanvasElement, kernel: DitheringKernelEx, palette: Palette): QuantResult {
|
export function quantizeOne(
|
||||||
|
canvas: HTMLCanvasElement, kernel: DitheringKernelEx, palette: Palette
|
||||||
|
): QuantResult {
|
||||||
if (kernel === "Flat") {
|
if (kernel === "Flat") {
|
||||||
const imageData = canvasToImageData(canvas);
|
const imageData = canvasToImageData(canvas);
|
||||||
flatQuantizeImageData(imageData, palette);
|
flatQuantizeImageData(imageData, palette);
|
||||||
@@ -389,7 +395,9 @@ export function ditheringKernelToName(kernel: string) {
|
|||||||
return stringBuilder;
|
return stringBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
function quantizeImage(canvas: HTMLCanvasElement, rgbQuant: RgbQuant, ditheringKernel: DitheringKernel) {
|
function quantizeImage(
|
||||||
|
canvas: HTMLCanvasElement, rgbQuant: RgbQuant, ditheringKernel: DitheringKernel
|
||||||
|
) {
|
||||||
// create canvas;
|
// create canvas;
|
||||||
const drawCanvas = document.createElement("canvas");
|
const drawCanvas = document.createElement("canvas");
|
||||||
drawCanvas.width = canvas.width;
|
drawCanvas.width = canvas.width;
|
||||||
@@ -469,7 +477,8 @@ async function importFile() {
|
|||||||
const content = await readAsString(fileData);
|
const content = await readAsString(fileData);
|
||||||
const mural = JSON.parse(content) as Mural;
|
const mural = JSON.parse(content) as Mural;
|
||||||
if (!mural.name) {
|
if (!mural.name) {
|
||||||
mural.name = await Popup.prompt("Missing name for this mural. Please enter it manually", name) || "";
|
mural.name = await Popup
|
||||||
|
.prompt("Missing name for this mural. Please enter it manually", name) || "";
|
||||||
}
|
}
|
||||||
validateMural(mural);
|
validateMural(mural);
|
||||||
return {
|
return {
|
||||||
|
|||||||
+3
-1
@@ -8,7 +8,9 @@ import { createRoot } from "react-dom/client";
|
|||||||
import { PixelPlaced } from "../lib/pixelPlaced";
|
import { PixelPlaced } from "../lib/pixelPlaced";
|
||||||
import { PixelCount } from "./components/pixelCount";
|
import { PixelCount } from "./components/pixelCount";
|
||||||
|
|
||||||
export function createUI(store: Store, storage: Storage, cords: Coordinates, palette: Palette, pixels: PixelPlaced) {
|
export function createUI(
|
||||||
|
store: Store, storage: Storage, cords: Coordinates, palette: Palette, pixels: PixelPlaced
|
||||||
|
) {
|
||||||
const unmounts = [
|
const unmounts = [
|
||||||
appendWindow(<PixelCount pixelCount={pixels} />),
|
appendWindow(<PixelCount pixelCount={pixels} />),
|
||||||
appendWindow(<Main cords={cords} store={store} storage={storage} palette={palette}/>),
|
appendWindow(<Main cords={cords} store={store} storage={storage} palette={palette}/>),
|
||||||
|
|||||||
+8
-2
@@ -19,8 +19,14 @@ async function main() {
|
|||||||
|
|
||||||
createUI(store,storage, coordinates, palette, pixelPlaced);
|
createUI(store,storage, coordinates, palette, pixelPlaced);
|
||||||
|
|
||||||
console.log("%cOverlay by 0xa663", "color: red; font-size: 15px; font-weight: bold; text-shadow: 2px 2px 4px #000000;");
|
console.log(
|
||||||
console.log("%cTerncode's fork", `color: #4a94cc; font-size: 10px; font-weight: bold; text-shadow: 1px 1px 0px #000000, -1px 1px 0px #000000, 1px -1px 0px #000000, -1px -1px 0px #000000;`);
|
"%cOverlay by 0xa663",
|
||||||
|
"color: red; font-size: 15px; font-weight: bold; text-shadow: 2px 2px 4px #000000;"
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"%cTerncode's fork",
|
||||||
|
`color: #4a94cc; font-size: 10px; font-weight: bold; text-shadow: 1px 1px 0px #000000, -1px 1px 0px #000000, 1px -1px 0px #000000, -1px -1px 0px #000000;`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.readyState === "complete") {
|
if (document.readyState === "complete") {
|
||||||
|
|||||||
+3
-1
@@ -119,7 +119,9 @@ export class Store implements LoadUnload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
await this.storage.setItem(this.STORAGE_KEY_MURAL, this._murals.map(m => ({ name: m.name, pixels: m.pixels, x: m.x, y: m.y } as Mural)));
|
await this.storage
|
||||||
|
.setItem(this.STORAGE_KEY_MURAL, this._murals
|
||||||
|
.map(m => ({ name: m.name, pixels: m.pixels, x: m.x, y: m.y } as Mural)));
|
||||||
const selected = this._selected?.m ? this._murals.indexOf(this._selected?.m!) : -1;
|
const selected = this._selected?.m ? this._murals.indexOf(this._selected?.m!) : -1;
|
||||||
await this.storage.setItem(this.STORAGE_KEY_SELECTED, selected);
|
await this.storage.setItem(this.STORAGE_KEY_SELECTED, selected);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-4
@@ -179,8 +179,10 @@ export function validateMural(mural: Mural) {
|
|||||||
throw new Error(`mural.pixels[${y}] is null`);
|
throw new Error(`mural.pixels[${y}] is null`);
|
||||||
}
|
}
|
||||||
for (let x = 0; x < yArray.length; x++) {
|
for (let x = 0; x < yArray.length; x++) {
|
||||||
if (typeof yArray[x] !== "number") throw new Error(`pixels[${y}][${x}] is not a number`);
|
if (typeof yArray[x] !== "number")
|
||||||
if (!isInteger(yArray[x])) throw new Error(`pixels[${y}][${x}] is not am integer`);
|
throw new Error(`pixels[${y}][${x}] is not a number`);
|
||||||
|
if (!isInteger(yArray[x]))
|
||||||
|
throw new Error(`pixels[${y}][${x}] is not am integer`);
|
||||||
const colorId = yArray[x];
|
const colorId = yArray[x];
|
||||||
if (colorId == null) throw new Error("colorId is null");
|
if (colorId == null) throw new Error("colorId is null");
|
||||||
}
|
}
|
||||||
@@ -300,7 +302,9 @@ export function imageToCanvas(image: HTMLImageElement) {
|
|||||||
return canvas;
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function drawPixelsOntoCanvas(canvas: HTMLCanvasElement, pixelsData: number[][], palette: string[], pixelSize = 1) {
|
export function drawPixelsOntoCanvas(
|
||||||
|
canvas: HTMLCanvasElement, pixelsData: number[][], palette: string[], pixelSize = 1
|
||||||
|
) {
|
||||||
const ctx = canvas.getContext("2d")!;
|
const ctx = canvas.getContext("2d")!;
|
||||||
if (!ctx) return 0;
|
if (!ctx) return 0;
|
||||||
const data = pixelsData;
|
const data = pixelsData;
|
||||||
@@ -374,7 +378,9 @@ export function formatNumber(number: number) {
|
|||||||
return numberFormatter ? numberFormatter.format(number) : number.toString();
|
return numberFormatter ? numberFormatter.format(number) : number.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function processNumberEvent(ev: React.ChangeEvent<HTMLInputElement>, cb: (n: number) => void) {
|
export function processNumberEvent(
|
||||||
|
ev: React.ChangeEvent<HTMLInputElement>, cb: (n: number) => void
|
||||||
|
) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
if(ev.target.value === "") {
|
if(ev.target.value === "") {
|
||||||
|
|||||||
Reference in New Issue
Block a user