Эффект плавно меняющихся картинок при скролле

Рейтинг: 1Ответов: 1Опубликовано: 27.04.2015

Хочу реализовать подобный эффект с картинками, как здесь http://ww1.lenta.ru/saraevo/ в Unity. Чтобы картинки двигались вверх-вниз, исчезали или появлялись при прокрутки колесика мышки или при движении пальцем по тачпаду.

Есть идея реализовать все это с помощью подобного скрипта:

using UnityEngine;
using System.Collections;
using UnityEngine.UI; 
public class img : MonoBehaviour {

    public GameObject Image;
    void Update()
    {
        if(Image.transform.position.y < (0 - Image.size/2) 
           || Image.transform.position.y > (Screen.height + Image.size/2))
            Image.SetActive(false);
        else
            Image.SetActive(true);
    }
}

Ответы

▲ 5Принят

Такой вариант будет приводить к щелчкам картинок, они не будут плавно растворяться как в примере.

Чтобы растворялось придется делать отрисовку через шейдеры с использованием Transparent, и в скрипте реализовывать анимацию Alpha у материала в момент перехода из видимой области в невидимую. Я бы сделал зону которая будет ограничивать область где видимость 100%. При входе центра объекта в зону исчезновения в зависимости от удаления от центра экрана подменял бы прозрачность в материале, и тогда бы получился эффект что чем дальше объект от зоны видимости тем больше исчезает. Если постараться можно и через градиент сделать растворение. Однако следует учитывать что использование transparent в материалах приведет к тому что тени без особых приседаний работать попросту не будут.

Вот в таком варианте у меня получилось. Скрипт накидал быстро, поэтому никакой оптимизации. Вешаем на каждую панель которая у нас будет содержать информацию в объекте Content для ScrollRect. Когда объект будет удаляться от центра Canvas( меня он был посередине экрана) то постепенно меняется цвет для каждого маскируемого объекта по альфе.

using UnityEngine;
using UnityEngine.UI;

public class EffectScroll : MonoBehaviour
{

    public Image panel = null;
    private RectTransform root = null;
    private bool isOk = false;

    // Use this for initialization
    void Start ()
    {
        if (panel == null)
            panel = GetComponent<Image>();

        isOk = panel != null;
        if (isOk)
            root = panel.rectTransform.root as RectTransform;
        isOk = isOk && (root != null);
    }

    // Update is called once per frame
    void Update () {
        if (!isOk) return;

        Color color = panel.color;
        Vector2 center = GetCenter(root);
        Vector2 center2 = GetCenter(panel.rectTransform);
        float h2 = root.sizeDelta.y/2;
        float newAlpha = 1 - Mathf.Clamp(center2.y > center.y? center2.y - center.y: center.y - center2.y ,0.0F, h2)/h2;
        if (Mathf.Abs(color.a - newAlpha) > float.Epsilon)
        {
            color.a = newAlpha;
            panel.color = color;
            MaskableGraphic[] childs = GetComponentsInChildren<MaskableGraphic>();
            foreach (MaskableGraphic child in childs)
            {
                Color newColor = child.color;
                newColor.a = newAlpha;
                child.color = newColor;
            }
        }

    }

    private Vector2 GetCenter(RectTransform transform)
    {
        Vector2 center = transform.TransformPoint(transform.rect.center);//new Vector2(transform.position.x, transform.position.y);
        return center;
    }
}

Другой вариант можно сделать постобработку на камере и если плашки отрисовываются в одной камере то брать целиком изображение и делать его исчезновение к краям.

Чтобы установить позицию скролируемой области в нужное место можно воспользоваться вот таким скриптом (вешаем его на объект со ScrollRect)

using UnityEngine;
using UnityEngine.UI;

public class ScrollStart : MonoBehaviour {

public enum AllignHorizontal
{
    None,
    Left,
    Center,
    Right
}
public enum AllignVertical
{
    None,
    Top,
    Center,
    Bottom
}

public ScrollRect main = null;
public AllignHorizontal Horizontal = AllignHorizontal.None;
public AllignVertical Vertical = AllignVertical.None;
public Text info;
// Use this for initialization
void Start ()
{
    if (main == null) main = GetComponent<ScrollRect>();
    if (main != null)
    {
        if (main.horizontal)
        {
            switch (Horizontal)
            {
                case AllignHorizontal.Left:
                    main.horizontalNormalizedPosition = 0f;
                    break;
                case AllignHorizontal.Center:
                    main.horizontalNormalizedPosition = 0.5f;
                    break;
                case AllignHorizontal.Right:
                    main.horizontalNormalizedPosition = 1f;
                    break;

            }

        }
        if (main.vertical)
        {
            switch (Vertical)
            {
                case AllignVertical.Top:
                    main.verticalNormalizedPosition = 1f;
                    break;
                case AllignVertical.Center:
                    main.verticalNormalizedPosition = 0.5f;
                    break;
                case AllignVertical.Bottom:
                    main.verticalNormalizedPosition = 0f;
                    break;

            }

        }
        main.onValueChanged.AddListener(OnValueChange);
    }
}

private void OnValueChange(Vector2 arg0)
{
    if (info != null)
    {
        info.text = arg0.ToString();
    }
}

}

Если есть необходимость синхронизовать два скрола, то следует на скролах слушать событие onValueChanged и править соответсвенно у себя verticalNormalizedPosition и horizontalNormalizedPosition в соответствии с изменениями у соседа.