现在的商业项目需要的功能,本来打算在网上搜搜,但是没有发现有,所以自己花了点时间自己写了一个,实现了卡牌的循环缩放修改Alpha。
namespace UIFramework
{
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using DG.Tweening;
///
/// 卡片选择器
///
public class CardCollection : MonoBehaviour, IDragHandler, IEndDragHandler, IPointerClickHandler
{
class Card
{
public GameObject root = null;
public GameObject page = null;
public GameObject pageOn = null;
public GameObject pageOff = null;
}
///
/// 需要动态生成的模板
///
public GameObject template = null;
///
/// 模板的页签
///
public GameObject pageTemplate = null;
///
/// 相对于页签的开启预制路径
///
public string pageOn = "On";
///
/// 相对于页签的关闭预制路径
///
public string pageOff = "Off";
///
/// 每一个目标的的位置差
///
public Vector2 offset = new Vector2(100, 0);
///
/// 移动速度
///
public float moveSpeed = 0.01f;
///
/// 是否循环
///
public bool IfLoop = false;
///
/// 相邻卡片scale差值
///
public float ReduceScale = 0.2f;
///
/// 改变Alpha通道
///
public bool ChangeAlpha = true;
///
/// 改变通道
///
public bool ChangeColor = true;
///
/// 自动改变顶部
///
public bool AutoChangeTop = false;
///
/// 使用曲线
///
public bool UseCurve = false;
///
/// 尺寸曲线
///
public AnimationCurve ScaleCurve;
///
/// 位置曲线
///
public AnimationCurve PosCurve;
///
/// 关闭拖动
///
[HideInInspector]
public bool disableDrag = false;
///
/// 顶端改变事件
///
public class TopChangeEvent : UnityEvent
///
/// 顶部改变事件功能
///
public TopChangeEvent onTopChanged = new TopChangeEvent();
#region PRIVATES
bool draging = false;
float current = 0;
RectTransform top = null;
List
bool autoChangeDirRight = true;
float lastAutoChangeTime = 0f;
List
#endregion
void Awake()
{
template.SetActive(false);
}
void Start()
{
lastAutoChangeTime = Time.realtimeSinceStartup;
}
void OnEnable()
{
lastAutoChangeTime = Time.realtimeSinceStartup;
}
void Update()
{
if (draging || !AutoChangeTop || top == null)
return;
if (Time.realtimeSinceStartup - lastAutoChangeTime > 5f)
{
int top_index = int.Parse(top.name);
int to_index = top_index;
if (autoChangeDirRight)
{
if (top_index + 1 >= transform.childCount + 1)
{
to_index = top_index - 1;
autoChangeDirRight = false;
}
else
{
to_index = top_index + 1;
}
}
else
{
if (top_index - 1 <= 0)
{
to_index = top_index + 1;
autoChangeDirRight = true;
}
else
{
to_index = top_index - 1;
}
}
DOTween.To(x => current = x, current, to_index - 1, 0.2f).OnUpdate(AutoRefresh);
lastAutoChangeTime = Time.realtimeSinceStartup;
}
}
///
/// 移动卡片到顶端
///
/// Card's name
public void BringUp(string card)
{
for (int i = 0; i < cards.Count; ++i)
{
if (cards[i].root.name == card)
{
current = i;
Refresh(true);
return;
}
}
}
///
/// 设置卡片名
///
///
///
///
public Transform SetCardName(int _index, string _name)
{
if (_index >= cards.Count)
return null;
cards[_index].root.name = _name;
return cards[_index].root.transform;
}
///
/// 通过名字获取卡片
///
///
///
public Transform GetCardByName(string _name)
{
for (int i = 0; i < cards.Count; ++i)
{
if (cards[i].root.name == _name)
{
return cards[i].root.transform;
}
}
return null;
}
///
/// 移动到顶端
///
/// Offset
/// Scale
/// Animation duration.
public void Move(Vector2 offset, float scale, float duration)
{
if (top == null) return;
for (int i = 0; i < transform.childCount - 1; ++i)
{
transform.GetChild(i).gameObject.SetActive(false);
}
if (pageTemplate != null)
pageTemplate.transform.parent.gameObject.SetActive(false);
disableDrag = true;
top.DOAnchorPos(offset, duration).SetEase(Ease.Linear);
top.DOScale(scale, duration).SetEase(Ease.Linear);
}
///
/// 返回
///
public void MoveBack(float duration)
{
if (top == null) return;
top.DOAnchorPos(Vector2.zero, duration).SetEase(Ease.Linear);
top.DOScale(1, duration).SetEase(Ease.Linear).OnComplete(() =>
{
for (int i = 0; i < transform.childCount - 1; ++i) transform.GetChild(i).gameObject.SetActive(true);
if (pageTemplate != null)
pageTemplate.transform.parent.gameObject.SetActive(true);
disableDrag = false;
Refresh(true);
});
}
///
/// 插入一个新的卡片
///
/// Card name for Find.
///
public GameObject Spawn(string name)
{
GameObject obj = null;
if (cache.Count > 0)
{
obj = cache[cache.Count - 1];
cache.RemoveAt(cache.Count - 1);
}
else
{
obj = Instantiate(template);
}
obj.name = name;
obj.transform.SetParent(transform);
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one;
obj.transform.rotation = Quaternion.identity;
obj.SetActive(true);
Card card = new Card();
card.root = obj;
if (pageTemplate != null)
{
GameObject page = Instantiate(pageTemplate);
page.transform.SetParent(pageTemplate.transform.parent);
page.transform.localPosition = Vector3.zero;
page.transform.localScale = Vector3.one;
page.transform.rotation = Quaternion.identity;
page.SetActive(true);
card.page = page;
card.pageOn = page.transform.Find(pageOn).gameObject;
card.pageOff = page.transform.Find(pageOff).gameObject;
}
cards.Add(card);
//Refresh( true );
return obj;
}
///
/// 通过名字移除卡片
///
///
public void Remove(string _name)
{
for (int i = 0; i < cards.Count; ++i)
{
GameObject obj = cards[i].root;
if (obj.name == _name)
{
obj.transform.SetParent(transform.parent, false);
cache.Add(obj);
obj.SetActive(false);
cards.RemoveAt(i);
lastAutoChangeTime = Time.realtimeSinceStartup;
if (top.gameObject == obj)
{
top = null;
Refresh();
}
break;
}
}
}
///
/// 获取当前卡片
///
///
public GameObject GetTop()
{
if (top == null)
return null;
return top.gameObject;
}
///
/// 清除所有的卡片
///
public void Clear()
{
for (int i = 0; i < cards.Count; ++i)
{
Destroy(cards[i].root);
Destroy(cards[i].page);
}
cards.Clear();
disableDrag = false;
draging = false;
}
///
/// 将卡片移入缓存隐藏
///
public void ClearToCache()
{
for (int i = 0; i < cards.Count; ++i)
{
GameObject obj = cards[i].root;
obj.transform.SetParent(transform.parent, false);
cache.Add(obj);
obj.SetActive(false);
}
cards.Clear();
}
///
/// 拖动实现
///
/// Drag event data.
public void OnDrag(PointerEventData ev)
{
if (disableDrag) return;
draging = true;
lastAutoChangeTime = Time.realtimeSinceStartup;
current -= moveSpeed * ev.delta.x;
Refresh();
}
///
/// 拖动结束
///
/// End drag event data
public void OnEndDrag(PointerEventData ev)
{
if (disableDrag) return;
float to = Mathf.RoundToInt(current);
if (to != current)
{
DOTween.To(x => current = x, current, to, 0.2f).OnUpdate(HandRefresh);
}
draging = false;
lastAutoChangeTime = Time.realtimeSinceStartup;
}
///
/// 点击事件
///
/// Pointer click event data
public void OnPointerClick(PointerEventData ev)
{
if (draging) return;
RectTransform enter = ev.rawPointerPress.GetComponent
if (enter == top) return;
for (int i = 0; i < cards.Count; ++i)
{
if (enter.gameObject == cards[i].root || enter.IsChildOf(cards[i].root.transform))
{
DOTween.To(x => current = x, current, i, 0.2f).OnUpdate
(
() =>
{
Refresh(false, false);
}
).onComplete = () =>
{
Refresh(false);
};
ResetAutoChangeTime();
break;
}
}
}
///
/// 重置自动改变时间
///
public void ResetAutoChangeTime()
{
lastAutoChangeTime = Time.realtimeSinceStartup;
}
///
/// 刷新
///
///
///
void Refresh(bool _auto = false, bool _invoke = true)
{
if (disableDrag) return;
int count = cards.Count;
if (IfLoop)
{
if (current > count)
{
current = 0;
}
if (current < -1)
{
current = count - 1;
}
}
else
current = Mathf.Clamp(current, 0, count - 1);
for (int i = 0; i < count; ++i)
{
float delta = i - current;
if (IfLoop)
{
if (delta < 0)
{
float cacheNum = Mathf.Abs(delta);
if (cacheNum > (count / 2) - 1)
{
delta = count - cacheNum;
}
}
else
{
float cacheNum = delta;
if (cacheNum > (count / 2) - 1)
{
delta = cacheNum - count;
}
}
}
float scale = 1;
float step = step = 1 - Mathf.Abs(delta) * ReduceScale; ;
if (!UseCurve)
{
scale = Mathf.Lerp(0, 1, step);
}
else
{
scale = ScaleCurve.Evaluate(Mathf.Abs(delta));
}
bool isTop = Mathf.Abs(delta) < 0.5f;
Card card = cards[i];
RectTransform trans = card.root.GetComponent
trans.localScale = Vector3.one * scale;
if (!UseCurve)
{
trans.anchoredPosition = offset * delta;
}
else
{
if (delta > 0)
trans.anchoredPosition = offset * PosCurve.Evaluate(Mathf.Abs(delta));
else if (delta < 0)
trans.anchoredPosition = -offset * PosCurve.Evaluate(Mathf.Abs(delta));
else
trans.anchoredPosition = Vector2.zero;
}
int id = trans.gameObject.GetInstanceID();
if (pageTemplate != null)
{
card.pageOn.SetActive(isTop);
card.pageOff.SetActive(!isTop);
}
if (isTop)
{
trans.SetSiblingIndex(count - 1);
//if (top != trans)
{
if (_invoke)
onTopChanged.Invoke(trans.gameObject, i);
}
top = trans;
}
else
{
trans.SetSiblingIndex(count - 1 - Mathf.CeilToInt(Mathf.Abs(delta)));
}
if (ChangeColor)
{
Image[] imgs = trans.GetComponentsInChildren
foreach (var img in imgs)
img.color = Color.Lerp(Color.gray, Color.white, step);
}
Button[] btns = trans.GetComponentsInChildren
SetAlpha();
}
///
/// 自动刷新
///
void AutoRefresh()
{
Refresh(true);
}
///
/// 拖动刷新
///
void HandRefresh()
{
Refresh(false);
}
///
/// 设置Alpha
///
private void SetAlpha()
{
if (!ChangeAlpha)
return;
int topIndex = 0;
int count = cards.Count;
for (int i = 0; i < count; ++i)
if (cards[i].root.GetComponent
topIndex = i;
for (int i = 0; i < count; ++i)
{
float alpha = 1.0f;
if (topIndex > i && topIndex - i == 1)
alpha = 0.7f;
else if (topIndex < i && i - topIndex == 1)
alpha = 0.7f;
else if (topIndex != i)
alpha = 0.5f;
Card card = cards[i];
CanvasGroup canvasGroup = card.root.GetComponent
if (canvasGroup == null)
canvasGroup = card.root.AddComponent
canvasGroup.alpha = alpha;
}
}
}
}
转载请注明出处!!!
欢迎加入951815219群聊,共享知识,讨论交流~