Mo.jsのライブラリはESモジュールとして読み込みます。ライブラリの読み込みからアニメーションの描画を行うコードは別のファイルに記述し、Oracle APEXのページにはコードを一切埋め込まないようにします。
作成したAPEXのアプリケーションは以下のように動作します。Mo.jsのプレイヤーなしのページとプレイヤーありのページを作成します。
以下より簡単に実装について紹介します。
空のAPEXアプリケーションを作成します。名前はPlay Mo.jsとしました。
ホーム・ページに、プレイヤーなしのbouncyCircleとspinnerのアニメーションを表示します。
静的コンテンツのリージョンを作成し、ソースのHTMLコードとして以下を記述します。bouncyCircleのアニメーションを描画するDIV要素になります。
<div id="bouncyCircle" class="w95p h300"></div>
<div id="spinner" class="w95p h300"></div>
静的アプリケーション・ファイルとしてapp-mojs-player.js(およびミニファイしたapp-mojs-player.min.js)を作成します。内容として以下を記述します。
ページ・プロパティのJavaScriptのファイルURLに以下を記述します。
[module]#APP_FILES#app-mojs#MIN#.js
HTMLヘッダーにimportmapを記述します。ES6モジュールを対象としたCDNサービスのesm.shを指しています。
<script type="importmap">
{
"imports": {
"@mojs/core": "https://esm.sh/@mojs/core"
}
}
</script>
静的アプリケーション・ファイルとしてapp-mojs.js(およびミニファイしたapp-mojs.min.js)を作成します。内容として以下を記述します。ほとんどMo.jsのGetting startedそのままです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import mojs from "@mojs/core"; | |
const bouncyCircle = new mojs.Shape({ | |
parent: '#bouncyCircle', | |
shape: 'circle', | |
fill: { '#F64040': '#FC46AD' }, | |
radius: { 20: 80 }, | |
duration: 2000, | |
width: 200, | |
height: 200, | |
isYoyo: true, | |
isShowStart: true, | |
easing: 'elastic.inout', | |
repeat: 3, | |
}); | |
bouncyCircle.play(); | |
const spinner = new mojs.Shape({ | |
parent: '#spinner', | |
shape: 'circle', | |
stroke: '#FC46AD', | |
strokeDasharray: '125, 125', | |
strokeDashoffset: { '0': '-125' }, | |
strokeWidth: 4, | |
fill: 'none', | |
left: '50%', | |
top: '50%', | |
rotate: { '-90': '270' }, | |
radius: 20, | |
isShowStart: true, | |
duration: 2000, | |
easing: 'back.in', | |
}) | |
.then({ | |
rotate: { '-90': '270' }, | |
strokeDashoffset: { '-125': '-250' }, | |
duration: 3000, | |
easing: 'cubic.out', | |
}); | |
spinner.play(); |
プレイヤーなしのバージョンは以上で完成です。
空白ページをページ番号2として作成し、ホーム・ページと同じく静的コンテンツのリージョンbouncyCircleとspinnerを作成します。
ページ・プロパティのJavaScriptのファイルURLに以下を記述します。
[module]#APP_FILES#app-mojs-player#MIN#.js
CSSのファイルURLに以下を記述します。
#APP_FILES#app-mojs-player#MIN#.css
HTMLヘッダーに以下を記述します。
<script type="importmap">
{
"imports": {
"@mojs/core": "https://esm.sh/@mojs/core",
"@mojs/player": "https://esm.sh/@mojs/player"
}
}
</script>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import mojs from "@mojs/core"; | |
import MojsPlayer from "@mojs/player"; | |
/* | |
* Player付きbouncyCircle | |
*/ | |
const bouncyCircleEl = document.getElementById("bouncyCircle"); | |
const bouncyCircle = new mojs.Shape({ | |
parent: bouncyCircleEl, | |
shape: 'circle', | |
fill: {'#F64040': '#FC46AD'}, | |
radius: {20: 80}, | |
duration: 2000, | |
width: 200, | |
height: 200, | |
isYoyo: true, | |
isShowStart: true, | |
easing: 'elastic.inout', | |
repeat: 3 | |
}); | |
const mojsPlayerBC = new MojsPlayer({ | |
// required | |
add: bouncyCircle, | |
parent: bouncyCircleEl, | |
// optionally | |
className: 'my-mojs-player', // class name to add to main HTMLElement | |
isSaveState: true, // determines if should preserve state on page reload | |
isPlaying: false, // playback state | |
progress: 0, // initial progress | |
isRepeat: false, // determines if it should repeat after completion | |
isBounds: false, // determines if it should have bounds | |
leftBound: 0, // left bound position [0...1] | |
rightBound: 1, // right bound position [0...1] | |
isSpeed: false, // determines if speed control should be open | |
speed: 1, // `speed` value | |
isHidden: false, // determines if the player should be hidden | |
precision: 0.1, // step size for player handle - for instance, after page reload - player should restore timeline progress - the whole timeline will be updated incrementally with the `precision` step size until the progress will be met. | |
name: 'mojs-player-bc', // name for the player - mainly used for localstorage identifier, use to distinguish between multiple local players | |
onToggleHide(isHidden) { // should be called after user taps on the hide-button (isHidden is a boolean, indicating the visibility state of the player) | |
if (isHidden) { | |
// do something when player is invisible | |
} else { | |
// do something when player is visible | |
} | |
} | |
}); | |
// bouncyCircle.play(); | |
/* | |
* Player付きspinner | |
*/ | |
const spinnerEl = document.getElementById("spinner"); | |
const spinner = new mojs.Shape({ | |
parent: spinnerEl, | |
shape: 'circle', | |
stroke: '#FC46AD', | |
strokeDasharray: '125, 125', | |
strokeDashoffset: { '0': '-125' }, | |
strokeWidth: 4, | |
fill: 'none', | |
left: '50%', | |
top: '50%', | |
rotate: { '-90': '270' }, | |
radius: 20, | |
isShowStart: true, | |
duration: 2000, | |
easing: 'back.in', | |
}) | |
.then({ | |
rotate: { '-90': '270' }, | |
strokeDashoffset: { '-125': '-250' }, | |
duration: 3000, | |
easing: 'cubic.out', | |
}); | |
const mojsPlayerSP = new MojsPlayer({ | |
// required | |
add: spinner, | |
parent: spinnerEl, | |
// optionally | |
className: 'my-mojs-player', // class name to add to main HTMLElement | |
isSaveState: true, // determines if should preserve state on page reload | |
isPlaying: false, // playback state | |
progress: 0, // initial progress | |
isRepeat: false, // determines if it should repeat after completion | |
isBounds: false, // determines if it should have bounds | |
leftBound: 0, // left bound position [0...1] | |
rightBound: 1, // right bound position [0...1] | |
isSpeed: false, // determines if speed control should be open | |
speed: 1, // `speed` value | |
isHidden: false, // determines if the player should be hidden | |
precision: 0.1, // step size for player handle - for instance, after page reload - player should restore timeline progress - the whole timeline will be updated incrementally with the `precision` step size until the progress will be met. | |
name: 'mojs-player-sp', // name for the player - mainly used for localstorage identifier, use to distinguish between multiple local players | |
onToggleHide(isHidden) { // should be called after user taps on the hide-button (isHidden is a boolean, indicating the visibility state of the player) | |
if (isHidden) { | |
// do something when player is invisible | |
} else { | |
// do something when player is visible | |
} | |
} | |
}); | |
// spinner.play(); |
Mo.jsのドキュメントからはプレイヤーの位置を指定する方法を見つけられず、コードから見つけています。MojsPlayerのインスタンスを作成する際に、parentとしてアニメーションを描画するDIV要素を指定し、classNameに指定したCSSクラス(上記のコードではmy-mojs-player)で表示位置を決めます。デフォルトでは、ウィンドウの最下部にプレイヤーが表示されます(parentの指定がdocument.bodyになる)。
プレイヤーの表示位置を定義するCSSクラスmy-mojs-playerは、app-mojs-player.cssで定義します。静的アプリケーション・ファイルとして作成します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.my-mojs-player { | |
position: absolute !important; | |
bottom: 0 !important; | |
} |
以上でアプリケーションは完成です。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/play-mojs.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完