mirror of
https://github.com/reanimate/reanimate.git
synced 2026-09-14 09:32:22 +00:00
Switch to a monadic API.
Former-commit-id: 0c2706be2b4cf0a92a46f000cbd1da620f86a2e1
This commit is contained in:
parent
aae3a4978f
commit
9707cca88b
11 changed files with 462 additions and 371 deletions
|
|
@ -32,6 +32,12 @@ div.messages {
|
|||
div.messages pre {
|
||||
margin: 0;
|
||||
}
|
||||
.home {
|
||||
color: white;
|
||||
text-align: center;
|
||||
float:right;
|
||||
margin-right: 2em;
|
||||
}
|
||||
|
||||
|
||||
#editor {
|
||||
|
|
|
|||
|
|
@ -10,24 +10,30 @@ import preset from './Presets';
|
|||
class App extends Component {
|
||||
connect = () => {
|
||||
const ws = new WebSocket("wss://reanimate.clozecards.com:9160");
|
||||
// const ws = new WebSocket("wss://localhost:9160");
|
||||
// const ws = new WebSocket("ws://localhost:9161");
|
||||
|
||||
ws.onopen = event => {
|
||||
this.setState(state => ({...state, message: "Connected."}));
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
message: "Connected."
|
||||
}));
|
||||
ws.send(this.state.program);
|
||||
}
|
||||
ws.onclose = event => {
|
||||
this.setState(state => ({...state, message: "Disconnected."}));
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
message: "Disconnected."
|
||||
}));
|
||||
setTimeout(this.connect, 1000);
|
||||
}
|
||||
ws.onmessage = event => {
|
||||
if( event.data === "Success!" ) {
|
||||
if (event.data === "Success!") {
|
||||
console.log("Success");
|
||||
} else if( event.data === "Rendering" ) {
|
||||
} else if (event.data === "Rendering") {
|
||||
this.setState({message: "Rendering..."});
|
||||
this.nFrames_new = 0;
|
||||
this.svgs_new = [];
|
||||
} else if( event.data === "Done" ) {
|
||||
} else if (event.data === "Done") {
|
||||
this.setState({message: "Success!"});
|
||||
console.log("Done");
|
||||
this.nFrames = this.nFrames_new;
|
||||
|
|
@ -35,9 +41,9 @@ class App extends Component {
|
|||
this.nFrames_new = 0;
|
||||
this.svgs_new = [];
|
||||
this.start = Date.now();
|
||||
} else if( event.data.startsWith("Error") ) {
|
||||
} else if (event.data.startsWith("Error")) {
|
||||
console.log("Error");
|
||||
this.setState({message: event.data.substring(5) });
|
||||
this.setState({message: event.data.substring(5)});
|
||||
} else {
|
||||
this.setState({message: `Rendering: ${this.nFrames_new}`});
|
||||
this.nFrames_new++;
|
||||
|
|
@ -46,7 +52,11 @@ class App extends Component {
|
|||
this.svgs_new.push(div);
|
||||
}
|
||||
}
|
||||
this.setState(state => ({...state, socket: ws, message: "Connecting..."}));
|
||||
this.setState(state => ({
|
||||
...state,
|
||||
socket: ws,
|
||||
message: "Connecting..."
|
||||
}));
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
@ -54,7 +64,7 @@ class App extends Component {
|
|||
this.state = {
|
||||
program: preset[0].programs[0].code
|
||||
};
|
||||
setTimeout(this.connect,0);
|
||||
setTimeout(this.connect, 0);
|
||||
this.nFrames_new = 0;
|
||||
this.svgs_new = [];
|
||||
this.nFrames = 0;
|
||||
|
|
@ -64,12 +74,11 @@ class App extends Component {
|
|||
const animate = () => {
|
||||
const now = Date.now();
|
||||
const nFrames = self.nFrames;
|
||||
const thisFrame = (Math.round((now-this.start)/1000*60))%nFrames
|
||||
// const thisFrame = 0;
|
||||
// console.log('Animation frame:', thisFrame, nFrames);
|
||||
if(nFrames) {
|
||||
const thisFrame = (Math.round((now - this.start) / 1000 * 60)) % nFrames
|
||||
// const thisFrame = 0; console.log('Animation frame:', thisFrame, nFrames);
|
||||
if (nFrames) {
|
||||
// self.svg.innerHTML = self.svgs[thisFrame];
|
||||
while(self.svg.firstChild)
|
||||
while (self.svg.firstChild)
|
||||
self.svg.removeChild(self.svg.firstChild);
|
||||
self.svg.appendChild(self.svgs[thisFrame]);
|
||||
} else {
|
||||
|
|
@ -93,7 +102,10 @@ class App extends Component {
|
|||
|
||||
this.timeout = setTimeout(function() {
|
||||
console.log('change', text);
|
||||
self.setState(state => ({...state, message: "Compiling..."}));
|
||||
self.setState(state => ({
|
||||
...state,
|
||||
message: "Compiling..."
|
||||
}));
|
||||
socket.send(text);
|
||||
}, 500);
|
||||
};
|
||||
|
|
@ -106,14 +118,15 @@ class App extends Component {
|
|||
<div className="App">
|
||||
<div>
|
||||
<select onChange={this.selectPreset}>
|
||||
{ preset.map( (group, i) =>
|
||||
<optgroup key={i} label={group.name}>
|
||||
{ group.programs.map( (elt, i) =>
|
||||
<option value={elt.code} key={i}>{elt.name}</option>
|
||||
)}
|
||||
</optgroup>
|
||||
)}
|
||||
{
|
||||
preset.map(
|
||||
(group, i) => <optgroup key={i} label={group.name}>
|
||||
{group.programs.map((elt, i) => <option value={elt.code} key={i}>{elt.name}</option>)}
|
||||
</optgroup>
|
||||
)
|
||||
}
|
||||
</select>
|
||||
<a className="home" href="https://github.com/Lemmih/reanimate">Return to GitHub page.</a>
|
||||
</div>
|
||||
<div className="editor">
|
||||
<AceEditor
|
||||
|
|
@ -131,9 +144,7 @@ class App extends Component {
|
|||
$blockScrolling: true
|
||||
}}/>
|
||||
</div>
|
||||
<div className="controls">
|
||||
|
||||
</div>
|
||||
<div className="controls"></div>
|
||||
<div className="viewer">
|
||||
<div ref={node => this.svg = node}/>
|
||||
<div className="messages">
|
||||
|
|
|
|||
|
|
@ -1,46 +1,43 @@
|
|||
const latex_draw =
|
||||
`animation = pauseAtEnd 1 $ proc () -> do
|
||||
emit -< toHtml $ mkBackground "black"
|
||||
drawText msg \`andThen\` fillText msg -< ()
|
||||
`animation :: Animation
|
||||
animation =
|
||||
bg \`sim\` (autoReverse $ drawText \`andThen\` fillText)
|
||||
where
|
||||
bg = mkAnimation 0 $ emit (mkBackground "black")
|
||||
msg = "\\\\sum_{k=1}^\\\\infty {1 \\\\over k^2} = {\\\\pi^2 \\\\over 6}"
|
||||
placement = translate (320/2) (180/2) . scale 5
|
||||
fillText txt = proc () -> do
|
||||
duration 1 -< ()
|
||||
s <- signal 0 1 -< ()
|
||||
emit -< toHtml $ placement $
|
||||
withFillColor "white" $ withFillOpacity s $
|
||||
center $ latexAlign txt
|
||||
drawText txt = proc () -> do
|
||||
duration 2 -< ()
|
||||
s <- signal 0 1 -< ()
|
||||
emit -< toHtml $ placement $
|
||||
glyphs = center $ latexAlign msg
|
||||
fillText = mkAnimation 1 $ do
|
||||
s <- signal 0 1
|
||||
emit $ scale 5 $ withFillColor "white" $ withFillOpacity s glyphs
|
||||
drawText = mkAnimation 2 $ do
|
||||
s <- signal 0 1
|
||||
emit $ scale 5 $
|
||||
withStrokeColor "white" $ withFillOpacity 0 $ withStrokeWidth (Num 0.1) $
|
||||
partialSvg s $ center $ latexAlign txt`;
|
||||
partialSvg s glyphs`;
|
||||
|
||||
const bbox =
|
||||
`animation :: Ani ()
|
||||
animation = proc () -> do
|
||||
emit -< toHtml $ mkBackground "black"
|
||||
duration 5 -< ()
|
||||
annotate' bbox1 -< g_ [transform_ $ Lucid.translate (320/2-50) (180/2)]
|
||||
annotate' bbox2 -< g_ [transform_ $ Lucid.translate (320/2+50) (180/2)]
|
||||
`animation :: Animation
|
||||
animation = bg \`sim\`
|
||||
mapA (translate (-50) 0) bbox1 \`sim\`
|
||||
mapA (translate 50 0) bbox2
|
||||
where
|
||||
bg = mkAnimation 0 $ emit $ mkBackground "black"
|
||||
|
||||
bbox1 :: Ani ()
|
||||
bbox1 = proc () -> do
|
||||
s <- signal 0 1 -< ()
|
||||
emit -< do
|
||||
toHtml $ mkBoundingBox $ rotate (360*s) svg
|
||||
toHtml $ withFillColor "white" $ rotate (360*s) svg
|
||||
bbox1 :: Animation
|
||||
bbox1 = mkAnimation 5 $ do
|
||||
s <- signal 0 1
|
||||
emit $ mkGroup
|
||||
[ mkBoundingBox $ rotate (360*s) svg
|
||||
, withFillColor "white" $ rotate (360*s) svg ]
|
||||
where
|
||||
svg = scale 3 $ center $ latexAlign "\\\\sum_{k=1}^\\\\infty"
|
||||
|
||||
bbox2 :: Ani ()
|
||||
bbox2 = proc () -> do
|
||||
s <- signalOscillate 0 1 -< ()
|
||||
emit -< do
|
||||
toHtml $ mkBoundingBox $ partialSvg s heartShape
|
||||
toHtml $ withStrokeColor "white" $ withFillOpacity 0 $ partialSvg s heartShape
|
||||
bbox2 :: Animation
|
||||
bbox2 = autoReverse $ mkAnimation 2.5 $ do
|
||||
s <- signal 0 1
|
||||
emit $ mkGroup
|
||||
[ mkBoundingBox $ partialSvg s heartShape
|
||||
, withStrokeColor "white" $ withFillOpacity 0 $ partialSvg s heartShape ]
|
||||
|
||||
mkBoundingBox :: Tree -> Tree
|
||||
mkBoundingBox svg = withStrokeColor "red" $ withFillOpacity 0 $
|
||||
|
|
@ -50,9 +47,9 @@ mkBoundingBox svg = withStrokeColor "red" $ withFillOpacity 0 $
|
|||
|
||||
heartShape =
|
||||
center $ rotateAroundCenter 225 $ mkPathString
|
||||
"M0.0,40.0 v-40.0 h40.0\
|
||||
\a20.0 20.0 90.0 0 1 0.0,40.0\
|
||||
\a20.0 20.0 90.0 0 1 -40.0,0.0 Z"`;
|
||||
"M0.0,40.0 v-40.0 h40.0\\
|
||||
\\a20.0 20.0 90.0 0 1 0.0,40.0\\
|
||||
\\a20.0 20.0 90.0 0 1 -40.0,0.0 Z"`;
|
||||
|
||||
const sinewave =
|
||||
`animation :: Ani ()
|
||||
|
|
@ -77,15 +74,14 @@ animation = proc () -> do
|
|||
wave idx = (idx*width, sin (idx*pi*2*freq) * 50)`;
|
||||
|
||||
const morph_wave =
|
||||
`animation :: Ani ()
|
||||
animation = proc () -> do
|
||||
duration 5 -< ()
|
||||
morph <- signalOscillate 0 1 -< ()
|
||||
emit -< toHtml $ mkBackground "black"
|
||||
emit -< toHtml $ withStrokeColor "white" $ mkGroup
|
||||
[ translate 30 50 $ mkPathText $ renderPathText wave1
|
||||
, translate 30 130 $ mkPathText $ renderPathText wave2
|
||||
, translate 30 90 $ mkPathText $ renderPathText $ morphPath wave1 wave2 morph
|
||||
`animation :: Animation
|
||||
animation = autoReverse $ mkAnimation 2.5 $ do
|
||||
morph <- signal 0 1
|
||||
emit $ mkBackground "black"
|
||||
emit $ withStrokeColor "white" $ translate (-320/2) (-180/2) $ mkGroup
|
||||
[ translate 30 50 $ mkLinePath wave1
|
||||
, translate 30 130 $ mkLinePath wave2
|
||||
, translate 30 90 $ mkLinePath $ morphPath wave1 wave2 morph
|
||||
, mkLine (Num 30, Num 10) (Num 30, Num 170)
|
||||
, mkLine (Num 30, Num 90) (Num 290, Num 90) ]
|
||||
where
|
||||
|
|
@ -94,13 +90,12 @@ animation = proc () -> do
|
|||
wave2 = approxFnData 100 $ \\idx -> (idx*width, sin (idx*pi*2*(freq*3)) * 20)`;
|
||||
|
||||
const morph_wave_circle =
|
||||
`animation :: Ani ()
|
||||
animation = proc t -> do
|
||||
duration 5 -< ()
|
||||
idx <- signalOscillate 0 1 -< ()
|
||||
emit -< toHtml $ mkBackground "black"
|
||||
emit -< toHtml $ withStrokeColor "white" $ mkGroup
|
||||
[ translate 30 90 $ mkPathText $ renderPathText $ morphPath circle wave1 idx
|
||||
`animation :: Animation
|
||||
animation = autoReverse $ mkAnimation 2.5 $ do
|
||||
idx <- signal 0 1
|
||||
emit $ mkBackground "black"
|
||||
emit $ withStrokeColor "white" $ translate (-320/2) (-180/2) $ mkGroup
|
||||
[ translate 30 90 $ mkLinePath $ morphPath circle wave1 idx
|
||||
, mkLine (Num 30, Num 10) (Num 30, Num 170)
|
||||
, mkLine (Num 30, Num 90) (Num 290, Num 90) ]
|
||||
where
|
||||
|
|
@ -110,99 +105,46 @@ animation = proc t -> do
|
|||
(cos (idx*pi*2+pi/2)*radius + width/2, sin (idx*pi*2+pi/2)*radius)`;
|
||||
|
||||
const progressMeters =
|
||||
`animation :: Ani ()
|
||||
animation = proc () -> do
|
||||
emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"]
|
||||
annotate' (adjustSpeed 1.0 progressMeter) -< g_ [transform_ $ Lucid.translate 40 20]
|
||||
annotate' (adjustSpeed 2.0 progressMeter) -< g_ [transform_ $ Lucid.translate 140 20]
|
||||
annotate' (adjustSpeed 0.5 progressMeter) -< g_ [transform_ $ Lucid.translate 240 20]
|
||||
|
||||
emit -< do
|
||||
text_ [x_ "55", y_ "150", font_size_ "20"
|
||||
, text_anchor_ "middle"
|
||||
, fill_ "white"] "1x"
|
||||
text_ [x_ "155", y_ "150", font_size_ "20"
|
||||
, text_anchor_ "middle"
|
||||
, fill_ "white"] "2x"
|
||||
text_ [x_ "255", y_ "150", font_size_ "20"
|
||||
, text_anchor_ "middle"
|
||||
, fill_ "white"] "0.5x"
|
||||
|
||||
progressMeter :: Ani ()
|
||||
progressMeter = loop $ proc () -> do
|
||||
duration 5 -< ()
|
||||
h <- signal 0 100 -< ()
|
||||
emit -< rect_ [ width_ "30", height_ "100", stroke_ "white", stroke_width_ "2", fill_opacity_ "0" ]
|
||||
emit -< rect_ [ width_ "30", num_ height_ h, stroke_ "white", fill_ "white" ]
|
||||
returnA -< ()`
|
||||
|
||||
const highlight =
|
||||
`animation :: Ani ()
|
||||
animation = proc () -> do
|
||||
emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"]
|
||||
emit -< do
|
||||
path_ (commonAttrs "white" ++ [d_ $ renderPathText rect1])
|
||||
path_ (commonAttrs "white" ++ [d_ $ renderPathText rect2])
|
||||
|
||||
path_ (commonAttrs "white" ++ [d_ $ renderPathText rect3])
|
||||
path_ (commonAttrs "lightblue" ++ [d_ $ renderPathText rect4])
|
||||
path_ (commonAttrs "yellow" ++ [d_ $ renderPathText rect5])
|
||||
path_ (commonAttrs "red" ++ [d_ $ renderPathText rect6])
|
||||
|
||||
follow
|
||||
[ mkTransition highlight1 highlight2
|
||||
, mkTransition highlight2 highlight3
|
||||
, mkTransition highlight3 highlight4
|
||||
, mkTransition highlight4 highlight5
|
||||
, mkTransition highlight5 highlight6
|
||||
, mkTransition highlight6 highlight1
|
||||
] -< ()
|
||||
|
||||
`animation :: Animation
|
||||
animation =
|
||||
bg \`sim\` labels \`sim\`
|
||||
mapA (translate (-100) 0) (adjustSpeed 1.0 progressMeter) \`simLoop\`
|
||||
mapA (translate 0 0) (adjustSpeed 2.0 progressMeter) \`simLoop\`
|
||||
mapA (translate 100 0) (adjustSpeed 0.5 progressMeter)
|
||||
where
|
||||
mkTransition from to = pauseAtEnd 1 $ proc () -> do
|
||||
duration 1 -< ()
|
||||
s <- signalSCurve 2 0 1 -< ()
|
||||
let trans = morphPath from to s
|
||||
emit -<
|
||||
path_ (highlightAttrs "green" ++ [d_ $ renderPathText trans <> "Z"])
|
||||
mkRect x y width height =
|
||||
[ (x,y), (x+width, y), (x+width, y+height), (x,y+height) ]
|
||||
rect1 = mkRect margin margin w h
|
||||
rect2 = mkRect (320-margin-w*2) margin (w*2) h
|
||||
rect3 = mkRect margin (180-margin-h) w h
|
||||
rect4 = mkRect (320/3) (180-margin-h) w h
|
||||
rect5 = mkRect (320/3*2-w) (180-margin-h) w h
|
||||
rect6 = mkRect (320-margin-w) (180-margin-h) w h
|
||||
highlight1 = mkRect (margin-b) (margin-b) (w+2*b) (h+2*b)
|
||||
highlight2 = mkRect (320-margin-w*2-b) (margin-b) (w*2+2*b) (h+2*b)
|
||||
highlight3 = mkRect (320-margin-w-b) (180-margin-h-b) (w+2*b) (h+2*b)
|
||||
highlight4 = mkRect (320/3*2-w-b) (180-margin-h-b) (320/3+2*b) (h+2*b)
|
||||
highlight5 = mkRect (320/3-b) (180-margin-h-b) (320/3+2*b) (h+2*b)
|
||||
highlight6 = mkRect (margin-b) (180-margin-h-b) (320/3+2*b) (h+2*b)
|
||||
b = 7; margin = 30; w = 30; h = 30
|
||||
commonAttrs c = [stroke_width_ "2", stroke_ c, fill_ c]
|
||||
highlightAttrs c = [stroke_width_ "2", stroke_ c, fill_opacity_ "0"]`;
|
||||
bg = mkAnimation 0 $ emit $ mkBackground "black"
|
||||
labels = mkAnimation 0 $ emit $ translate 0 70 $ withFillColor "white" $ mkGroup
|
||||
[ translate (-100) 0 $ scale 2 $ center $ latex "1x"
|
||||
, translate 0 0 $ scale 2 $ center $ latex "2x"
|
||||
, translate 100 0 $ scale 2 $ center $ latex "0.5x"
|
||||
]
|
||||
|
||||
progressMeter :: Animation
|
||||
progressMeter = mkAnimation 3 $ do
|
||||
h <- signal 0 100
|
||||
emit $ center $ mkGroup
|
||||
[ withStrokeColor "white" $ withStrokeWidth (Num 2) $ withFillOpacity 0 $
|
||||
mkRect (Num 0, Num 0) (Num 30) (Num 100)
|
||||
, withFillColor "white" $
|
||||
mkRect (Num 0, Num 0) (Num 30) (Num h) ]`
|
||||
|
||||
const latex_basic =
|
||||
`animation :: Ani ()
|
||||
animation = proc () -> do
|
||||
duration 2 -< ()
|
||||
s <- signalOscillate 0 1 -< ()
|
||||
emit -< toHtml $ mkGroup
|
||||
[ mkBackground "black"
|
||||
, translate (320/2) (180/2) $ mkGroup
|
||||
[ withStrokeColor "white" $ withFillOpacity 0 $ withStrokeWidth (Num 0.1) text
|
||||
, withFillColor "white" $ withFillOpacity s text] ]
|
||||
`animation :: Animation
|
||||
animation = autoReverse $ mkAnimation 2 $ do
|
||||
s <- signal 0 1
|
||||
emit $ mkGroup
|
||||
[ mkBackground "black"
|
||||
, withStrokeColor "white" $ withFillOpacity 0 $ withStrokeWidth (Num 0.1) text
|
||||
, withFillColor "white" $ withFillOpacity s text ]
|
||||
where
|
||||
text = scale 4 $ center $ latexAlign
|
||||
"\\\\sum_{k=1}^\\\\infty {1 \\\\over k^2} = {\\\\pi^2 \\\\over 6}"`
|
||||
|
||||
const latex_color =
|
||||
`animation :: Ani ()
|
||||
animation = proc () -> do
|
||||
duration 0.1 -< ()
|
||||
emit -< toHtml $ mkBackground "black"
|
||||
emit -< toHtml $ translate (320/2) (180/2) $ withStrokeWidth (Num 0.2) $
|
||||
`animation :: Animation
|
||||
animation = mkAnimation 1 $ do
|
||||
emit $ mkBackground "black"
|
||||
emit $ withStrokeWidth (Num 0.2) $
|
||||
withStrokeColor "white" $
|
||||
withSubglyphs [0] (withFillColor "blue") $
|
||||
withSubglyphs [1] (withFillColor "yellow") $
|
||||
|
|
@ -221,7 +163,7 @@ export default [
|
|||
, {name: "LaTeX Color", code: latex_color }
|
||||
, {name: "LaTeX Basic", code: latex_basic }
|
||||
, {name: "Bounding boxes", code: bbox }
|
||||
, {name: "Sinewave", code: sinewave }
|
||||
// , {name: "Sinewave", code: sinewave }
|
||||
, {name: "Morphwave", code: morph_wave }
|
||||
, {name: "Morphwave Circle", code: morph_wave_circle }
|
||||
, {name: "Progress meters", code: progressMeters }
|
||||
|
|
|
|||
Loading…
Reference in a new issue