LoginSignup
26
24

More than 5 years have passed since last update.

uGUI スクロールビューを分割毎にスナップする

Last updated at Posted at 2015-05-23

放置でしたが、最新のUnityに合わせて、更新しました。

ScrollRectSnap

ScrollRectにはページング機能やスナップ機能は付いてなかったので、デザイナーなりに考えた。

ScrollRectSnap.gif

  • スクロール位置はnormalizedPositionから0f〜1fで取得/入力できるので、各ページ位置は以下で取得。

    ページ数/ページ総数

  • スクロール位置と各ページ間の中間地点比較して、越えていたら次ページ位置をスナップ位置に指定

    ページ間の中間地点
    (2*ページ数-1)/((ページ総数-1)*2)

  • スナップモーションはVector2.Lerpで。

スクリプト

ScrollRectSnap.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class ScrollRectSnap : ScrollRect {
    public int horizontalPages = 3; // horizontalの分割数
    public int verticalPages = 3;  // verticalの分割数

    [SerializeField] private float smooth = 10f;  // スナップ係数
    private Vector2 targetPosition; // スナップ先座標
    private bool isDrag = false; // フラグ

    protected override void Start(){
        base.Start ();
        normalizedPosition = content.GetComponent<RectTransform> ().pivot;
        targetPosition = FindSnapPosition ();
    }

    void Update(){
        if (!isDrag && normalizedPosition != targetPosition) {
            normalizedPosition = Vector2.Lerp (normalizedPosition, targetPosition, smooth * Time.deltaTime);
        }
    }

    public override void OnBeginDrag(PointerEventData eventData){
        base.OnBeginDrag (eventData);
        isDrag = true;
    }

    public override void OnEndDrag(PointerEventData eventData){
        base.OnEndDrag (eventData);
        targetPosition = FindSnapPosition ();
        isDrag = false;
    }

    // スナップ先座標を取得する
    Vector2 FindSnapPosition(){
        float x = 0, y = 0;
        Vector2 center;

        if(horizontal){
            if(horizontalPages > 1){
                for (int page = 0; page < horizontalPages; page ++) {
                    center.x = (2f * page - 1f) / ((horizontalPages - 1f) * 2f);
                    if(horizontalNormalizedPosition >= center.x){
                        x = page / (horizontalPages - 1f);
                    }
                }
            }
        }else{
            x = horizontalNormalizedPosition;
        }

        if(vertical){
            if(verticalPages > 1){
                for (int page = 0; page < verticalPages; page ++) {
                    center.y = (2f * page - 1f) / ((verticalPages - 1f) * 2f);
                    if(verticalNormalizedPosition >= center.y){
                        y = page / (verticalPages - 1f) ;
                    }
                }
            }
        }else{
            y = verticalNormalizedPosition;
        }
        return new Vector2 (x, y);
    }
}

上記だけだと追加したpublic変数がInspectorに表示されないので、以下をAssets/Editorに追加

ScrollRectSnapEditor.cs
using UnityEngine;
using UnityEditor;

[CustomEditor( typeof(ScrollRectSnap))]
public sealed class ScrollRectSnapEditor : Editor {

    public override void OnInspectorGUI(){
        DrawDefaultInspector ();
    }
}

使い方

  • ScrollRect の代わりに上記スクリプトをコンポーネントに追加。
  • Horizontal Pages に水平方向のページ総数を入力 (Horizontal がオンになっていないと効かない)
  • Vertical Pages に垂直方向のページ数を入力 (Vertical がオンになっていないと効かない)
  • Smoothでスナップモーションを調整
26
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
24