這篇文章主要介紹了Unity實(shí)現(xiàn)圖片輪播組件的方法,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
創(chuàng)新互聯(lián)專(zhuān)注于企業(yè)營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、網(wǎng)站重做改版、江津網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5開(kāi)發(fā)、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性?xún)r(jià)比高,為江津等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。
游戲中有時(shí)候會(huì)見(jiàn)到圖片輪播的效果,那么這里就自己封裝了一個(gè),包括自動(dòng)輪播、切頁(yè)按鈕控制、頁(yè)碼下標(biāo)更新、滑動(dòng)輪播、切頁(yè)后的回調(diào)等等 。
下面,先上一個(gè)簡(jiǎn)陋的gif動(dòng)態(tài)效果圖
從圖中可以看出,該示例包括了三張圖片的輪播,左右分別是上一張和下一張的按鈕,右下角顯示了當(dāng)前是第幾章的頁(yè)碼下標(biāo)。
直接上腳本:
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.EventSystems; using UnityEngine.UI; namespace UnityEngine.UI { [AddComponentMenu("UI/Slidershow", 39)] //添加菜單 [ExecuteInEditMode] //編輯模式下可執(zhí)行 [DisallowMultipleComponent] //不可重復(fù) [RequireComponent(typeof(RectTransform))] //依賴(lài)于RectTransform組件 public class Slideshow : UIBehaviour,IPointerDownHandler,IPointerUpHandler { public enum MovementType { /// <summary> /// 循環(huán) /// </summary> Circulation, //循環(huán),輪播到最后一頁(yè)之后,直接回到第一頁(yè) /// <summary> /// 來(lái)回往復(fù) /// </summary> PingPong, //來(lái)回往復(fù),輪播到最后一頁(yè)之后,倒序輪播,到第一頁(yè)之后,同理 } public enum MoveDir { Left, Right, } [SerializeField] private MovementType m_movement = MovementType.Circulation; public MovementType Movement { get { return m_movement; } set { m_movement = value; } } [SerializeField] private RectTransform m_content; public RectTransform Content { get { return m_content; } set { m_content = value; } } [SerializeField] private Button m_lastPageButton; public Button LastPageButton { get { return m_lastPageButton; } set { m_lastPageButton = value; } } [SerializeField] private Button m_nextPageButton; public Button NextPageButton { get { return m_nextPageButton; } set { m_nextPageButton = value; } } /// <summary> /// 自動(dòng)輪播時(shí)長(zhǎng) /// </summary> [SerializeField] private float m_showTime = 2.0f; public float ShowTime { get { return m_showTime; } set { m_showTime = value; } } /// <summary> /// 是否自動(dòng)輪播 /// </summary> [SerializeField] private bool m_autoSlide = false; public bool AutoSlide { get { return m_autoSlide; }set { m_autoSlide = value; } } /// <summary> /// 自動(dòng)輪播方向,-1表示向左,1表示向右 /// </summary> private MoveDir m_autoSlideDir = MoveDir.Right; /// <summary> /// 是否允許拖動(dòng)切頁(yè) /// </summary> [SerializeField] private bool m_allowDrag = true; public bool AllowDrag { get { return m_allowDrag; }set { m_allowDrag = value; } } /// <summary> /// 當(dāng)前顯示頁(yè)的頁(yè)碼,下標(biāo)從0開(kāi)始 /// </summary> private int m_curPageIndex = 0; public int CurPageIndex { get { return m_curPageIndex; } } /// <summary> /// 最大頁(yè)碼 /// </summary> private int m_maxPageIndex = 0; public int MaxPageIndex { get { return m_maxPageIndex; } } /// <summary> /// 圓圈頁(yè)碼ToggleGroup /// </summary> [SerializeField] private ToggleGroup m_pageToggleGroup; public ToggleGroup PageToggleGroup { get { return m_pageToggleGroup; } set { m_pageToggleGroup = value; } } /// <summary> /// 圓圈頁(yè)碼Toggle List /// </summary> private List<Toggle> m_pageToggleList; public List<Toggle> PageToggleLise { get { return m_pageToggleList; }} //item數(shù)目 private int m_itemNum = 0; public int ItemNum { get { return m_itemNum; } } //以Toggle為Key,返回頁(yè)碼 private Dictionary<Toggle, int> m_togglePageNumDic = null; private float m_time = 0f; private List<float> m_childItemPos = new List<float>(); private GridLayoutGroup m_grid = null; protected override void Awake() { base.Awake(); if (null == m_content) { throw new Exception("Slideshow content is null"); } else { m_grid = m_content.GetComponent<GridLayoutGroup>(); if (m_grid == null) { throw new Exception("Slideshow content is miss GridLayoutGroup Component"); } InitChildItemPos(); } if (null != m_lastPageButton) { m_lastPageButton.onClick.AddListener(OnLastPageButtonClick); } if (null != m_nextPageButton) { m_nextPageButton.onClick.AddListener(OnNextPageButtonClick); } if (null != m_pageToggleGroup) { int toggleNum = m_pageToggleGroup.transform.childCount; if (toggleNum > 0) { m_pageToggleList = new List<Toggle>(); m_togglePageNumDic = new Dictionary<Toggle, int>(); for (int i = 0; i < toggleNum; i++) { Toggle childToggle = m_pageToggleGroup.transform.GetChild(i).GetComponent<Toggle>(); if (null != childToggle) { m_pageToggleList.Add(childToggle); m_togglePageNumDic.Add(childToggle, i); childToggle.onValueChanged.AddListener(OnPageToggleValueChanged); } } m_itemNum = m_pageToggleList.Count; m_maxPageIndex = m_pageToggleList.Count - 1; } } UpdateCutPageButtonActive(m_curPageIndex); } private void InitChildItemPos() { int childCount = m_content.transform.childCount; float cellSizeX = m_grid.cellSize.x; float spacingX = m_grid.spacing.x; float posX = -cellSizeX * 0.5f; m_childItemPos.Add(posX); for (int i = 1; i < childCount; i++) { posX -= cellSizeX + spacingX; m_childItemPos.Add(posX); } } private void OnPageToggleValueChanged(bool ison) { if (ison) { Toggle activeToggle = GetActivePageToggle(); if (m_togglePageNumDic.ContainsKey(activeToggle)) { int page = m_togglePageNumDic[activeToggle]; SwitchToPageNum(page); } } } private Toggle GetActivePageToggle() { if (m_pageToggleGroup == null || m_pageToggleList == null || m_pageToggleList.Count <= 0) { return null; } for (int i = 0; i < m_pageToggleList.Count; i++) { if (m_pageToggleList[i].isOn) { return m_pageToggleList[i]; } } return null; } /// <summary> /// 切換至某頁(yè) /// </summary> /// <param name="pageNum">頁(yè)碼</param> private void SwitchToPageNum(int pageNum) { if (pageNum < 0 || pageNum > m_maxPageIndex) { throw new Exception("page num is error"); } if (pageNum == m_curPageIndex) { //目標(biāo)頁(yè)與當(dāng)前頁(yè)是同一頁(yè) return; } m_curPageIndex = pageNum; if (m_movement == MovementType.PingPong) { UpdateCutPageButtonActive(m_curPageIndex); } Vector3 pos = m_content.localPosition; m_content.localPosition = new Vector3(m_childItemPos[m_curPageIndex], pos.y, pos.z); m_pageToggleList[m_curPageIndex].isOn = true; if (m_onValueChanged != null) { //執(zhí)行回調(diào) m_onValueChanged.Invoke(m_pageToggleList[m_curPageIndex].gameObject); } } /// <summary> /// 根據(jù)頁(yè)碼更新切頁(yè)按鈕active /// </summary> /// <param name="pageNum"></param> private void UpdateCutPageButtonActive(int pageNum) { if (pageNum == 0) { UpdateLastButtonActive(false); UpdateNextButtonActive(true); } else if (pageNum == m_maxPageIndex) { UpdateLastButtonActive(true); UpdateNextButtonActive(false); } else { UpdateLastButtonActive(true); UpdateNextButtonActive(true); } } private void OnNextPageButtonClick() { m_time = Time.time; //重新計(jì)時(shí) switch (m_movement) { case MovementType.Circulation: SwitchToPageNum((m_curPageIndex + 1) % m_itemNum); break; case MovementType.PingPong: //該模式下,會(huì)自動(dòng)隱藏切頁(yè)按鈕 SwitchToPageNum(m_curPageIndex + 1); break; default: break; } Debug.Log(m_content.localPosition); } private void OnLastPageButtonClick() { m_time = Time.time; //重新計(jì)時(shí) switch (m_movement) { case MovementType.Circulation: SwitchToPageNum((m_curPageIndex + m_itemNum - 1) % m_itemNum); break; case MovementType.PingPong: //該模式下,會(huì)自動(dòng)隱藏切頁(yè)按鈕 SwitchToPageNum(m_curPageIndex - 1); break; default: break; } } private void UpdateLastButtonActive(bool activeSelf) { if (null == m_lastPageButton) { throw new Exception("Last Page Button is null"); } bool curActive = m_lastPageButton.gameObject.activeSelf; if (curActive != activeSelf) { m_lastPageButton.gameObject.SetActive(activeSelf); } } private void UpdateNextButtonActive(bool activeSelf) { if (null == m_nextPageButton) { throw new Exception("Next Page Button is null"); } bool curActive = m_nextPageButton.gameObject.activeSelf; if (curActive != activeSelf) { m_nextPageButton.gameObject.SetActive(activeSelf); } } private Vector3 m_originDragPos = Vector3.zero; private Vector3 m_desDragPos = Vector3.zero; private bool m_isDrag = false; public void OnPointerDown(PointerEventData eventData) { if (!m_allowDrag) { return; } if (eventData.button != PointerEventData.InputButton.Left) { return; } if (!IsActive()) { return; } m_isDrag = true; m_originDragPos = eventData.position; } public void OnPointerUp(PointerEventData eventData) { m_desDragPos = eventData.position; MoveDir dir = MoveDir.Right; if (m_desDragPos.x < m_originDragPos.x) { dir = MoveDir.Left; } switch (dir) { case MoveDir.Left: if (m_movement == MovementType.Circulation || (m_movement == MovementType.PingPong && m_curPageIndex != 0)) { OnLastPageButtonClick(); } break; case MoveDir.Right: if (m_movement == MovementType.Circulation || (m_movement == MovementType.PingPong && m_curPageIndex != m_maxPageIndex)) { OnNextPageButtonClick(); } break; } m_isDrag = false; } /// <summary> /// 切頁(yè)后回調(diào)函數(shù) /// </summary> [Serializable] public class SlideshowEvent : UnityEvent<GameObject> { } [SerializeField] private SlideshowEvent m_onValueChanged = new SlideshowEvent(); public SlideshowEvent OnValueChanged { get { return m_onValueChanged; } set { m_onValueChanged = value; } } public override bool IsActive() { return base.IsActive() && m_content != null; } private void Update() { if (m_autoSlide && !m_isDrag) { if (Time.time > m_time + m_showTime) { m_time = Time.time; switch (m_movement) { case MovementType.Circulation: m_autoSlideDir = MoveDir.Right; break; case MovementType.PingPong: if (m_curPageIndex == 0) { m_autoSlideDir = MoveDir.Right; } else if (m_curPageIndex == m_maxPageIndex) { m_autoSlideDir = MoveDir.Left; } break; } switch (m_autoSlideDir) { case MoveDir.Left: OnLastPageButtonClick(); break; case MoveDir.Right: OnNextPageButtonClick(); break; } } } } } }
這里提供了一個(gè)枚舉MovementType,該枚舉定義了兩種循環(huán)方式,其中Circulation循環(huán),是指輪播到最后一頁(yè)之后,直接回到第一頁(yè);而PingPong相信大家你熟悉了,就是來(lái)回往復(fù)的。
其中還提供了對(duì)每張圖顯示的時(shí)長(zhǎng)進(jìn)行設(shè)置,還有是否允許自動(dòng)輪播的控制,是否允許拖動(dòng)切頁(yè)控制,等等。。其實(shí)將圖片作為輪播子元素只是其中之一而已,完全可以將ScrollRect作為輪播子元素,這樣每個(gè)子元素又可以滑動(dòng)閱覽了。
這里還提供了兩個(gè)編輯器腳本,一個(gè)是SlideshowEditor(依賴(lài)Slideshow組件),另一個(gè)是給用戶(hù)提供菜單用的CreateSlideshow,代碼分別如下:
using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class CreateSlideshow : Editor { private static GameObject m_slideshowPrefab = null; private static GameObject m_canvas = null; [MenuItem("GameObject/UI/Slideshow")] static void CreateSlideshowUI(MenuCommand menuCommand) { if (null == m_slideshowPrefab) { m_slideshowPrefab = Resources.Load<GameObject>("Slideshow"); if (null == m_slideshowPrefab) { Debug.LogError("Prefab Slideshow is null"); return; } } m_canvas = menuCommand.context as GameObject; if (m_canvas == null || m_canvas.GetComponentInParent<Canvas>() == null) { m_canvas = GetOrCreateCanvasGameObject(); } GameObject go = GameObject.Instantiate(m_slideshowPrefab, m_canvas.transform); go.transform.localPosition = Vector3.zero; go.name = "Slideshow"; Selection.activeGameObject = go; } static public GameObject GetOrCreateCanvasGameObject() { GameObject selectedGo = Selection.activeGameObject; Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null; if (canvas != null && canvas.gameObject.activeInHierarchy) return canvas.gameObject; canvas = Object.FindObjectOfType(typeof(Canvas)) as Canvas; if (canvas != null && canvas.gameObject.activeInHierarchy) return canvas.gameObject; return CreateCanvas(); } public static GameObject CreateCanvas() { var root = new GameObject("Canvas"); root.layer = LayerMask.NameToLayer("UI"); Canvas canvas = root.AddComponent<Canvas>(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; root.AddComponent<CanvasScaler>(); root.AddComponent<GraphicRaycaster>(); Undo.RegisterCreatedObjectUndo(root, "Create " + root.name); CreateEventSystem(); return root; } public static void CreateEventSystem() { var esys = Object.FindObjectOfType<EventSystem>(); if (esys == null) { var eventSystem = new GameObject("EventSystem"); GameObjectUtility.SetParentAndAlign(eventSystem, null); esys = eventSystem.AddComponent<EventSystem>(); eventSystem.AddComponent<StandaloneInputModule>(); Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name); } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor.Advertisements; using UnityEngine.UI; namespace UnityEditor.UI { [CustomEditor(typeof(Slideshow), true)] public class SlideshowEditor : Editor { SerializedProperty m_movement; SerializedProperty m_content; SerializedProperty m_lastPageButton; SerializedProperty m_nextPageButton; SerializedProperty m_showTime; SerializedProperty m_pageToggleGroup; SerializedProperty m_onValueChanged; SerializedProperty m_allowDrag; SerializedProperty m_autoSlide; protected virtual void OnEnable() { m_movement = serializedObject.FindProperty("m_movement"); m_content = serializedObject.FindProperty("m_content"); m_lastPageButton = serializedObject.FindProperty("m_lastPageButton"); m_nextPageButton = serializedObject.FindProperty("m_nextPageButton"); m_showTime = serializedObject.FindProperty("m_showTime"); m_pageToggleGroup = serializedObject.FindProperty("m_pageToggleGroup"); m_onValueChanged = serializedObject.FindProperty("m_onValueChanged"); m_allowDrag = serializedObject.FindProperty("m_allowDrag"); m_autoSlide = serializedObject.FindProperty("m_autoSlide"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(m_movement); EditorGUILayout.PropertyField(m_content); EditorGUILayout.PropertyField(m_lastPageButton); EditorGUILayout.PropertyField(m_nextPageButton); EditorGUILayout.PropertyField(m_allowDrag); EditorGUILayout.PropertyField(m_autoSlide); EditorGUILayout.PropertyField(m_showTime); EditorGUILayout.PropertyField(m_pageToggleGroup); EditorGUILayout.Space(); EditorGUILayout.PropertyField(m_onValueChanged); //不加這句代碼,在編輯模式下,無(wú)法將物體拖拽賦值 serializedObject.ApplyModifiedProperties(); } } }
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Unity實(shí)現(xiàn)圖片輪播組件的方法”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
分享文章:Unity實(shí)現(xiàn)圖片輪播組件的方法
URL地址:http://jinyejixie.com/article30/ppepso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站、網(wǎng)站制作、微信公眾號(hào)、網(wǎng)站營(yíng)銷(xiāo)、關(guān)鍵詞優(yōu)化、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)