Skip to content

Commit 4c2cd70

Browse files
committed
Rewrite of MojsInteractive.vue and moved all custom play functions to use Mojs Player
1 parent 2f74b36 commit 4c2cd70

File tree

6 files changed

+95
-95
lines changed

6 files changed

+95
-95
lines changed

docs/.vuepress/components/DemoExpandingCircles.vue

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,15 @@
33
<div class="mojs-interactive">
44
<slot></slot>
55
<div class="mojs-interactive__result" id="demo-expanding-circle" style="background: rgb(241, 226, 215); height: 600px">
6-
<button class="button button--icon button--control" v-on:click="playPause" :aria-label="isPlaying ? 'Pause animation' : 'Play animation'">{{isPlaying ? '⇤' : '︎︎︎▶︎'}}</button>
76
<div id="demo-expanding-circle_controller" class="mojs-interactive__controller"></div>
87
</div>
98
</div>
109
</template>
1110

1211
<script>
1312
export default {
14-
data: function () {
15-
return {
16-
isPlaying: false,
17-
prefersReducedMotion: false,
18-
}
19-
},
20-
21-
methods: {
22-
playPause: function() {
23-
if (this.isPlaying) {
24-
this.timeline.replayBackward(
25-
this.prefersReducedMotion ? 1800 : 0
26-
);
27-
} else {
28-
this.timeline.play(
29-
this.prefersReducedMotion ? 1700 : 0
30-
);
31-
}
32-
this.isPlaying = !this.isPlaying;
33-
}
34-
},
3513
3614
mounted: function () {
37-
var motionQuery = matchMedia('(prefers-reduced-motion)');
38-
const handleReduceMotionChanged = () => {
39-
this.prefersReducedMotion = motionQuery.matches;
40-
}
41-
motionQuery.addListener(handleReduceMotionChanged);
42-
handleReduceMotionChanged(); // trigger once on load to check initial value
43-
4415
import('@mojs/core').then(module => {
4516
import('@mojs/player').then(module => {
4617
@@ -174,7 +145,7 @@
174145
name: "demo-expanding-circle_controller",
175146
className: 'controller',
176147
isSaveState: false,
177-
isHidden: true,
148+
isHidden: false,
178149
});
179150
180151
});

docs/.vuepress/components/MojsCode.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ new mojs.Shape({
4141
4242
props: {
4343
id: { type: String, default: 'code_example' },
44-
controller: { type: [String, Boolean], default: false },
44+
controller: { type: [String, Boolean], default: true },
4545
height: { type: String, default: '300px' },
4646
code: { type: [String, Boolean], default: '' },
4747
dark: { type: Boolean, default: false }, // if you want the demo to be dark 🕶

docs/.vuepress/components/MojsInteractive.vue

Lines changed: 73 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,22 @@ Usage:
1010
})"
1111
/>
1212

13-
or if you wanna declare a height or a controller:
13+
With autoplay on the timeline:
14+
<MojsInteractive
15+
id="unique_id"
16+
autoplay
17+
code=
18+
"new mojs.Shape({
19+
parent: '#unique_id',
20+
shape: 'circle',
21+
radius: {20: 80},
22+
})"
23+
/>
24+
25+
or if you wanna declare a height:
1426

1527
<MojsInteractive
1628
id="unique_id"
17-
:controller=true
1829
height="200px"
1930
code=
2031
"new mojs.Shape({
@@ -24,26 +35,54 @@ or if you wanna declare a height or a controller:
2435
})"
2536
/>
2637

27-
or with no controlls at all (static animation, unless you provide a .play() function):
38+
or with no controlls (will have no animation, unless you provide a .play() function yourself):
2839

2940
<MojsInteractive
3041
id="unique_id"
31-
:playbutton=false
42+
:controller=false
3243
code=
3344
"new mojs.Shape({
3445
parent: '#unique_id',
3546
shape: 'circle',
3647
radius: {20: 80},
3748
}).play()"
3849
/>
50+
51+
If you want to show (and use) the decleration of the animation like this:
52+
53+
const bouncyCircle = new mojs.Shape({
54+
...
55+
});
56+
57+
bouncyCircle.play()
58+
59+
Then you may wanna use the global mode.
60+
The string passed in the global prop should equal the variable you declared.
61+
Note that it will be global, so make sure it's unique, and use it carefully:
62+
63+
<MojsInteractive
64+
id="bouncyCircle"
65+
autoplay
66+
global="circles"
67+
code=
68+
"const circles = new mojs.Shape({
69+
parent: '#bouncyCircle',
70+
shape: 'circle',
71+
fill: {'#F64040': '#FC46AD'},
72+
});
73+
74+
circles.play()"
75+
>
76+
</MojsInteractive>
77+
3978
*/
4079

4180
<template>
4281
<div class="mojs-interactive">
4382
<div
4483
class="mojs-interactive__code"
4584
>
46-
<prism-editor :code="code" language="js" @change="change"></prism-editor>
85+
<prism-editor :code="rawCode" language="js" @change="change"></prism-editor>
4786
<div class="buttons">
4887
<button class="button button--secondary" v-on:click="reset">Reset</button>
4988
<button class="button" v-on:click="updateCode">Update code</button>
@@ -55,8 +94,6 @@ or with no controlls at all (static animation, unless you provide a .play() func
5594
:class="'mojs-interactive__result ' + (dark ? 'mojs-interactive__result--dark' : '')"
5695
:style="style"
5796
>
58-
<button class="button button--icon button--control" v-if="!controller && playbutton" v-on:click="playPause" :aria-label="isPlaying ? 'Pause animation' : 'Play animation'">{{isPlaying ? '⑊' : '︎︎︎▶︎'}}</button>
59-
<!-- <button class="button button--icon button--control" v-if="!isPlaying && !controller" v-on:click="play" aria-label="Play animation">▶︎</button> -->
6097
<div v-if="controller" :id="this.id + '_controller'" class="mojs-interactive__controller"></div>
6198
</div>
6299
</div>
@@ -73,13 +110,14 @@ or with no controlls at all (static animation, unless you provide a .play() func
73110
74111
props: {
75112
id: { type: String, default: 'code_example' }, // A unique ID
76-
controller: { type: [String, Boolean], default: false }, // this will create a mojs.Player controller
77-
playbutton: { type: Boolean, default: true }, // use this if you want a simple contoller with a play button
113+
controller: { type: [String, Boolean], default: true }, // this will create a mojs.Player controller
114+
playbutton: { type: Boolean, default: false }, // use this if you want a simple contoller with a play button
78115
height: { type: String, default: '300px' }, // add a custom height to the container, takes all CSS values
79116
code: { type: String, default: '' }, // the code (as a string) to be executed
80117
dark: { type: Boolean, default: false }, // if you want the demo to be dark 🕶
81118
notice: { type: [String, Boolean], default: false }, // to show a "click somewhere to activate animation" text
82119
autoplay: { type: Boolean, default: false }, // if your REALY want it to autoplay. Use with responsibility!
120+
global: { type: String, default: '' }
83121
},
84122
85123
data: function () {
@@ -105,48 +143,46 @@ or with no controlls at all (static animation, unless you provide a .play() func
105143
if (!window) return; // For SSR
106144
107145
// Do some cleaning
146+
var domRef = window['demo_' + this.id] || (this.global !== '' && window[this.global]);
147+
108148
// Stop, remove and delete previous instance of: demo_', this.id
109-
if (window['demo_' + this.id]) { // the mojs animation element
110-
window['demo_' + this.id].stop();
111-
window['demo_' + this.id].el.remove(); // remove the DOM node
112-
delete window['demo_' + this.id];
149+
if (domRef && domRef.stop) { // the mojs animation element
150+
domRef.stop();
151+
domRef.el.remove(); // remove the DOM node
113152
}
114153
// Remove and delete previous instance of player: mojsPlayer_', this.id
115154
if (window['mojsPlayer_' + this.id]) { // the mojs player element
116155
window['mojsPlayer_' + this.id].el.remove(); // remove the DOM node
117156
delete window['mojsPlayer_' + this.id];
118157
}
119158
159+
// Normalize variable declaration and moves them to the windows object instead
160+
// Then runs the code using new Function()
161+
if (this.global !== '') {
162+
let normalizedCode = code.replaceAll("const " + this.global, "window." + this.global);
163+
normalizedCode = normalizedCode.replaceAll("var " + this.global, "window." + this.global);
164+
normalizedCode = normalizedCode.replaceAll("let " + this.global, "window." + this.global);
165+
166+
new Function(normalizedCode)();
167+
} else {
120168
// Creating a global window object from a provided mojs object (code), and play it.
121-
const func = new Function('window["demo_' + this.id + '"] = ' + code);
122-
try {
123-
func();
124-
if (!this.controller && this.playbutton) {
125-
this.timeline = new mojs.Timeline({
126-
onPlaybackComplete: () => {
127-
this.isPlaying = false;
128-
}
129-
})
130-
.add(
131-
window['demo_' + this.id]
132-
);
133-
// Autoplay the timeline when we press the "Update code" button
134-
if (play) {
135-
this.timeline.play();
136-
this.isPlaying = true;
137-
}
169+
170+
const func = new Function('window["demo_' + this.id + '"] = ' + code);
171+
try {
172+
func();
173+
}
174+
catch(error) {
175+
console.error('Woops, please check your code for errors.', error)
138176
}
139177
}
140-
catch(error) {
141-
console.error('Woops, please check your code for errors.', error)
142-
}
143-
178+
144179
// Set the prop :controller=true to include a mojs player
145-
if (this.controller && window['demo_' + this.id]) {
180+
domRef = window['demo_' + this.id] || (this.global !== '' && window[this.global]);
181+
if (this.controller && domRef) {
146182
const parentDOM = document.getElementById(this.id + '_controller');
147183
// Create a global mojs player instance
148184
window['mojsPlayer_' + this.id] = new MojsPlayer({
149-
add: window['demo_' + this.id],
185+
add: domRef,
150186
parent: parentDOM,
151187
className: 'controller',
152188
isSaveState: false,
@@ -163,14 +199,14 @@ or with no controlls at all (static animation, unless you provide a .play() func
163199
164200
reset: function() {
165201
this.handleCode(this.code);
202+
this.rawCode = this.code;
166203
},
167204
168205
playPause: function() {
169206
if (this.isPlaying) {
170207
this.timeline.pause();
171208
} else {
172209
this.timeline.play();
173-
174210
}
175211
this.isPlaying = !this.isPlaying;
176212
},

docs/.vuepress/styles/index.styl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,6 @@ blockquote {
195195
.mojs-interactive__result {
196196
position: relative;
197197
}
198-
.mojs-interactive__result .button--control {
199-
position: absolute;
200-
bottom: 0;
201-
left: 0; // keep it to the left to prevent colliding with MojsPlayer expander
202-
z-index: 100;
203-
}
204198
.mojs-interactive__result {
205199
background: #f1e2d7;
206200
width: 100%;

docs/tutorials/getting-started.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414

1515

1616
<MojsInteractive
17-
id="bouncy_circle"
18-
:controller=true
17+
id="bouncyCircle"
18+
autoplay
19+
global="bouncyCircle"
1920
code=
20-
"new mojs.Shape({
21-
parent: '#bouncy_circle',
21+
"const bouncyCircle = new mojs.Shape({
22+
parent: '#bouncyCircle',
2223
shape: 'circle',
2324
fill: {'#F64040': '#FC46AD'},
2425
radius: {20: 80},
@@ -27,7 +28,9 @@
2728
isShowStart: true,
2829
easing: 'elastic.inout',
2930
repeat: 1,
30-
})"
31+
});
32+
33+
bouncyCircle.play()"
3134
>
3235
</MojsInteractive>
3336
@@ -39,9 +42,11 @@ Or maybe a loading animation?
3942

4043
<MojsInteractive
4144
id="spinner"
45+
autoplay
4246
height="200px"
47+
global="spinner"
4348
code=
44-
"new mojs.Shape({
49+
"const spinner = new mojs.Shape({
4550
parent: '#spinner',
4651
shape: 'circle',
4752
stroke: '#FC46AD',
@@ -62,10 +67,9 @@ Or maybe a loading animation?
6267
strokeDashoffset: {'-125': '-250'},
6368
duration: 3000,
6469
easing: 'cubic.out',
65-
onComplete () {
66-
this.replay(0); // create an infinite loop
67-
}
68-
})"
70+
});
71+
72+
spinner.play();"
6973
>
7074
</MojsInteractive>
7175

0 commit comments

Comments
 (0)