Skip to content

Commit 75d278c

Browse files
committed
1 parent 1ef7489 commit 75d278c

File tree

2 files changed

+246
-0
lines changed

2 files changed

+246
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import React, { useRef, PointerEventHandler, useState, useEffect } from 'react';
2+
import {
3+
stroke as brush,
4+
BrushStroke,
5+
defaultBrushConfig,
6+
BrushStrokeResult,
7+
} from 'croquis.js/lib/brush/simple';
8+
import {
9+
getStroke as getPulledStringStroke,
10+
defaultPulledStringConfig,
11+
PulledStringDrawingContext,
12+
} from 'croquis.js/lib/stabilizer/pulled-string';
13+
import type { StrokeDrawingContext } from 'croquis.js/lib/stroke-protocol';
14+
import { getStylusState, createStylusState } from 'croquis.js/lib/stylus';
15+
import PulledStringGuide from '../../components/guide/stabilizer/PulledStringGuide';
16+
import Draw from '../../components/example/Draw';
17+
import GithubCorner from '../../components/GithubCorner';
18+
import useCanvasFadeout from '../../misc/useCanvasFadeout';
19+
import useWindowSize from '../../misc/useWindowSize';
20+
import useForceUpdate from '../../misc/useForceUpdate';
21+
22+
const pulledString = getPulledStringStroke(brush);
23+
24+
const Page = () => {
25+
const canvasRef = useRef<HTMLCanvasElement>(null);
26+
useCanvasFadeout(canvasRef);
27+
const windowSize = useWindowSize();
28+
const [drawingPhase, setDrawingPhase] = useState<
29+
StrokeDrawingContext<any, any, BrushStrokeResult>
30+
>();
31+
useEffect(() => {
32+
if (!drawingPhase?.getState().update) return;
33+
const id = setInterval(drawingPhase.getState().update, 10);
34+
return () => clearInterval(id);
35+
}, [drawingPhase]);
36+
const downHandler: PointerEventHandler = e => {
37+
const ctx = canvasRef.current!.getContext('2d')!;
38+
const stylusState = getStylusState(e.nativeEvent);
39+
const brushConfig = {
40+
...defaultBrushConfig,
41+
ctx,
42+
size: 20,
43+
};
44+
const drawingPhase = pulledString.down(
45+
{
46+
...defaultPulledStringConfig,
47+
targetConfig: brushConfig,
48+
},
49+
stylusState
50+
);
51+
setDrawingPhase(drawingPhase);
52+
};
53+
useEffect(() => {
54+
if (!drawingPhase) return;
55+
const moveHandler = (e: PointerEvent) => {
56+
const stylusState = getStylusState(e);
57+
drawingPhase.move(stylusState);
58+
};
59+
const upHandler = (e: PointerEvent) => {
60+
const stylusState = getStylusState(e);
61+
drawingPhase.up(stylusState);
62+
setDrawingPhase(undefined);
63+
};
64+
window.addEventListener('pointermove', moveHandler);
65+
window.addEventListener('pointerup', upHandler);
66+
return () => {
67+
window.removeEventListener('pointermove', moveHandler);
68+
window.removeEventListener('pointerup', upHandler);
69+
};
70+
}, [drawingPhase]);
71+
return (
72+
<>
73+
<canvas
74+
ref={canvasRef}
75+
onPointerDown={downHandler}
76+
width={windowSize.width}
77+
height={windowSize.height}
78+
style={{
79+
position: 'absolute',
80+
top: 0,
81+
left: 0,
82+
touchAction: 'none',
83+
}}
84+
/>
85+
<StabilizerGuide drawingPhase={drawingPhase} />
86+
<Draw drawing={!!drawingPhase} />
87+
<GithubCorner
88+
bannerColor="#000"
89+
octoColor="#fff"
90+
href="https://github.com/disjukr/croquis.js/blob/master/packages/website/src/pages/example/stabilizer-pulled-string.tsx"
91+
/>
92+
</>
93+
);
94+
};
95+
96+
export default Page;
97+
98+
interface StabilizerGuideProps {
99+
drawingPhase?: PulledStringDrawingContext<BrushStroke>;
100+
}
101+
const defaultStylusState = createStylusState();
102+
const StabilizerGuide: React.FC<StabilizerGuideProps> = props => {
103+
const [stylusState, setStylusState] = useState(defaultStylusState);
104+
const forceUpdate = useForceUpdate();
105+
useEffect(() => {
106+
const pointermove = (e: PointerEvent) => setStylusState(getStylusState(e));
107+
const id = setInterval(forceUpdate, 10);
108+
window.addEventListener('pointermove', pointermove);
109+
return () => {
110+
clearInterval(id);
111+
window.removeEventListener('pointermove', pointermove);
112+
};
113+
}, []);
114+
if (!props.drawingPhase) return null;
115+
return (
116+
<PulledStringGuide
117+
brushSize={props.drawingPhase.getConfig(brush).size}
118+
stylusState={stylusState}
119+
follower={props.drawingPhase.getState().follower}
120+
stringLength={props.drawingPhase.getConfig().stringLength}
121+
style={{ position: 'absolute', top: 0, left: 0 }}
122+
/>
123+
);
124+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import React, { useRef, PointerEventHandler, useState, useEffect } from 'react';
2+
import {
3+
stroke as brush,
4+
BrushStroke,
5+
defaultBrushConfig,
6+
BrushStrokeResult,
7+
} from 'croquis.js/lib/brush/simple';
8+
import {
9+
getStroke as getSnakeStroke,
10+
defaultSnakeConfig,
11+
SnakeDrawingContext,
12+
} from 'croquis.js/lib/stabilizer/snake';
13+
import type { StrokeDrawingContext } from 'croquis.js/lib/stroke-protocol';
14+
import { getStylusState, createStylusState } from 'croquis.js/lib/stylus';
15+
import SnakeGuide from '../../components/guide/stabilizer/SnakeGuide';
16+
import Draw from '../../components/example/Draw';
17+
import GithubCorner from '../../components/GithubCorner';
18+
import useCanvasFadeout from '../../misc/useCanvasFadeout';
19+
import useWindowSize from '../../misc/useWindowSize';
20+
import useForceUpdate from '../../misc/useForceUpdate';
21+
22+
const snake = getSnakeStroke(brush);
23+
24+
const Page = () => {
25+
const canvasRef = useRef<HTMLCanvasElement>(null);
26+
useCanvasFadeout(canvasRef);
27+
const windowSize = useWindowSize();
28+
const [drawingPhase, setDrawingPhase] = useState<
29+
StrokeDrawingContext<any, any, BrushStrokeResult>
30+
>();
31+
useEffect(() => {
32+
if (!drawingPhase?.getState().update) return;
33+
const id = setInterval(drawingPhase.getState().update, 10);
34+
return () => clearInterval(id);
35+
}, [drawingPhase]);
36+
const downHandler: PointerEventHandler = e => {
37+
const ctx = canvasRef.current!.getContext('2d')!;
38+
const stylusState = getStylusState(e.nativeEvent);
39+
const brushConfig = {
40+
...defaultBrushConfig,
41+
ctx,
42+
size: 20,
43+
};
44+
const drawingPhase = snake.down(
45+
{
46+
...defaultSnakeConfig,
47+
targetConfig: brushConfig,
48+
},
49+
stylusState
50+
);
51+
setDrawingPhase(drawingPhase);
52+
};
53+
useEffect(() => {
54+
if (!drawingPhase) return;
55+
const moveHandler = (e: PointerEvent) => {
56+
const stylusState = getStylusState(e);
57+
drawingPhase.move(stylusState);
58+
};
59+
const upHandler = (e: PointerEvent) => {
60+
const stylusState = getStylusState(e);
61+
drawingPhase.up(stylusState);
62+
setDrawingPhase(undefined);
63+
};
64+
window.addEventListener('pointermove', moveHandler);
65+
window.addEventListener('pointerup', upHandler);
66+
return () => {
67+
window.removeEventListener('pointermove', moveHandler);
68+
window.removeEventListener('pointerup', upHandler);
69+
};
70+
}, [drawingPhase]);
71+
return (
72+
<>
73+
<canvas
74+
ref={canvasRef}
75+
onPointerDown={downHandler}
76+
width={windowSize.width}
77+
height={windowSize.height}
78+
style={{
79+
position: 'absolute',
80+
top: 0,
81+
left: 0,
82+
touchAction: 'none',
83+
}}
84+
/>
85+
<StabilizerGuide drawingPhase={drawingPhase} />
86+
<Draw drawing={!!drawingPhase} />
87+
<GithubCorner
88+
bannerColor="#000"
89+
octoColor="#fff"
90+
href="https://github.com/disjukr/croquis.js/blob/master/packages/website/src/pages/example/stabilizer-snake.tsx"
91+
/>
92+
</>
93+
);
94+
};
95+
96+
export default Page;
97+
98+
interface StabilizerGuideProps {
99+
drawingPhase?: SnakeDrawingContext<BrushStroke>;
100+
}
101+
const defaultStylusState = createStylusState();
102+
const StabilizerGuide: React.FC<StabilizerGuideProps> = props => {
103+
const [stylusState, setStylusState] = useState(defaultStylusState);
104+
const forceUpdate = useForceUpdate();
105+
useEffect(() => {
106+
const pointermove = (e: PointerEvent) => setStylusState(getStylusState(e));
107+
const id = setInterval(forceUpdate, 10);
108+
window.addEventListener('pointermove', pointermove);
109+
return () => {
110+
clearInterval(id);
111+
window.removeEventListener('pointermove', pointermove);
112+
};
113+
}, []);
114+
if (!props.drawingPhase) return null;
115+
return (
116+
<SnakeGuide
117+
brushSize={props.drawingPhase.getConfig(brush).size}
118+
stylusStates={props.drawingPhase.getState().stylusStates}
119+
style={{ position: 'absolute', top: 0, left: 0 }}
120+
/>
121+
);
122+
};

0 commit comments

Comments
 (0)