我们将卡牌之间 的间隔变大,则可以看到 下面的UI
首先,我们 想做一个滚动列表,这就像在 x轴 和Z 轴上的 一个循环的椭圆
##如果我们将卡牌平均分布在这个椭圆上。那么每个卡牌占这个 椭圆 整个圆周 角度一定的 比例。我们定这个比例 为 radio ,radio 的值 从 0 ~ 1 ,0和1 的点重合。 现在大家 清除 我们卡牌 是怎么 排布的了吧。 我们 需要做的点有四个: 1.将 卡牌 排布在这个椭圆上。 2. 根据 radio 去 设置 不同位置的卡牌的 缩放。 3. 为了看起来有层次感,我们需要设置 卡牌的 层级。 4. 最后就是 给卡牌添加 拖拽的监听。
那么现在第一步骤: 在 unity UI 上添加一个 节点,用来放置我们的卡牌。 在UI 上加个 空的 组件。作为父节点。
然后 添加 C# 脚本,添加到该组件上。
我这里 百度截图了 10张图,将就着用。 先初始化这 10张卡牌
private GameObject CreateTempate() { GameObject temp = new GameObject("Template"); temp.AddComponent<PageItem>(); temp.AddComponent<RectTransform>().sizeDelta = ItemSize; temp.AddComponent<Image>(); return temp; } private void CreateItem() { GameObject temp = CreateTempate(); for (int i = 0; i < SpriteList.Count; i++) { PageItem item = Instantiate(temp).GetComponent<PageItem>(); item.Index = i; item.SetImage(SpriteList[i]); item.SetParent(transform); item.AddEventlistenr(change); ItemList.Add(item); } }我们 在这个椭圆上 平均分布 这些卡牌,则 均分的 系数 是 radio = 1/10,十张卡牌均分;
private void CaculateData() { float length = (ItemSize.x + OffSetX) * 6; float radio = 1.0f / SpriteList.Count; float tempRadio = 0f; for (int i = 0; i < SpriteList.Count; i++) { ItemPosData pos = new ItemPosData(); ItemIdData itemId = new ItemIdData(); itemId.Id = i; pos.X = GetX(tempRadio, length); pos.ScareTimes = GetScaraTimes(tempRadio, ScareMax, ScareMin); tempRadio += radio; pos.Order = i; ItemPosList.Add(pos); itemIdList.Add(itemId); } itemIdList = itemIdList.OrderBy(u => ItemPosList[u.Id].ScareTimes).ToList(); for (int i = 0; i < itemIdList.Count; i++) //根据缩放有小到大,排列了id列表 { int id = itemIdList[i].Id; ItemPosList[id].Order = i; } for (int i = 0; i < ItemPosList.Count; i++) { ItemList[i].SetPositon(ItemPosList[i]); } }length 是我们自己定义 滚动列表的宽度,很重要的一点,Z 轴 左右两边 的 卡牌坐标是是对称的。 我们根据 radio 和宽度 计算出 卡牌的 X 坐标。
private float GetX(float radio, float length) { if (radio < 0 || radio > 1) { Debug.Log("系数错误"); return 0; } if (radio >= 0 && radio <= 0.25f) { return radio * length; } else if (radio > 0.25 && radio < 0.75f) { return (0.5f - radio) * length; } else { return (radio - 1f) * length; } }同样的,卡牌的缩放,也是 左右对称的。
private float GetScaraTimes(float radio, float scareMax, float scareMin) { float scareSub = scareMax - scareMin; if (radio < 0f || radio > 1f) { Debug.Log("系数错误"); return 0; } if (radio == 0 || radio == 1f) { return scareSub; } if (radio > 0 && radio <= 0.5f) { return (1 - radio) * scareSub;//0.5 ~ 1 } else { return radio * scareSub; } }这时候的 卡牌是没有层级的
item 中 我们 重点 就是 添加可 两个 拖拽接口: IDragHandler,IEndDragHandler 这是我们能让 卡牌滚动的重点。
通过委托,我们将 offX 也就是拖拽的 值传递到 父节点的脚本中。 item.AddEventlistenr(change);
我们 通过 计算好的 位置 和缩放值 的列表。 去给 item 重新设置 位置 和 缩放,就产生了滚动的效果。
private void change(float offX) { int symbol = 0; symbol = offX > 0 ? 1 : -1; rotateItem(symbol); } private void rotateItem(int symbol) { int allNums = itemIdList.Count; int lens = allNums - 1; int maxValues = lens; for (int i = 0; i < ItemPosList.Count; i++) { int index = ItemList[i].Index; if (symbol < 0) { if (index == 0) { index = maxValues; } else { index = index + symbol; } } else { if (index == maxValues) { index = 0; } else { index = index + symbol; } } ItemList[i].Index = index; } for (int i = 0; i < allNums; i++) { int index = ItemList[i].Index; ItemList[i].SetPositon(ItemPosList[index]); } }这里主要 要理解 的还是位置的重置。
链接: https://pan.baidu.com/s/1dynUHQYCCevMUW8qFlRM-Q 提取码: r59t demo 下载