The sky is the limit

Vue.js、PHP、Java、Cordova、Monacaを中心にハイブリッドアプリ開発、PWA開発など効率的なWEB、iOS、Androidアプリ開発の情報を共有します。

1-3【UI開発】OnsenUIを使った画面内スクロールの実装【ons-carousel】

1-3【UI開発】OnsenUIを使った画面内スクロールの実装【ons-carousel】

f:id:duo-taro100:20160218004611p:plain

今回は一つのタブ内での横スクロールでの画面遷移を実現するための方法。
今回のアプリでは、目標貯金金額を貯めるための期間や月々の貯蓄額などを計算するためのページでこの機能を使う。動きは以下のような感じ。

f:id:duo-taro100:20180109153120p:plain

この機能の利点としては、ユーザーがよりスムーズに自分の求めている画面に遷移できること。
スマホでの直感的な操作を取り入れるとこういった機能も必要になりそう。
OnsenUIを使えば、この実装は簡単で、

ons-carouselタグ

スクロールが必要な箇所に設置。

<ons-carousel></ons-carousel>
ons-carousel-itemタグ

スクロール対象の画面。

<ons-carousel-item></ons-carousel-item>
ons-carousel-coverタグ

スクロール時に固定で表示する画面。
常に表示したい内容をここに。

<ons-carousel-cover></ons-carousel-cover>

この3つを使えばいい。
横スクロールが必要な画面にを用意して、スクロール対象になる画面をで作成する。
どの画面を表示しているか分かりやすいように、ページネーションも実装したが、ここでやった方法は若干無理やりな感じがする。(詳細は後ほど)

■ons-carouselの例(html)

<!-- シミュレーション画面 -->
    <ons-template id="simulation.html">
        <ons-page ons-show="pctrl.title = '計算'">
            <div class="content" ng-app="myApp">
                <div class="main" ng-controller="simCtrl as sctrl">
                    <ons-carousel swipeable overscrollable auto-scroll auto-scroll-ratio="0.3" fullscreen ons-postchange="sctrl.carouselChange()" var="sim_carousel">
                    <ons-carousel-item class="carousel-items">
                        <p>1ページ目</p>
                    </ons-carousel-item>
                    <ons-carousel-item class="carousel-items">
                        <p>2ページ目</p>
                    </ons-carousel-item>
                    <ons-carousel-item class="carousel-items">
                        <p>3ページ目</p>
                    </ons-carousel-item>
                    <ons-carousel-cover>
                        <p>スクロールしてもここは固定表示される</p>
                    </ons-carousel-cover>
                </div>
            </div>
        </ons-page>
    </ons-template>

ons-carousel

今回使っているoptionは以下の通り。
説明は公式ドキュメントから引用

https://ja.onsen.io/v1/reference/ons-carousel.html

swipeable

この属性がある時、カルーセルをスワイプやドラッグで移動できるようになります。

overscrollable

この属性がある時、タッチやドラッグで端までスクロールした時に、バウンドするような効果が当たります。

auto-scroll

この属性がある時、一番近いcarosel-itemの境界まで自動的にスクロールするようになります。

auto-scroll-ratio

0.0から1.0までの値を指定します。カルーセルの要素をどれぐらいの割合までドラッグすると次の要素に自動的にスクロールするかを指定します。

→ 値が低いほどスクロールしやすくなる。ここでは0.3を指定。

fullscreen

この属性があると、absoluteポジションを使ってカルーセルが自動的に画面いっぱいに広がります。

var

このカルーセルを参照するための変数名を指定します。

→ ここでは「sim_carousel」としている。

ons-postchange

"postchange"イベントが発火された時の挙動を独自に指定できます。

→ "postchange"イベントは「現在表示しているカルーセルの要素が変わるイベント」のこと。つまり、横スクロールして、表示しているが変更されるイベントのこと。

ons-carousel-cover

どこの画面を表示しているか分かるように、ページネーションを表示するために実装。
今回は、スクロールイベントを拾って、現在表示している画面を「carouselNum」という変数で管理して、その値によって、表示するページネーションを変えるという実装にしている。ちょっと無理やりな感じがするので、スマートな実装はないか模索中。

■html
「carouselNum」の値で表示を変更。ページが少ない場合はこれでもいいかと思うが。。。

    <ons-template id="simulation.html">
        <ons-page ons-show="pctrl.title = '計算'">
            <div class="content" ng-app="myApp">
                <div class="main" ng-controller="simCtrl as sctrl">
                    <ons-carousel swipeable overscrollable auto-scroll auto-scroll-ratio="0.3" fullscreen ons-postchange="sctrl.carouselChange()" var="sim_carousel">
                    <!-- ons-carousel-item省略 -->
                    <ons-carousel-cover>
                        <div class="cover-label" ng-show="sctrl.carouselNum == 0">
                            <ons-icon icon="circle" ></ons-icon>
                            <ons-icon icon="circle-thin"></ons-icon>
                            <ons-icon icon="circle-thin"></ons-icon>
                        </div>
                        <div class="cover-label" ng-show="sctrl.carouselNum == 1">
                            <ons-icon icon="circle-thin"></ons-icon>
                            <ons-icon icon="circle" ></ons-icon>
                            <ons-icon icon="circle-thin"></ons-icon>
                        </div>
                        <div class="cover-label" ng-show="sctrl.carouselNum == 2">
                            <ons-icon icon="circle-thin"></ons-icon>
                            <ons-icon icon="circle-thin"></ons-icon>
                            <ons-icon icon="circle" ></ons-icon>
                        </div>
                    </ons-carousel-cover>
                    </ons-carousel>
                </div>
            </div>
        </ons-page>
    </ons-template>

■javascript
現在のcarouselの位置を「carouselNum」で管理。1ページ目が「0」であることに注意。
「carouselChange」でons-carouselのindexを取得して、「carouselNum」に設定する。
この値の変化をhtmlで読み取って、ページネーションの表示を切り替えている。

myApp.controller("simCtrl", function(calendarService,configService,listService,purposeService) {
    
    // carouselの位置
    this.carouselNum = 0;

    /**
     * ons-carouselのindexを取得し、carouselNumに設定します。
     */ 
    this.carouselChange = function () {
        this.carouselNum = sim_carousel.getActiveIndex();
    };

});

ons-carouselを使った実装はここまで。
ons-carouselを使うと縦スクロールができないと考えられるので、注意!
http://www.sky-limit-future.com/entry/2017/08/23/111915

ページネーションの実装をもう少しスマートにするのは今後の課題。
以上。