Open mattdesl opened 5 years ago
👏 nice! I love the concept to have a minimal gui serializable as the save-seed-and-commit works.
Is this a can of worms I don't even want to get into? 😅
Love this idea @mattdesl! I've tried to use ControlKit in my environment before with loads of issues, this would be a real game changer.
Persisting to localStorage would be nice. Requesting a "reset" control to easily revert to default values without having to manually localStorage.clear()
. Additionally, would these values already persist between hot-reloads? That's been a big frustration of my previous attempts.
On the serialization, I'd love to be able to save a particular config as a snapshot. Similarly to how you can save out iterations of artwork. Could this provide you with a list of previous snapshots that you can return to in a dropdown or something?
Your approach looks promising, great work 🎉. I love the idea of the fuzzy searching, folders would be definitively nice, too.
To have custom change handlers, something like the following would be convenient from my point of view:
background: {
value: 'pink',
onChange: newValue => { /* custom code that should run on change */ }
}
Also I was wondering if it would be possible to have interconnected parameter changes (e.g. change the background color which then will effect another parameter), ... just popped into my head as a maybe nice feature for generative art 🤔.
👍 +1 for persisting localStorage, which @kellymilligan suggested
Thanks guys!
Some more questions:
onChange
event syntax so that user can specify them within the scope of their sketch function?duration
, dimensions
, animate
etc which link directly with update()
functionPossible answers for each...
If you specify { serialize: true }
in your params, then each time you export a frame, it will also export a [filename].params.json
to be associated with that artwork. This means serialize
is a reserved word you can't use in your own UI. In the case of animations, it exports a single JSON for a sequence of PNG frames.
To deserialize, you can drag and drop a JSON file onto the page...? Or maybe also specify a --param-file
in the CLI to override default params. Maybe there should also be some sort of programmatic way of doing it?
onChange
and button eventsOne tricky thing is that most of the time when you react to changes and button presses, you will need to be in the scope of your sketch. What is the syntax for that? Take for example:
const { createRandom } = require('canvas-sketch-util/math');
const settings = {
params: {
seed: 0
}
};
canvasSketch(({ params }) => {
const random = createRandom(params.seed);
// how to do random.setSeed(newSeed) with param change?
return ({ context }) => {
// render...
};
}, settings);
I'm not sure any clean way to tackle this, really. I could use ES7 decorators but I'd rather not introduce non-standard syntax. One way is just looking for { type: 'folder' }
and if found, all keys that are not reserved (keys like open
, visible
can't be used for example) will be made into UI elements:
const settings = {
params: {
circle: {
type: 'folder',
background: 'red',
lineWidth: { min: 0, max: 10, value: 3, step: 0.1 }
}
}
};
canvasSketch(({ params }) => {
console.log(params.circle.lineWidth) // 3
}, settings);
Some properties like dimensions
or duration
you will just want to 'expose' but not have to wire up yourself manually. In the case of dimensions it could be nice to have canvas-sketch
populate a drop-down with paper size presets and so forth. In that case, maybe using special type
keys.
const settings = {
params: {
// Expose a dimension selector
dimensions: { type: 'dimensions' },
duration: {
// Expose a duration slider
type: 'duration',
// In case you wanted to give a specific constraint to the loop duration
min: 1,
max: 10
}
}
};
canvasSketch(mySketch, settings);
I see you are using your own flavour of localStorage in the examples/util/controls.js
. Have you ever tried dat.GUI's gui.remember(settings.params);
which allegedly saves the current state to localStorage?
Yeah! I ended up doing a few things differently:
I would like to help with this one. I've been thinking about building a lightweight HUD library for a while as a separate module but It can be nice to make sure it works great with canvas-sketch
– we can design the API based on the needs of canvas-sketch
I'm trying to add a control panel/settings to an app I've built using the canvas-sketch and modulating orb thing @mattdesl built for his Frontend Masters course. However, it seems like canvas-sketch may be preventing my mouse events from reaching my form fields. And I've never been able to right-click to inspect the page, even before adding my control panel... is canvas-sketch preventing event bubbling somehow? If this is too off-topic, I can start a new issue or ask this question in a different venue!
Hey @onetwothreebutter do you mind starting a new issue and also providing some code samples? It shouldn’t capture mouse events by default.
I've managed to add https://github.com/dataarts/dat.gui with minimal amount of effort.
npm install dat.gui --save
Instantiate GUI
import * as dat from 'dat.gui';
const gui = new dat.GUI();
Extend settings Object with something like params
const settings = {
suffix: Random.getSeed(),
dimensions: 'A4',
orientation: 'portrait',
pixelsPerInch: 300,
params: {
myControlledVar: 10
},
Add params
to be controlled by datGui
gui.add(settings.params, 'myControlledVar', 1, 50);
Reference it inside render function returned by sketch
:
const sketch = (props) => {
return (props) => {
const { myControlledVar } = settings.params;
...
Profit
Here's an example showing basically the same thing, but also re-rendering the frame when a GUI parameter changes (fairly useful for static sketches).
https://gist.github.com/mattdesl/04ceca544e637ce1da4d2cf5200d71af
I'm working in a
feature/hud
branch to test out the idea of a built-in GUI system forcanvas-sketch
. It would be like dat.gui but a bit more opinionated, a lot more declarative, and will integrate easily with canvas-sketch as well as features like exporting/importing serialized data (for example, making prints parameters reproducible).Here is an example, no fancy styling yet:
And a video in this tweet.
It would be built with Preact to keep the
canvas-sketch
library small.Syntax
I don't want to introduce a lot of new API concepts to users, and I want it to be declarative and in line with the rest of the ethos of pure render functions. My current thought is to have something like this:
params
is passed tosettings
orupdate()
function, the sketch will be added to a global HUD panel, and the panel will be made visible if it has one or more sketches attached to it.param
prop is converted into literal values (e.g. instead of a descriptor with options, you just get the raw number value).Motivation
It won't be all that different than dat.gui, but:
--params
flag to the CLI tool to override params with a JSON fileFeatures
Should support:
Questions
time
,dimensions
,duration
etc?