木骰

UGUI:一个渐变特写的滚动框特效

一个滚动框的特写特效。中间的Item为选中的Item,给个尺寸,坐标,Alpha的特写。而两边的则渐淡掉。
思路是把Grid下的每个Item只作为一个容器,再建一个content层级用来放真正的内容。然后监听ScrollRect的onValueChange,遍历Item,根据与中心坐标的距离来调整content的缩放,坐标偏移以及Alpha值。不过需要事先设置好在目标位置上的各项指标值,然后再按照位置进行插值。效果看起来像这样:

配合之前写的CenterOnChild脚本。
工程地址:https://github.com/mutou1994/UGUI_ScrollEffect


public class ScrollRectEffect : MonoBehaviour
{
    float left_alpha = 0.6f;
    float right_alpha = 0.4f;
    float middle_alpha = 1f;
    float left_height = 150;
    float right_height = 100;
    float middle_height = -120;
    float left_scale = 0.6f;
    float right_scale = 0.3f;
    float middle_scale = 1f;
    ScrollRect scroll;
    List contents;
    Vector2 centerPoint;
    Vector2 viewPort_size;
    void Awake()
    {
        scroll = transform.GetComponentInParent();
        CacheContents();
        CalCenterPoint();
        scroll.onValueChanged.AddListener(onScroll);
    }
    void CacheContents()
    {
        if (contents == null)
            contents = new List();
        contents.Clear();
        for (int i = 0, Imax = transform.childCount; i < Imax; i++)
        {
            Transform child = transform.GetChild(i).Find("content");
            contents.Add(child);
        }
    }
    void CalCenterPoint()
    {
        viewPort_size = (scroll.transform as RectTransform).rect.size;
        Vector3 pickingPoint = Vector3.zero;
        //裁剪区域四角坐标
        Vector2 halfSize = viewPort_size / 2;
        Vector2[] Conners = new Vector2[4];
        Conners[0] = new Vector2(-halfSize.x, halfSize.y);
        Conners[1] = new Vector2(halfSize.x, halfSize.y);
        Conners[2] = new Vector2(halfSize.x, -halfSize.y);
        Conners[3] = new Vector2(-halfSize.x, -halfSize.y);
        centerPoint = (Conners[0] + Conners[2]) * 0.5f;
    }
    void onScroll(Vector2 vec)
    {
        Adjust();
    }
    void Adjust()
    {
        CalCenterPoint();
        for (int i = 0, Imax = contents.Count; i < Imax; i++)
        {
            Vector3 pos = scroll.transform.InverseTransformPoint(contents[i].position);
            if (!scroll.horizontal) pos.x = centerPoint.x;
            if (!scroll.vertical) pos.y = centerPoint.y;
            pos.z = 0;
            float dis = Vector3.Distance(centerPoint, pos);
            int direct = pos.x < centerPoint.x ? -1 : 1;
            AdjustAlpha(i, dis, direct < 0 ? left_alpha : right_alpha);
            AdjustScale(i, dis, direct < 0 ? left_scale : right_scale);
            AdjustPosition(i, dis, direct < 0 ? left_height : right_height);
        }
    }
    void AdjustScale(int index, float dis, float minVal)
    {
        float rate = 1 - (dis / (viewPort_size.x / 2f));
        float scale = Mathf.Lerp(minVal, middle_scale, rate);
        Vector3 vec = Vector3.zero;
        vec.x = vec.y = vec.z = scale;
        contents[index].localScale = vec;
    }
    void AdjustAlpha(int index, float dis, float minVal)
    {
        float rate = 1 - (dis / (viewPort_size.x / 2f));
        float alpha = Mathf.Lerp(minVal, middle_alpha, rate);
        var canvas = contents[index].GetComponent();
        canvas.alpha = alpha;
    }
    void AdjustPosition(int index, float dis, float minVal)
    {
        float height = Mathf.Lerp(minVal, middle_height, 1 - (dis / (viewPort_size.x / 2f)));
        Vector3 pos = contents[index].localPosition;
        pos.y = height;
        contents[index].localPosition = pos;
    }
}
— 于 共写了2465个字
— 文内使用到的标签:

2条回应:“UGUI:一个渐变特写的滚动框特效”

  1. Deliver说道:

    public Action onCenterCallBack;
    public Action onCenterFinshed;

    if (onCenterCallBack != null)
    onCenterCallBack.Invoke(target.gameObject);

    if (onCenterFinished != null)
    onCenterFinished.Invoke(centeredObject);

    你好,我想问一下这段回调的作用是什么?我把这些注释掉之后,感觉没什么变化。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*