Skip to content

Commit 105e302

Browse files
committed
feat: add Rotations animations examples
1 parent d73a10d commit 105e302

File tree

4 files changed

+226
-6
lines changed

4 files changed

+226
-6
lines changed

docs/.vitepress/components/AnimationForm.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
{ label: 'delay' },
5757
{ label: 'staggerDelay' },
5858
{ label: 'blur' },
59+
{ label: 'angle' },
5960
{ label: 'easing' },
6061
{ label: 'maintainSpace', type: 'checkbox' },
6162
{

docs/.vitepress/components/Example.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@
173173
/>
174174
175175
<section>
176+
<slot />
176177
<CodeSnippet
177178
v-if="codeSnippet"
178179
:key="codeSnippetKey"
@@ -182,7 +183,6 @@
182183
:langs="codeSnippet.langs"
183184
:lang="codeSnippet.lang"
184185
/>
185-
<slot />
186186
</section>
187187
</Container>
188188
</template>

docs/examples/examples.json

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,62 @@
9999
"text": "The 'staggerDelay', 'delay' and 'duration' options can either be specified as a number, representing the total time in milliseconds, or as a string. If passed as a string, it should contain the time unit: 's' for second, or 'ms' for milliseconds, exactly as you would use in the CSS 'animation-delay' property, for example."
100100
}
101101
]
102+
},
103+
"rotations": {
104+
"btnList": [
105+
{
106+
"text": [
107+
"Rotate Right CCW",
108+
"Rotate Up"
109+
],
110+
"class": "rotateRightCCW--btn",
111+
"targetSelector": ".example__rotate"
112+
},
113+
{
114+
"text": [
115+
"Rotate Left CCW",
116+
"Rotate Up"
117+
],
118+
"class": "rotateLeftCCW--btn",
119+
"targetSelector": ".example__rotate"
120+
},
121+
{
122+
"text": [
123+
"Rotate Down",
124+
"Rotate Up"
125+
],
126+
"class": "rotateDown--btn",
127+
"targetSelector": ".example__rotate"
128+
},
129+
{
130+
"text": [
131+
"Rotate Left",
132+
"Rotate Up"
133+
],
134+
"class": "rotateLeft--btn",
135+
"targetSelector": ".example__rotate"
136+
},
137+
{
138+
"text": [
139+
"Rotate Right",
140+
"Rotate Up"
141+
],
142+
"class": "rotateRight--btn",
143+
"targetSelector": ".example__rotate"
144+
}
145+
],
146+
"contentList": []
147+
},
148+
"rotate": {
149+
"btnList": [
150+
{
151+
"text": [
152+
"Rotate",
153+
"Rotate Up"
154+
],
155+
"class": "rotate--btn"
156+
}
157+
],
158+
"contentList": []
102159
}
103160
}

docs/examples/index.md

Lines changed: 167 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ aside: false
44
---
55

66
<script setup>
7-
import { onMounted } from 'vue';
7+
import { onMounted, ref } from 'vue';
88
import Example from '../.vitepress/components/Example.vue'
99
import CodeSnippet from '../.vitepress/components/CodeSnippet.vue'
1010
import examples from './examples.json'
@@ -17,7 +17,7 @@ aside: false
1717
const btn = document.querySelector(`.${btnSelector}`)
1818
const btnText = btnList[idx].text;
1919

20-
btn.innerText = btn.innerText === btnText[0] ? btnText[1] : btnText[0];
20+
btn.innerText = btn.innerText === btnText[0] ? btnText[1] ?? btnText[0] : btnText[0];
2121
}
2222

2323
function toggleBtnHandler(animationName) {
@@ -79,6 +79,33 @@ aside: false
7979
})
8080
}
8181

82+
function rotationAnimations() {
83+
['rotateRightCCW', 'rotateLeftCCW', 'rotateDown', 'rotateLeft', 'rotateRight'].forEach((animation, i) => {
84+
jsCssAnimations.init[animation]({
85+
trigger: `.${ examples.rotations.btnList[i].class }`,
86+
targetSelector: `.example__rotate`,
87+
complete: () => {
88+
toggleBtnHandler('rotations')
89+
}
90+
});
91+
})
92+
}
93+
94+
const angleRef = ref(0);
95+
const customRotateOpts = {
96+
angle: 155
97+
}
98+
function customRotationAnimation(angle) {
99+
jsCssAnimations.init.rotate({
100+
trigger: '.rotate--btn',
101+
targetSelector: '.example__custom-rotate',
102+
...customRotateOpts,
103+
complete: () => {
104+
toggleBtnHandler('rotate')
105+
}
106+
})
107+
}
108+
82109
const validateAnimationFormField = {
83110
timePropertyValidation: val => val.match(/^(\d+|\d+\.\d+)(ms|s)?$/),
84111
blur: val => val.match(/^(\d+|\d+\.\d+)(px|rem|em)$/),
@@ -102,7 +129,8 @@ aside: false
102129
delay: '0ms',
103130
staggerDelay: '0ms',
104131
easing: 'cubic-bezier(0.455, 0.03, 0.515, 0.955)',
105-
blur: '0.5px'
132+
blur: '0.5px',
133+
angle: '0deg'
106134
}
107135

108136
if (opts.maintainSpace) opts.dimensionsTransition = false;
@@ -116,7 +144,7 @@ aside: false
116144
}
117145
});
118146

119-
const animation = animName === 'slide'
147+
const animation = [ 'slide', 'rotations'].includes(animName)
120148
? (triggerSelector.replace('--btn','')
121149
.replace(/-(\w)/,(l) => l.toUpperCase()).replace(/[-\.]/g,''))
122150
: animName;
@@ -219,5 +247,139 @@ code: `jsCssAnimations.init.collapse({
219247
highlight: [4]
220248
}"/>
221249

222-
<style>
250+
<Example
251+
:animation-api="animationApi"
252+
:animation-fn="rotationAnimations"
253+
:animation-name="'rotations'"
254+
:title="'Rotate'"
255+
:btn-list="examples.rotations.btnList"
256+
:content-list="examples.rotations.contentList"
257+
:anim-opts="{}"
258+
:fields-list="['duration', 'delay', 'easing', 'transfOrigin']"
259+
@reset-animation="(opts) => {resetAnimation('rotations', opts)}"
260+
:animation-form-validation="validateAnimationFormField"
261+
:code-snippet="{
262+
code: `jsCssAnimations.init.rotateRightCCW({
263+
trigger: '.rotateRightCCW--btn',
264+
targetSelector: '.example__rotate',
265+
});
266+
jsCssAnimations.init.rotateLeftCCW({
267+
trigger: '.rotateLeftCCW--btn',
268+
targetSelector: '.example__rotate',
269+
});
270+
jsCssAnimations.init.rotateDown({
271+
trigger: '.rotateDown--btn',
272+
targetSelector: '.example__rotate',
273+
});
274+
jsCssAnimations.init.rotateLeft({
275+
trigger: '.rotateLeft--btn',
276+
targetSelector: '.example__rotate',
277+
});
278+
jsCssAnimations.init.rotateRight({
279+
trigger: '.rotateRight--btn',
280+
targetSelector: '.example__rotate',
281+
});
282+
`}">
283+
284+
<div class="rotation-example--wrapper">
285+
286+
<div class="example__rotate rotation-area">
287+
<p class="rotation-area--text"></p>
288+
</div>
289+
290+
### Predefined Rotations
291+
292+
A set of predefined rotation animations is available to choose from:
293+
294+
- **rotateUp**: will always bring the element to its original position by setting rotation angle to _0 degrees_.
295+
- **rotateDown**: rotation angle will be set to _180 degrees_.
296+
- **rotateLeft**: _270 degrees_.
297+
- **rotateRight**: _90 degrees_.
298+
299+
### Counter Clockwise
300+
301+
There's also a set of predefined counter clockwise rotations:
302+
303+
- **rotateDownCCW**: rotation angle will be set to _-180 degrees_.
304+
- **rotateLeftCCW**: _-90 degrees_.
305+
- **rotateRightCCW**: _-180 degrees_.
306+
307+
::: tip
308+
_Notice that when toggling back up from any rotation, the element will rotate in the opposite direction of the initial rotation. For example: when using **rotateLeftCCW** to rotate an element by clicking a button, the first time the button is clicked the element will rotate **-90 degrees** (counter clockwise), then, in the next button click, the element will toggle back up by rotating clockwise back to zero degrees._
309+
:::
310+
311+
</div>
312+
</Example>
313+
314+
<Example
315+
:animation-api="animationApi"
316+
:animation-fn="customRotationAnimation"
317+
:animation-name="'rotate'"
318+
:title="'Custom Rotation'"
319+
:btn-list="examples.rotate.btnList"
320+
:content-list="examples.rotate.contentList"
321+
:anim-opts="{}"
322+
:fields-list="['duration', 'delay', 'angle', 'easing', 'transfOrigin']"
323+
@reset-animation="(opts) => {resetAnimation('rotate', opts)}"
324+
:animation-form-validation="validateAnimationFormField"
325+
:code-snippet="{
326+
code: `jsCssAnimations.init.rotate({
327+
trigger: '.rotate--btn',
328+
targetSelector: '.example__rotate',
329+
angle: 155
330+
});
331+
`
332+
}">
333+
334+
<div class="rotation-example--wrapper">
335+
<div class="example__custom-rotate rotation-area">
336+
<p class="rotation-area--text">↑</p>
337+
</div>
338+
</div>
339+
340+
</Example>
341+
342+
<style scoped>
343+
.rotation-example--wrapper {
344+
text-align: center;
345+
}
346+
347+
.rotation-example--wrapper ul {
348+
text-align: left;
349+
}
350+
351+
.rotation-area {
352+
width: 5rem;
353+
height: 5rem;
354+
background-color: darkolivegreen;
355+
margin: 1rem auto;
356+
padding-top: 0.25em;
357+
border-radius: 50%;
358+
}
359+
360+
.rotation-area--text {
361+
margin: 0;
362+
font-size: 2rem;
363+
color: beige;
364+
text-align: center;
365+
}
366+
367+
input {
368+
width: 3rem;
369+
appearance: listbox;
370+
-webkit-appearance: listbox;
371+
text-align: center;
372+
border: 1px solid var(--vp-c-gray-dark-1);
373+
border-radius: 4px;
374+
padding: 0.2em 0.6em;
375+
margin-top: 10px;
376+
background-color: var(--vp-c-bg);
377+
transition: background-color 0.5s;
378+
touch-action: manipulation;
379+
}
380+
381+
input:focus,
382+
input:hover {
383+
border: 1px solid var(--vp-c-green-lighter);
384+
}
223385
</style>

0 commit comments

Comments
 (0)