theatre-js / theatre Goto Github PK
View Code? Open in Web Editor NEWMotion design editor for the web
Home Page: https://www.theatrejs.com
License: Apache License 2.0
Motion design editor for the web
Home Page: https://www.theatrejs.com
License: Apache License 2.0
Opening this issue since I've heard it from multiple sources now, keyframe selection is currently not as ideal as it probably could be.
Key problems right now:
Suggestions for improvements:
Right now it's only visible when you hover, you can't make it stay visible/hidden
When the following is added to a file within theatre/studio
and Keyframe
is not used within that file, eslint does not pick this up
import type {Keyframe} from '@theatre/core/projects/store/types/SheetState_Historic'
A very minor issue, but never the less would be nice to understand what's causing this and if it's happening anywhere else.
We're currently using eslint-plugin-unused-imports: 1.1.5
and I've also replicated this issue with version 2.0.0
It looks like a lot of the images for the UI could easily be converted to SVG, which would make them show up clearly on any display pixel density and also decrease load time by a good bit (since svgs are xml files and can be minified and gzipped, or inlined)
Would be nice to have this kind of flexible behaviour for ranges of numerical values:
Hi, it would be great to have SkinnedMesh as an editable type, so that models with skeletal animations can be played/edited. Currently I believe only mesh is exposed.
Thanks so much!
Nice tool! Can animations created in Theatre.js also be exported as Lottie animations so that they can be used in apps?
When building a project that uses the studio
npm package - and NODE_ENV
is set to production
the sequence pane (timeline) doesn't show up and keyframes become un-editable
create-react-app
and add @theathre/core
/ @theathre/studio
build
commandNODE_ENV
is set to development
this is what showsNODE_ENV
is set to production
this is what showsIf an object is created and down the line, decided that it's not needed, or want to add another property to it, no way to do that at the moment.
Feature request based on this thread.
The main idea is to have the ability to trigger functions at specific points in a sequence, similar to Unity's Animation Events or Timeline Signals.
Some common use cases would be to trigger side-effects like SFX or React state updates.
Currently, trying to time events accurately to music is tricky, as it's very hard to correctly place the playhead.
These features will make it far easier to create timelines that need to sync up to music accurately.
There are times when I want to move multiple keyframes at once in the sequence editor. These times I instinctively try to make a rectangle selection with the mouse, which moves the playhead here.
Here's a rough sketch of the rectangle selection tool to illustrate my point:
I haven't thought about how to resolve the conflict between moving the playhead and the multiple keyframe selection tool yet.
Hi guys.
The project was terminated?
Hi, this is a transcription of part of a discord conversation on theatrejs channel, moved here by suggestion of @AriaMinaei .
Basically I'm using the timeline for scrollable website transitions...
so labelling a frame group would probably be the most flexible (it would be possible to name either one frame or several ones) to work with that, instead of having to take note of individual time frame for each transition.
On Flash at least and very probably on other editors, there was an ability to name a keyframe or a range of keyframes.
Having that, the usage in terms of play
or some sort of playToPosition(frame time or frame name)
api could be something like the following: it would nice to be to be able to say "go to that frame group" either jump there instantaneously or playing from the current sequence position.
It could diverge slightly if when the play is triggered was from a frame before or after that frame group
Other parameter for that would be either stop on hitting the framegroup or also playing it through.
well I guess this might sound confusing but feel free to ask me any clarifications
Great work!
Hello,
first of all, i have to say that theaterjs is a pretty need piece of software imo. i'm not really into es6, but managed to wrap threejs/studio an integrate it into an angular application pretty easy. The studio part works except of some self-inflicted css fuckery flawless. :)
I'm stuck at the moment to play() a persisted project. No matter if i'm using the theater localstorage implementation nor if i try to load a json project exported from studio.createContentOfSaveFile(projectUuid);. I will atttach an excample json, looks good to me, but i do not get how the revision history works, maybe it's part of the problem. I digged into the js code a bit and learned that project.ready.then(()=>{}) will never resolve if studio is imported. I'm now able to run sheet.sequence.play() ->
//resolving persisted sheet
const [sheet, setSheet] = useState(project.sheet('Scene', 'default'));
//start sequence after component mounted
useEffect(() => {
project.ready.then(() => {
sheet.sequence.play().then((finished: boolean) => {
if (finished) {
console.log('Playback finished');
} else {
console.log('Playback interrupted');
}
});
});
});
The squence plays and also logs when the playback finishes. What i'm trying to do in the first place to use a bunch of React.FC which are coupled to SequenceObjects, which works works in studio mode. but if i'm reloading the objects from the persistent sequence and listen to subscribe to onValuesChange on these objects, the event is emmited once, and neveer again.
Maybe somebody has an idea what could make this work. Here some code ->
//resolving the old sequence objects
const obj: ISheetObject<EditorElementProps> = sheet.object(curDef.id, EditorElementDefaultPropeties);
//reinitialzing the linked component
if (curDef.type === 'image') {
return <Image
id={curDef.id}
key={'c' + curDef.id}
sheet={curDef.sheet}
payload={curDef.payload}
selectedObject={curDef.selectedObject}
rotation={0}
CurState={null}
obj={obj}/>;
}
//linking
const [style, setSyle] = useState<EditorElementStyle>(obj.value);
//subscribing to value change
useLayoutEffect(() => {
const unsubscribeFromChanges = curState.childObj.onValuesChange((newValues) => {
setSyle(newValues);
Object.assign(moveable.props, [moveable.props, {left: newValues.x}]);
moveable.updateRect();
});
}, []);
state.json -> https://gist.github.com/my5t3ry/c060d339bc7e13a29fc9fd65d776e80e#file-state-json
thank you : )
Hey! And thanks for making this awesome framework ๐๐
As of now, sequencing of string literals does not seem to be supported. It would be nice to have the option to sequence between the given values to the string literal.
Consider the following example:
const dinoStates = ['idle', 'scared', 'run'];
const Dino = ({ sheet }) => {
const obj = sheet.object('Dino', {
y: t.number(0),
stateIndex: t.number(0, { range: [0, dinoStates.length], nudgeMultiplier: 1 }),
});
const [dinoState, setDinoState] = useState({
y: 0,
state: 'idle',
});
useLayoutEffect(() => {
return obj.onValuesChange(({ y, stateIndex }) => {
setDinoState({
y,
state: y < 0 ? 'jump' : dinoStates[Math.round(stateIndex)],
});
});
}, [obj]);
// ... etc ...
Instead of relying on the stateIndex
above, if sequencing was supported, I could simplify the example above as:
const Dino = ({ sheet }) => {
const obj = sheet.object('Dino', {
y: t.number(0),
// ๐ explicit mapping of state as a stringLiteral type, with given values (instead of a "stateIndex")
state: t.stringLiteral('idle', { idle: 'Idle', run: 'Run', jump: 'Jump', scared: 'Scared' }),
});
const [dinoState, setDinoState] = useState({
y: 0,
state: 'idle',
});
useLayoutEffect(() => {
return obj.onValuesChange(({ y, state}) => {
setDinoState({
y,
state: y < 0 ? 'jump' : state, // ๐ no need for a lookup based on an index
});
});
}, [obj]);
// ... etc ...
Since tree-shaking in different build systems is not bullet proof, there are situations where the user intends for @theatre/studio
to not be included in the bundle but it still ends up in there. We can help the user avoid this situation by emitting a warning if the studio is imported but studio.initialize()
is not called within a time period.
Thanks @RuiOrey for the report :)
So issues like #16 are less likely to happen.
Because it's cool
This has use-cases in VR/XR, among other things.
The current data server module that runs on nodejs is buggy and gets slow in big projects.
For now, we can just separate it from theatrejs and put it in another package and fix it there. The temporary fix would be to make it cache the data file and not read it from disk every time the client requests to read/update data.
That'll probably be enough for theatrejs-0.1
, and for later releases we can focus on creating a real data structure for timeline data.
Hi,
the link to demo, links to demo of griddify.
Mentioned on, and probably related to #19
When using shift + scroll
in the sequence editor of the studio, the sequence pans left/right based on the scroll direction.
After scrolling (in either the keyframes-window or easing-window), the windows and scrollbar is out of sync:
It would be nice to have a way to change the gain for sequences with attached audio.
Possible solution already sketched by @AriaMinaei on discord.
I'll add steps to reproduce if I don't find a solution in time. But here is a capture:
Opening the studio requires pressing different keys (alt + '
on a Norwegian layout), depending on which keyboard layout is used.
There should be a unified way of opening the studio, that is independent of the keyboard layout.
The issue lies here: https://github.com/AriaMinaei/theatre/blob/main/theatre/studio/src/UIRoot/useKeyboardShortcuts.ts#L47
Would replacing e.code === 'Backslash'
with e.code === "'"
solve this issue for all layouts?
First of all, the theatre/examples/dom-cra/src/index.js
doesnt have a import app statement which render an error, I'm wondering if this example has been tested ever. And here is errors after correcting the issue:
Error: t.compound() expects an object, like: {x: 10}. null given.
sanitizeCompoundProps
src/propTypes/internals.ts:87
84 | const sanitizedProps: IValidCompoundProps = {}
85 | if (process.env.NODE_ENV !== 'production') {
86 | if (typeof props !== 'object' || !props) {
> 87 | throw new InvalidArgumentError(
| ^ 88 | `t.compound() expects an object, like: {x: 10}. ${userReadableTypeOfValue(
89 | props,
90 | )} given.`,
View compiled
compound
src/propTypes/index.ts:82
79 | validateCommonOpts('t.compound(props, opts)', opts)
80 | return {
81 | type: 'compound',
> 82 | props: sanitizeCompoundProps(props),
| ^ 83 | valueType: null as $IntentionalAny,
84 | [propTypeSymbol]: 'TheatrePropType',
85 | label: opts?.label,
View compiled
TheatreSheet.object
src/sheets/TheatreSheet.ts:121
118 |
119 | return existingObject.publicApi as $IntentionalAny
120 | } else {
> 121 | const sanitizedConfig = compound(config)
| ^ 122 | const object = internal.createObject(
123 | sanitizedPath,
124 | nativeObject,
View compiled
Box
src/App.js:14
11 |
12 | const Box = ({id, sheet, selectedObject}) => {
13 | // This is cheap to call and always returns the same value, so no need for useMemo()
> 14 | const obj = sheet.object(id, null, boxObjectConfig)
15 |
16 | const isSelected = selectedObject === obj
17 |
Sometimes the sequence editor becomes a bit crowded so it would be nice to have an option to hide the information that the user currently does not have to see. (If this feature exists, then I'm sorry, I just couldn't find it. ๐ )
Maybe clicking on the caret next to the name of the object could hide its properties? Here's a rough sketch about what I have in mind (the poperties of the first item, left arm
is collapsed on the picture):
The idea comes from blender, originally saw it in this tweet.
Should go in the /contributing
folder.
Hi, thanks for the amazing library, it is being ultra useful.
I'm facing an issue:
Was able to circumvent this by @AriaMinaei advice of dragging the lower scrollbar to scale and for now is good to go for me.
But anyway here is the bug report.
Thanks!
Most likely a problem with the way Scrolla
is utilized by components/timelineBoxScrollableArea/View
.
To reproduce: Simply zoom a few times in the timeline, and then drag to scroll. Everything seems to skip about 200px to the right.
On my current three.js project I've noticed a drastic drop in FPS when closing the studio UI.
I'm experimenting the same poor performance using a built version without loading the studio.
Here is a short video showing the FPS drop when closing the UI and the FPS rising again after opening it.
I assumed it may be something related to my project so I tried to recreate the issue in a minimal reproduction example.
I forked a previous theater.js example and made this
https://codesandbox.io/s/theatre-js-0-4-7-perf-difference-with-without-studio-pgudj?file=/src/index.js
You'll notice that if you open the UI, the animation will run better, the 4000ms setInterval run correctly etc while when the studio is closed the animation is less smooth, the setInterval doesn't seem to trigger anymore etc
On my project I'm not even able to run the performance debug tool when I close the studio UI.
I'm not sure where to look at or what other informations I could give to figure out where this is coming from.
Let me know if you have questions / need additional informations.
edit : here I have the same issue and I removed everything related to @theatre/studio
https://codesandbox.io/s/theatre-js-0-4-7-perf-difference-when-no-studio-sjgob?file=/src/index.js
edit2 : I can reproduce it with latest Chrome, Firefox, Edge on windows 10
Chrome version 96.0.4664.110 (Build officiel) (64 bits)
Edge Version 96.0.1054.62 (Official build) (64-bit)
Firefox Version 95.0.2
Relevant discussion here.
Summary: Expose changes to the playback state of a sequence, including changes to its position, and its playing/paused state. This allows creating a custom UI for scrubbing through the timeline, play/pausing the animation, etc.
API sketch:
import {onChange} from '@theatre/core'
onChange(sequence.props.position, (newPos) => {console.log('pos: ' + newPos)})
sequence.position = 10 // logs "pos: 10"
import {onChange} from '@theatre/core'
onChange(sequence.props.playState, (playState) => {console.log(playState)})
sequence.play() // logs {state: 'playing'}
// 10s later, logs {state: 'paused'}
Based off of @mrdoob's project Frame.js there is a way to render out <canvas />
elements in the browser. It could be nice to add this same render functionality to Theatre.js. FFMPEG is loaded here and I think it can also be loaded as an ES6 module. The render logic can be found here.
I've actually already rigged this up in my own personal project. If you have an idea of where or how this could be implemented, I'd be happy to contribute and make a PR for it.
Awesome project!
It would be great to be able to copy and paste keyframes, since it's a feature that I use quite a lot when I create loops (and some other times too).
UX-wise the easiest solution might be adding new items (Copy Keyframe
, Paste Keyframe
) to the context menu that appears when the user right clicks on a keyframe in the sequence editor (right now ("@theatre/studio": "0.4.7"
) it's just contains one item: Delete Keyframe
).
Because everyone is asking for it :)
Users can implement this by themselves, but having a ready-made solution would make things easier.
If I try to use theatre on NextJS I randomly get following error:
Error [ERR_REQUIRE_ESM]: require() of ES Module /.../node_modules/lodash-es/get.js from /.../node_modules/@theatre/dataverse/dist/index.js not supported.
Instead change the require of get.js in /.../node_modules/@theatre/dataverse/dist/index.js to a dynamic import() which is available in all CommonJS modules.
The error happened to other developers in my company, and with a different setup of NextJS.
If I understand right, lodash-es is an ES module library and theatre output is a CommonJS build. So there is a clash between commonjs and esm?
I suppose a solution could be to use type="module"
instead of type="commonjs"
? Or change the configuration of the compiler to generates dynamic import() instead of require() ?
Is there any reason why you chose CommonJS instead of an ESM build?
FYI we use lodash-es as a dependency in our project
Could you also put few notes on how to use use/run theaterjs?
Feature request based on this thread.
The default easing between two keyframes is by default set to ease-in-out
after inserting a new keyframe. This is fine for most cases, but in some cases it might be useful to provide a way to select another easing between to keyframes, like linear
.
E.g. when right-clicking the easing-curve between 2 keyframes, it would be nice to present a menu of predefined easing-curves to provide a quick way to set a curve without having to manually adjust the handles.
The prime example for this, is trying to get a perfectly linear curve between two keyframes. Today, if the keyframes are spread far apart, it is quite tricky to get the curve perfectly linear. One workaround is to adjust the state.json manually.
It would be nice to support a predefined set of easing-curves, like how css have a set of predefined easing functions:
linear [cubic-bezier(0.0, 0.0, 1.0, 1.0)]
ease [cubic-bezier(0.25, 0.1, 0.25, 1.0)]
ease-in [cubic-bezier(0.42, 0.0, 1.0, 1.0)]
ease-in-out [cubic-bezier(0.42, 0.0, 0.58, 1.0)]
ease-out [cubic-bezier(0.0, 0.0, 0.58, 1.0)]
Could you provide a working sandbox for this project on sandbox.io as an example for integration?
how to use theaterjs for https://www.wix.com/velo
any native support in wix community?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.