View detection

This commit is contained in:
Bradlee Speice 2024-12-08 16:17:21 -05:00
parent 3c583705f8
commit 78d71cbc7b
7 changed files with 40 additions and 16 deletions

View File

@ -103,7 +103,7 @@ const ColorEditor: React.FC<ColorEditorProps> = ({title, palette, transformColor
onInput={e => setTransformColor({...transformColor, color: Number(e.currentTarget.value)})}/> onInput={e => setTransformColor({...transformColor, color: Number(e.currentTarget.value)})}/>
</div> </div>
<div className={styles.inputElement}> <div className={styles.inputElement}>
<p>Color speed: {transformColor.colorSpeed}</p> <p>Speed: {transformColor.colorSpeed}</p>
<input type={'range'} min={0} max={1} step={.001} value={transformColor.colorSpeed} <input type={'range'} min={0} max={1} step={.001} value={transformColor.colorSpeed}
onInput={e => setTransformColor({...transformColor, colorSpeed: Number(e.currentTarget.value)})}/> onInput={e => setTransformColor({...transformColor, colorSpeed: Number(e.currentTarget.value)})}/>
</div> </div>

View File

@ -1,24 +1,24 @@
import React, {useContext, useEffect} from "react"; import React, {useContext, useEffect} from "react";
import * as params from "../src/params"; import {xforms as transforms, xformFinal as final} from "../src/params";
import {PainterContext} from "../src/Canvas"; import {PainterContext} from "../src/Canvas";
import {chaosGameHistogram} from "./chaosGameHistogram"; import {chaosGameHistogram} from "./chaosGameHistogram";
type Props = { type Props = {
quality?: number; quality?: number;
paintFn: (width: number, histogram: Uint32Array) => ImageData; paint: (width: number, histogram: Uint32Array) => ImageData;
children?: React.ReactElement; children?: React.ReactElement;
} }
export default function FlameHistogram({quality, paintFn, children}: Props) { export default function FlameHistogram({quality, paint, children}: Props) {
const {width, height, setPainter} = useContext(PainterContext); const {width, height, setPainter} = useContext(PainterContext);
useEffect(() => { useEffect(() => {
const gameParams = { const gameParams = {
width, width,
height, height,
transforms: params.xforms, transforms,
final: params.xformFinal, final,
quality, quality,
painter: paintFn paint
} }
setPainter(chaosGameHistogram(gameParams)); setPainter(chaosGameHistogram(gameParams));
}, []); }, []);

View File

@ -20,7 +20,7 @@ export type ChaosGameColorProps = ChaosGameFinalProps & {
} }
export function* chaosGameColor({width, height, transforms, final, palette, colors, finalColor, quality, step}: ChaosGameColorProps) { export function* chaosGameColor({width, height, transforms, final, palette, colors, finalColor, quality, step}: ChaosGameColorProps) {
let iterations = (quality ?? 1) * width * height; let iterations = (quality ?? 1) * width * height;
step = step ?? 100_000; step = step ?? 10_000;
let currentColor = Math.random(); let currentColor = Math.random();
const red = Array(width * height).fill(0); const red = Array(width * height).fill(0);

View File

@ -9,7 +9,7 @@ export type ChaosGameHistogramProps = ChaosGameFinalProps & {
} }
export function* chaosGameHistogram({width, height, transforms, final, quality, step, paint}: ChaosGameHistogramProps) { export function* chaosGameHistogram({width, height, transforms, final, quality, step, paint}: ChaosGameHistogramProps) {
let iterations = (quality ?? 1) * width * height; let iterations = (quality ?? 1) * width * height;
step = step ?? 100_000; step = step ?? 10_000;
const histogram = new Uint32Array(width * height); const histogram = new Uint32Array(width * height);

View File

@ -32,7 +32,7 @@ import Canvas from "../src/Canvas";
import FlameHistogram from "./FlameHistogram"; import FlameHistogram from "./FlameHistogram";
import {paintLinear} from "./paintLinear"; import {paintLinear} from "./paintLinear";
<Canvas><FlameHistogram quality={5} paintFn={paintLinear}/></Canvas> <Canvas><FlameHistogram quality={5} paint={paintLinear}/></Canvas>
## Log display ## Log display
@ -42,7 +42,7 @@ import paintLogarithmicSource from "!!raw-loader!./paintLogarithmic"
import {paintLogarithmic} from './paintLogarithmic' import {paintLogarithmic} from './paintLogarithmic'
<Canvas><FlameHistogram quality={5} paintFn={paintLogarithmic}/></Canvas> <Canvas><FlameHistogram quality={5} paint={paintLogarithmic}/></Canvas>
## Color ## Color

View File

@ -1,4 +1,4 @@
import React, {useCallback, useEffect, useState, createContext} from "react"; import React, {useCallback, useEffect, useState, createContext, useRef} from "react";
import {useColorMode} from "@docusaurus/theme-common"; import {useColorMode} from "@docusaurus/theme-common";
import BrowserOnly from "@docusaurus/BrowserOnly"; import BrowserOnly from "@docusaurus/BrowserOnly";
@ -100,10 +100,32 @@ interface CanvasProps {
* a good way to make those generic. * a good way to make those generic.
*/ */
export default function Canvas({width, height, children}: CanvasProps) { export default function Canvas({width, height, children}: CanvasProps) {
const viewportDetectionRef = useRef<HTMLDivElement>(null);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
if (!viewportDetectionRef) {
return;
}
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true);
}
}, {root: null, threshold: .1});
observer.observe(viewportDetectionRef.current);
return () => {
if (viewportDetectionRef.current) {
observer.unobserve(viewportDetectionRef.current);
}
}
}, [viewportDetectionRef]);
const [image, setImage] = useState<[ImageData]>(null); const [image, setImage] = useState<[ImageData]>(null);
const [painterHolder, setPainterHolder] = useState<[Iterator<ImageData>]>(null); const [painterHolder, setPainterHolder] = useState<[Iterator<ImageData>]>(null);
useEffect(() => { useEffect(() => {
if (!painterHolder) { if (!isVisible || !painterHolder) {
console.log("Skipping, not visible");
return; return;
} }
@ -115,7 +137,7 @@ export default function Canvas({width, height, children}: CanvasProps) {
} else { } else {
setPainterHolder(null); setPainterHolder(null);
} }
}, [painterHolder]); }, [isVisible, painterHolder]);
const [painter, setPainter] = useState<Iterator<ImageData>>(null); const [painter, setPainter] = useState<Iterator<ImageData>>(null);
useEffect(() => { useEffect(() => {
@ -129,7 +151,9 @@ export default function Canvas({width, height, children}: CanvasProps) {
return ( return (
<> <>
<center> <center>
<InvertibleCanvas width={width} height={height} image={image}/> <div ref={viewportDetectionRef}>
<InvertibleCanvas width={width} height={height} image={image}/>
</div>
</center> </center>
<PainterContext.Provider value={{width, height, setPainter}}> <PainterContext.Provider value={{width, height, setPainter}}>
<BrowserOnly>{() => children}</BrowserOnly> <BrowserOnly>{() => children}</BrowserOnly>

View File

@ -4,7 +4,7 @@
"private": true, "private": true,
"scripts": { "scripts": {
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
"start": "docusaurus start", "start": "docusaurus start --host 0.0.0.0",
"build": "docusaurus build", "build": "docusaurus build",
"swizzle": "docusaurus swizzle", "swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy", "deploy": "docusaurus deploy",