mirror of
https://github.com/bspeice/speice.io
synced 2024-12-22 16:48:10 -05:00
Use a sizing ref to avoid resizing the canvas
This commit is contained in:
parent
c3c3c65614
commit
f643996128
@ -2,14 +2,32 @@ import React, {useContext, useEffect, useMemo, useRef, useState} from "react";
|
|||||||
import * as params from "../src/params";
|
import * as params from "../src/params";
|
||||||
import {PainterContext} from "../src/Canvas";
|
import {PainterContext} from "../src/Canvas";
|
||||||
import {colorFromPalette} from "./paintColor";
|
import {colorFromPalette} from "./paintColor";
|
||||||
import {chaosGameColor, ChaosGameColorProps, TransformColor} from "./chaosGameColor";
|
import {chaosGameColor, Props as ChaosGameColorProps, TransformColor} from "./chaosGameColor";
|
||||||
|
|
||||||
import styles from "../src/css/styles.module.css";
|
import styles from "../src/css/styles.module.css";
|
||||||
import {histIndex} from "../src/camera";
|
import {histIndex} from "../src/camera";
|
||||||
import {useColorMode} from "@docusaurus/theme-common";
|
import {useColorMode} from "@docusaurus/theme-common";
|
||||||
|
|
||||||
const paletteBarPainter = (palette: number[]) =>
|
type PaletteBarProps = {
|
||||||
(width: number, height: number) => {
|
height: number;
|
||||||
|
palette: number[];
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}
|
||||||
|
const PaletteBar: React.FC<PaletteBarProps> = ({height, palette, children}) => {
|
||||||
|
const sizingRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [width, setWidth] = useState(0);
|
||||||
|
useEffect(() => {
|
||||||
|
if (sizingRef) {
|
||||||
|
setWidth(sizingRef.current.offsetWidth);
|
||||||
|
}
|
||||||
|
}, [sizingRef]);
|
||||||
|
|
||||||
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const paletteImage = useMemo(() => {
|
||||||
|
if (width === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const image = new ImageData(width, height);
|
const image = new ImageData(width, height);
|
||||||
for (let x = 0; x < width; x++) {
|
for (let x = 0; x < width; x++) {
|
||||||
const colorIndex = x / width;
|
const colorIndex = x / width;
|
||||||
@ -23,21 +41,20 @@ const paletteBarPainter = (palette: number[]) =>
|
|||||||
image.data[pixelIndex + 3] = 0xff;
|
image.data[pixelIndex + 3] = 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
type PaletteBarProps = {
|
return image;
|
||||||
height: number;
|
}, [width, height, palette]);
|
||||||
palette: number[];
|
|
||||||
children?: React.ReactNode;
|
useEffect(() => {
|
||||||
|
if (canvasRef && paletteImage) {
|
||||||
|
canvasRef.current.getContext("2d").putImageData(paletteImage, 0, 0);
|
||||||
}
|
}
|
||||||
const PaletteBar: React.FC<PaletteBarProps> = ({height, palette, children}) => {
|
}, [canvasRef, paletteImage]);
|
||||||
const painter = useMemo(() => paletteBarPainter(palette), [palette]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div style={{width: '100%', height, marginTop: '1em', marginBottom: '1em'}}>
|
<div ref={sizingRef} style={{width: '100%', height}}>
|
||||||
{/*<AutoSizingCanvas painter={painter}/>*/}
|
{width > 0 ? <canvas ref={canvasRef} width={width} height={height}/> : null}
|
||||||
</div>
|
</div>
|
||||||
{children}
|
{children}
|
||||||
</>
|
</>
|
||||||
@ -115,7 +132,6 @@ export default function FlameColor({quality, children}: Props) {
|
|||||||
height,
|
height,
|
||||||
transforms: params.xforms,
|
transforms: params.xforms,
|
||||||
final: params.xformFinal,
|
final: params.xformFinal,
|
||||||
quality,
|
|
||||||
palette: params.palette,
|
palette: params.palette,
|
||||||
colors: [xform1Color, xform2Color, xform3Color],
|
colors: [xform1Color, xform2Color, xform3Color],
|
||||||
finalColor: xformFinalColor
|
finalColor: xformFinalColor
|
||||||
|
@ -4,11 +4,10 @@ import {PainterContext} from "../src/Canvas";
|
|||||||
import {chaosGameHistogram} from "./chaosGameHistogram";
|
import {chaosGameHistogram} from "./chaosGameHistogram";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
quality?: number;
|
paint: (width: number, height: number, histogram: number[]) => ImageData;
|
||||||
paint: (width: number, histogram: Uint32Array) => ImageData;
|
|
||||||
children?: React.ReactElement;
|
children?: React.ReactElement;
|
||||||
}
|
}
|
||||||
export default function FlameHistogram({quality, paint, children}: Props) {
|
export default function FlameHistogram({paint, children}: Props) {
|
||||||
const {width, height, setPainter} = useContext(PainterContext);
|
const {width, height, setPainter} = useContext(PainterContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -17,11 +16,10 @@ export default function FlameHistogram({quality, paint, children}: Props) {
|
|||||||
height,
|
height,
|
||||||
transforms,
|
transforms,
|
||||||
final,
|
final,
|
||||||
quality,
|
|
||||||
paint
|
paint
|
||||||
}
|
}
|
||||||
setPainter(chaosGameHistogram(gameParams));
|
setPainter(chaosGameHistogram(gameParams));
|
||||||
}, []);
|
}, [width, height]);
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
@ -17,7 +17,7 @@ function mixColor(color1: number, color2: number, colorSpeed: number) {
|
|||||||
return color1 * (1 - colorSpeed) + color2 * colorSpeed;
|
return color1 * (1 - colorSpeed) + color2 * colorSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = ChaosGameFinalProps & {
|
export type Props = ChaosGameFinalProps & {
|
||||||
palette: number[];
|
palette: number[];
|
||||||
colors: TransformColor[];
|
colors: TransformColor[];
|
||||||
finalColor: TransformColor;
|
finalColor: TransformColor;
|
||||||
|
@ -14,8 +14,17 @@ type CanvasProps = {
|
|||||||
children?: React.ReactElement
|
children?: React.ReactElement
|
||||||
}
|
}
|
||||||
export const Canvas: React.FC<CanvasProps> = ({style, children}) => {
|
export const Canvas: React.FC<CanvasProps> = ({style, children}) => {
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const sizingRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [width, setWidth] = useState(0);
|
||||||
|
const [height, setHeight] = useState(0);
|
||||||
|
useEffect(() => {
|
||||||
|
if (sizingRef.current) {
|
||||||
|
setWidth(sizingRef.current.offsetWidth);
|
||||||
|
setHeight(sizingRef.current.offsetHeight);
|
||||||
|
}
|
||||||
|
}, [sizingRef]);
|
||||||
|
|
||||||
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvasRef.current) {
|
if (!canvasRef.current) {
|
||||||
@ -35,16 +44,7 @@ export const Canvas: React.FC<CanvasProps> = ({style, children}) => {
|
|||||||
observer.unobserve(canvasRef.current);
|
observer.unobserve(canvasRef.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [canvasRef]);
|
}, [canvasRef.current]);
|
||||||
|
|
||||||
const [width, setWidth] = useState(0);
|
|
||||||
const [height, setHeight] = useState(0);
|
|
||||||
useEffect(() => {
|
|
||||||
if (canvasRef.current) {
|
|
||||||
setWidth(canvasRef.current.offsetWidth);
|
|
||||||
setHeight(canvasRef.current.offsetHeight);
|
|
||||||
}
|
|
||||||
}, [canvasRef]);
|
|
||||||
|
|
||||||
const [imageHolder, setImageHolder] = useState<[ImageData]>(null);
|
const [imageHolder, setImageHolder] = useState<[ImageData]>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -76,25 +76,22 @@ export const Canvas: React.FC<CanvasProps> = ({style, children}) => {
|
|||||||
}
|
}
|
||||||
}, [painter]);
|
}, [painter]);
|
||||||
|
|
||||||
const {colorMode} = useColorMode();
|
const filter = useColorMode().colorMode === 'dark' ? 'invert(1)' : '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<canvas
|
<center>
|
||||||
ref={canvasRef}
|
<div ref={sizingRef} style={style}>
|
||||||
width={width}
|
{width > 0 ? <canvas ref={canvasRef} width={width} height={height} style={{filter}}/> : null}
|
||||||
height={height}
|
</div>
|
||||||
style={{
|
</center>
|
||||||
filter: colorMode === 'dark' ? 'invert(1)' : '',
|
|
||||||
...style
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<PainterContext.Provider value={{width, height, setPainter}}>
|
<PainterContext.Provider value={{width, height, setPainter}}>
|
||||||
<BrowserOnly>{() => children}</BrowserOnly>
|
{width > 0 ? children : null}
|
||||||
</PainterContext.Provider>
|
</PainterContext.Provider>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SquareCanvas: React.FC<CanvasProps> = ({style, children}) => {
|
export const SquareCanvas: React.FC<CanvasProps> = ({style, children}) => {
|
||||||
return <Canvas style={{width: '100%', aspectRatio: '1/1', ...style}} children={children}/>
|
return <center><Canvas style={{width: '75%', aspectRatio: '1/1', ...style}} children={children}/></center>
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user