原文章:https://blog.csdn.net/lyh916/article/details/46984789
效果图:
使用的是UGUI和DOTween
其中比较关键的是循环滑动和层次排序:
1.循环滑动:这里先假设显示五张图片,分别标记为0,1,2,3,4,那么当向左滑动时,序列就变为1,2,3,4,0,这里先保存4的位置,然后从4开始,4的位置和大小向3渐变,3的位置和大小向2渐变,2的位置和大小向1渐变,1的位置和大小向0渐变,0的位置直接变为原来保存的4的位置。也就是说,当向左滑动时,最左端的那张图片特殊处理,其余的向左推进;当向右滑动时,最右端的那张图片特殊处理,其余的向右推进。
2.层次排序:由于使用的是UGUI,UI的排序跟在Hierarchy的位置有关。如果图片缩放得越小,就认为它越远离屏幕,因此就越靠前,会被后面的图片遮住。注意的是在缩放动画播放时,localScale是不确定的,因此要直接将当前位置的下一个位置的localScale传入,从而计算图片的"深度"。还有就是使用SetSiblingIndex时要完全确定好所有图片的排序。
-
using UnityEngine;
-
using System.Collections.Generic;
-
using DG.Tweening;
-
-
public
class
ScrollView :
MonoBehaviour {
-
-
public
int xOffset =
1;
//x轴偏移
-
public
int yOffset =
0;
//y轴偏移
-
public
float scale =
0.8f;
//缩放倍数
-
public
float time =
0.5f;
//偏移与缩放动画的播放时间
-
-
private
int left;
//最左端的编号
-
private
int right;
//最右端的编号
-
public
int itemAmount =
5;
//展示的图片数
-
public Vector3 middlePos;
//最中间的位置
-
-
public GameObject itemPrefab;
-
private GameObject canvas;
-
private GameObject[] sortArray;
-
private List<GameObject> list =
new List<GameObject>();
-
-
private void InstantiateItem(Vector3 pos,float scale)
-
{
-
GameObject go = Instantiate(itemPrefab)
as GameObject;
-
go.transform.SetParent(canvas.transform);
-
go.transform.localPosition = pos;
-
go.transform.localScale *= scale;
-
-
InsertToSortArray(go, go.transform.localScale.x);
-
list.Add(go);
-
}
-
-
public void Init()
-
{
-
left =
0;
-
right = itemAmount -
1;
-
canvas = GameObject.Find(
"Canvas");
-
sortArray =
new GameObject[itemAmount];
-
-
int oneSideAmount = (itemAmount -
1) /
2;
-
-
for(
int i = oneSideAmount;i >=
1;i--)
-
{
-
Vector3 pos = middlePos +
new Vector3(i * xOffset,i * yOffset,
0) *
-1;
-
InstantiateItem(pos,Mathf.Pow(scale,i));
-
}
-
-
InstantiateItem(middlePos,
1);
-
-
for(
int i =
1;i <= oneSideAmount;i++)
-
{
-
Vector3 pos = middlePos +
new Vector3(i * xOffset,i * yOffset,
0);
-
InstantiateItem(pos,Mathf.Pow(scale,i));
-
}
-
-
Sort();
-
}
-
-
/// <summary>
-
/// 根据缩放倍数计算深度
-
/// </summary>
-
/// <param name="scaleNum"></param>
-
/// <returns></returns>
-
private int CalculateDepth(float scaleNum)
-
{
-
float num =
0;
-
int i =
0;
-
while (
true)
-
{
-
num = Mathf.Pow(scale, i);
-
if (num != scaleNum) i++;
-
else
break;
-
}
-
return i;
-
}
-
-
/// <summary>
-
/// 插入到排序数组中,数组序号越低,则越远离屏幕
-
/// </summary>
-
/// <param name="go"></param>
-
/// <param name="localScaleX"></param>
-
private void InsertToSortArray(GameObject go, float localScaleX)
-
{
-
int depth = CalculateDepth(localScaleX);
-
depth = itemAmount /
2 - depth;
-
-
if (depth == itemAmount /
2)
-
sortArray[depth *
2] = go;
-
else
if (sortArray[depth] ==
null)
-
sortArray[depth] = go;
-
else
-
sortArray[depth + itemAmount /
2] = go;
-
}
-
-
private void Sort()
-
{
-
for (
int i =
0; i < itemAmount; i++)
-
{
-
sortArray[i].transform.SetSiblingIndex(i);
-
}
-
sortArray =
new GameObject[itemAmount];
-
}
-
-
public void Move(int direction)
-
{
-
if(direction ==
-1)
//向左滑动
-
{
-
int startIndex = left;
-
int lastIndex = right;
-
Vector3 lastPos = list[lastIndex].transform.position;
-
-
InsertToSortArray(list[startIndex], list[startIndex].transform.localScale.x);
-
-
for (
int i =
0; i < itemAmount -
1;i++ )
-
{
-
int index = (lastIndex - i + itemAmount) % itemAmount;
-
int preIndex = (index -
1 + itemAmount) % itemAmount;
-
list[index].transform.DOMove(list[preIndex].transform.position,time);
-
list[index].transform.DOScale(list[preIndex].transform.localScale,time);
-
-
InsertToSortArray(list[index], list[preIndex].transform.localScale.x);
-
}
-
-
list[startIndex].transform.DOMove(lastPos,time);
-
-
left = (left +
1) % itemAmount;
-
right = (right +
1) % itemAmount;
-
}
-
else
if (direction ==
1)
//向右滑动
-
{
-
int startIndex = right;
-
int lastIndex = left;
-
Vector3 lastPos = list[lastIndex].transform.position;
-
-
InsertToSortArray(list[startIndex], list[startIndex].transform.localScale.x);
-
-
for (
int i =
0; i < itemAmount -
1; i++)
-
{
-
int index = (lastIndex + i + itemAmount) % itemAmount;
-
int preIndex = (index +
1 + itemAmount) % itemAmount;
-
list[index].transform.DOMove(list[preIndex].transform.position, time);
-
list[index].transform.DOScale(list[preIndex].transform.localScale, time);
-
-
InsertToSortArray(list[index], list[preIndex].transform.localScale.x);
-
}
-
-
list[startIndex].transform.DOMove(lastPos, time);
-
-
left = (left -
1 + itemAmount) % itemAmount;
-
right = (right -
1 + itemAmount) % itemAmount;
-
}
-
-
Sort();
-
}
-
}
不足之处:
1.只适用于展示图片数为奇数的场合
2.等等...