【PlayCanvas】2Dスクリーンでスクロールバーを作る


この記事は PlayCanvas Advent Calendar 2017 の9日目の記事です。

作ったもの


以前紹介したポータルサイトで、スクロールバーを実装してみました。
動作はアクセスしていただけるとわかるかと思いますが、
位置に応じて上下、ドラッグでの位置変更等できます。
htmlのスクロールバーではなくWebGLに直接書き込んでいるため、ブラウザ設定でサイドバーを無効にしても表示されます。

なぜ作ったか

自分が使っているラップトップに搭載されたSynaptics製のタッチパッドの2本指スクロールがEdgeでは拾えなくて、ポータルサイトが動かなくなってしまったので急遽実装しました。

作り方

2D Screenエンティティを配置し、その下にImage Elementを配置します。
スクロールバー用の画像を適当に用意して、Image Elementのテクスチャにアタッチします。

エレメントのinputイベントを取得したいので、Use Inputのチェックボックスをtrueにしておきましょう。

Image Elementに以下スクリプトをアタッチします。

sidebar.js
var Sidebar = pc.createScript('sidebar');
Sidebar.attributes.add("selectColor",{type:"rgb"});
Sidebar.attributes.add("unSelectColor",{type:"rgb"});

// initialize code called once per entity
Sidebar.prototype.initialize = function() {
    this.isMousePressed = false;
    this.entity.element.on("mousedown",this._mdown,this);
    this.app.mouse.on("mousemove",this._mmove,this);
    this.app.mouse.on("mouseup",this._mup,this);
};

// update code called every frame
Sidebar.prototype.update = function(dt) {
    this.entity.element.anchor = new pc.Vec4(1,1-camera.cameraPosition,1,1-camera.cameraPosition);
    this.entity.element.pivot = new pc.Vec2(1,1-camera.cameraPosition);
    if(this.isMousePressed){
        this.entity.element.color = this.selectColor;
    }else{
        this.entity.element.color = this.unSelectColor;
    }
};

Sidebar.prototype._mdown = function(ev){
    if(ev.button === 0){
        this.isMousePressed = true;        
    }
};

Sidebar.prototype._mup = function(ev){
    this.isMousePressed = false;
};

Sidebar.prototype._mmove = function(ev){
    if(!ev.buttons[0]){
        this.isMousePressed = false;
    }
    if(this.isMousePressed){
        camera.cameraPosition = (ev.y / window.innerHeight);
    }
};

_mmove()でマウスが動いた時のイベントを取得しています、マウスが押されているときだったらcameraのポジションを変更するようにします。
またサイドバーの位置はanchor,pivotで操作し、update内で常に同期させてあげます。

initializeのイベント周りは、mousedownはエレメントからのインプット限定ですが、mouseup,mousemoveはエレメント外、canvas全体のイベントで取得します。

ポータルページではカメラのY座標に割り当てましたが、ほかのパラメータに割り当てて発展した使い方なんかもできそうですね