Optimize overlay

This commit is contained in:
2025-02-13 17:15:37 +01:00
parent 5587dd7909
commit 75994c110d
4 changed files with 75 additions and 35 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ export class Main extends React.Component<Props, State> {
muralExtended={this.props.store.murals[this.state.phantomOverlay]} muralExtended={this.props.store.murals[this.state.phantomOverlay]}
/> : null } /> : null }
{this.state.overlayModify ? <Overlay {this.state.overlayModify ? <Overlay
muralObj={this.state.overlayModify.muralObj} muralModifier={this.state.overlayModify.muralModify}
opacity={this.state.opacity} opacity={this.state.opacity}
storage={this.props.storage} storage={this.props.storage}
cords={this.props.cords} cords={this.props.cords}
+63 -27
View File
@@ -6,7 +6,6 @@ import { Palette } from "../../lib/palette";
import { MovableWindow } from "./movableWindow"; import { MovableWindow } from "./movableWindow";
import { Storage } from "../../lib/storage"; import { Storage } from "../../lib/storage";
import { MuralEditor } from "./muralEditor"; import { MuralEditor } from "./muralEditor";
import { Mural } from "../../lib/mural";
const Canvas = styled.canvas` const Canvas = styled.canvas`
position: fixed; position: fixed;
@@ -15,9 +14,9 @@ const Canvas = styled.canvas`
`; `;
interface Props { interface Props {
muralExtended: MuralEx; muralExtended: Readonly<MuralEx>;
muralObj?: Partial<Mural>; muralModifier?: { x: number, y: number, name: string };
onChange?: (name: string, x: number, y:number, confirm?: boolean) => void; onChange?: (name: string, x: number, y: number, confirm?: boolean) => void;
cords: Coordinates; cords: Coordinates;
storage: Storage; storage: Storage;
palette: Palette; palette: Palette;
@@ -32,7 +31,6 @@ interface State {
export class Overlay extends React.Component<Props, State> { export class Overlay extends React.Component<Props, State> {
private ref = React.createRef<HTMLCanvasElement>(); private ref = React.createRef<HTMLCanvasElement>();
private _refImage?: HTMLCanvasElement;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
@@ -44,21 +42,52 @@ export class Overlay extends React.Component<Props, State> {
} }
componentDidMount() { componentDidMount() {
this.draw(); this.resize();
this.ref.current!.style.top = this.ref.current!.style.left = `0px`;
this.props.cords.on(CordType.Url, this.draw); this.props.cords.on(CordType.Url, this.draw);
window.addEventListener("mousemove", this.draw); console.log("test");
if (this.props.muralObj) { window.addEventListener("mousemove", this.onMouseMove);
window.addEventListener("touchmove", this.onTouchMove);
window.addEventListener("resize", this.resize);
if (this.props.muralModifier) {
this.setState({ this.setState({
name: this.props.muralObj.name || "", name: this.props.muralModifier.name || "",
x: this.props.muralObj.x ?? 0, x: this.props.muralModifier.x ?? 0,
y: this.props.muralObj.y ?? 0, y: this.props.muralModifier.y ?? 0,
}); });
} }
} }
componentWillUnmount() { componentWillUnmount() {
this.props.cords.off(CordType.Url, this.draw); this.props.cords.off(CordType.Url, this.draw);
window.removeEventListener("mousemove", this.draw);
window.removeEventListener("mousemove", this.onMouseMove);
window.removeEventListener("touchmove", this.onTouchMove);
window.removeEventListener("resize", this.resize);
} }
onMouseMove = (event: MouseEvent) => {
if (event.buttons === 1) {
this.draw();
}
};
onTouchMove = (event: TouchEvent) => {
if (event.touches.length) {
this.draw();
}
};
resize = () => {
const canvas = this.ref.current!;
if (canvas.height !== window.outerHeight || canvas.width !== window.outerWidth) {
canvas.width = window.outerWidth;
canvas.height = window.outerHeight;
canvas.style.width = `${window.outerWidth}px`;
canvas.style.height = `${window.outerHeight}px`;
this.draw();
}
};
componentDidUpdate(prevProps: Readonly<Props>, prevState: Readonly<State>) { componentDidUpdate(prevProps: Readonly<Props>, prevState: Readonly<State>) {
if (prevProps.muralExtended !== this.props.muralExtended) { if (prevProps.muralExtended !== this.props.muralExtended) {
@@ -78,11 +107,11 @@ export class Overlay extends React.Component<Props, State> {
} }
get x() { get x() {
return this.props.muralExtended.mural.x; return this.props.muralModifier ? this.state.x : this.props.muralExtended.mural.x;
} }
get y() { get y() {
return this.props.muralExtended.mural.y; return this.props.muralModifier ? this.state.y : this.props.muralExtended.mural.y;
} }
get refImg() { get refImg() {
@@ -92,33 +121,40 @@ export class Overlay extends React.Component<Props, State> {
draw = () => { draw = () => {
const canvas = this.ref.current!; const canvas = this.ref.current!;
const scale = Math.pow(2, this.props.cords.uScale); const scale = Math.pow(2, this.props.cords.uScale);
// TODO calculate cords differently to be less expensive
// TODO also add cache
// TODO also profile the thing
const cords = this.props.cords.gridToScreen(this.x, this.y)!; const cords = this.props.cords.gridToScreen(this.x, this.y)!;
if (!cords) { if (!cords) {
const ctx = canvas.getContext("2d")!; const ctx = canvas.getContext("2d")!;
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
return; return;
} }
const { x, y } = cords; const x = cords.x;
const y = cords.y;
const width = this.props.muralExtended.mural.w * scale; const width = this.props.muralExtended.mural.w * scale;
const height = this.props.muralExtended.mural.h * scale; const height = this.props.muralExtended.mural.h * scale;
if (width !== canvas.width || height !== canvas.height ) {
canvas.width = width;
canvas.height = height;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
}
const ctx = canvas.getContext("2d")!;
ctx.imageSmoothingEnabled = false;
canvas.style.left = `${x}px`;
canvas.style.top = `${y}px`;
ctx.drawImage(this.refImg, 0, 0, canvas.width, canvas.height); const ctx = canvas.getContext("2d")!;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.imageSmoothingEnabled = false;
ctx.drawImage(this.refImg, x, y, width, height);
// if (true) {
// ctx.strokeStyle = "#000000";
// ctx.strokeText(`${x}px ${y}px`, 11, 11);
// ctx.strokeText(`${x}px ${y}px`, 9, 9);
// ctx.strokeText(`${x}px ${y}px`, 9, 11);
// ctx.strokeText(`${x}px ${y}px`, 11, 9);
// ctx.fillStyle = "#ffffff";
// ctx.fillText(`${x}px ${y}px`, 10, 10);
// }
}; };
private get style(): React.CSSProperties { private get style(): React.CSSProperties {
return { left: this.state.x, top: this.state.y, opacity: this.props.opacity / 100}; return { opacity: this.props.opacity / 100};
} }
renderModifyWindow() { renderModifyWindow() {
+9 -5
View File
@@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { ImportOutput, MuralOld, RGB } from "../interfaces"; import { ImportOutput, MuralOld, RGB } from "../interfaces";
import { canvasToImageData, convertOldMuralToNewMural, getColorScore, getExtension, import { canvasToImageData, convertOldMuralToNewMural, createMuralExtended, getColorScore, getExtension,
imageDataToPaletteIndices, imageToCanvas, loadImageSource, processNumberEvent, imageDataToPaletteIndices, imageToCanvas, loadImageSource, processNumberEvent,
readAsArrayBuffer, readAsArrayBuffer,
readAsDataUrl, readAsString, resize, rgb } from "../lib/utils"; readAsDataUrl, readAsString, resize, rgb } from "../lib/utils";
@@ -97,13 +97,17 @@ export async function importArtWorks(
} else { } else {
const img = file.data; const img = file.data;
const pixels = await imageToMural(img, palette); const pixels = await imageToMural(img, palette);
const x = Math.floor(cords.ux - (img.width / 2));
const y = Math.floor(cords.uy - (img.height / 2));
const fakeMural = new Mural(img.alt, x, y, img.width, img.height, pixels);
const muralExtended = createMuralExtended(fakeMural, palette.hex);
const mural = await new Promise<Mural>((resolve, reject)=> { const mural = await new Promise<Mural>((resolve, reject)=> {
store.setOverlayModify({ store.setOverlayModify({
mural, mural: muralExtended,
muralObj: { muralModify: {
name: img.alt, name: img.alt,
x: Math.floor(cords.ux - (img.width / 2)), x,
y: Math.floor(cords.uy - (img.height / 2)), y,
}, },
cb: (name, x, y, confirm) => { cb: (name, x, y, confirm) => {
if (confirm) { if (confirm) {
+1 -1
View File
@@ -22,7 +22,7 @@ export enum StoreEvents {
export interface OverlayReturn { export interface OverlayReturn {
mural: MuralEx; mural: MuralEx;
muralObj?: Partial<Mural>; muralModify?: { name: string, x: number, y: number };
cb: (name: string, x: number, y: number, confirm?: boolean) => void; cb: (name: string, x: number, y: number, confirm?: boolean) => void;
} }