Open 9am opened 1 year ago
I'm a big fan of doing animation with codes, it's part of the reason I choose front-end to start my career years ago. In every stage of the coding, there will always be a bunch of parameters to adjust, with a control panel on the screen, we could check out the output without changing the codes now and then.
Check out the articles related to animation in this blog:
There are so many wheels in this area, I'll show you why and how I did this one.
I built a library called fire-flame which will generate a flame animation on canvas. And it supports many parameters including a 2d vector which indicates the wind force applied to the flame. To control the wind, I build this panel.
<input type="?">
for complicated value (tuple, map...).The old <input type="*">
works fine. (most of the time), As you can see, the wind is controlled by two separated <input type="range">
, but things got tricky when we need complicated data(tuple, map) out of a <input>
.
To solve this, we need to expand the types of input. Make new
<input>
element to our needs, like<input type="vector2d">
for the wind in fire-flame.
<input>
needs transcoding.The input.value
is confusing sometimes, for example, most of it's a string
, but for range
or number
we probably need a number
. But for checkbox
, input.value
doesn't work, instead input.checked
is the right way.
To solve this, we'd better implement our version of
<input>
, and involveTypeScript
to make the types right.
Even if we add a whole bunch of new <input>
, we can not include all possible data structures that the developers need. It's better to offer a way to compose and shape the value with the simple elements we offer.
To solve this, we need a logical element that doesn't hold value, it collects values from the children instead. It works like a
group
of values, so it's a recursive idea. We'll have two kinds of<input>
:<input-item>
and<input-group>
. And to shape the value of<input-group>
, we'll support attributes likedata-type=(array|object|...)
.
If we use <input>
directly, the style can be tricky to override, since every browser has its implementation and pseudo-element naming. And for some deeper customization, we can not do, for example, a <input type="range">
in a knob shape. Even with the new <input>
we defined, we still need to consider the style customization to make the lib more versatile.
To solve this, we can use CSS Custom Properties and part from custom elements to expose the ability to customize the style to developers. Throw some pre-defined themes with the lib maybe :)
All right, the lib will be like this:
<input-*>
to offer the basic UI of different types of value.<input-*>
with <ctrl-*>
, add name
, label
, detail
.<ctrl-group>
to hold <ctrl-*>
, collect values from the children.<ctrl-group name="g1" data-type="map">
<ctrl-text name="text">text:</ctrl-text>
<ctrl-group name="g2" data-type="array">
<ctrl-color>color:</ctrl-color>
<ctrl-switch>switch:</ctrl-switch>
</ctrl-group>
</ctrl-group>
document.querySelector('ctrl-group').value
/*
* {
* g1: '', // ctrl-text
* g2: [
* '#000000', // ctrl-color
* false, // ctrl-switch
* ]
* }
*/
npm install @9am/ctrl-panel
Element | Screenshot | Varient | Description | Live Demo |
---|---|---|---|---|
ctrl-panel | ------- | ------- | The root element. | demo |
ctrl-group | ------- | ------- | Group ctrl-* together to shape the value. | demo |
ctrl-slider | ![]() |
![]() |
A numblic slider. | demo |
ctrl-clamp | ![]() |
![]() |
Select a tuple low-high value. | demo |
ctrl-switch | ![]() |
![]() |
A ON/OFF switch. | demo |
ctrl-radio | ![]() |
![]() |
Multiple/Single switch. | demo |
ctrl-vector | ![]() |
Select a tuple vector on a 2D surface. | demo | |
ctrl-text | ![]() |
Text input. | demo | |
ctrl-color | ![]() |
Color picker. | demo |
Well, hope you enjoy it. I'll see you next time.
@9am 🕘