Unity UGUI超链接

using System.Collections.Generic;
using UnityEngine.EventSystems;
using Unity.Collections;
using UnityEngine.UI;
using UnityEngine;
using System.Text;
using System;

public class HyperlinkInfo : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
    public GameObject prefab;

    /// 
    /// 是否显示超链接的区域框
    /// 
    [Header("是否显示超链接的区域框")]
    public bool isShowHyperlineSign = false;

    private Text targetText;
    private string noColorMsg;
    private Canvas targetCanvas;

    public List<HyperlinkInfoContains> hyperlinks = new List<HyperlinkInfoContains>();

    void Awake()
    {
        targetText = GetComponent<Text>();
        targetCanvas = FindObjectOfType<Canvas>();
        StartCoroutine( DataMgr.LoadConfig("test.txt", LoadConfigFinished));
    }

    private void LoadConfigFinished(string obj)
    {
        AnalysisHyperlink(obj);
    }

    #region Hyperlink超链接系统(*Canvas设置:RenderMode必须为Screen Space - Overlay*)
    /// 
    /// 解析超链接
    /// 
    private void AnalysisHyperlink(string str)
    {
        int startIndex = 0;
        int endIndex = 0;

        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] == '<' && str[i + 1] == '/') 
            {
                startIndex = i + 2;
            }
            if (str[i] == '>' && str[i - 1] == '/')
            {
                endIndex = i - 2;
            }
            if (endIndex > startIndex)
            {
                StringBuilder stringBuilder = new StringBuilder();
                for (int j = startIndex; j <= endIndex; j++) 
                {
                    stringBuilder.Append(str[j]);
                }
                HyperlinkInfoContains contains = new HyperlinkInfoContains();
                contains.url = stringBuilder.ToString();
                hyperlinks.Add(contains);
                startIndex = endIndex = 0;
            }
        }

        noColorMsg = str.Replace(", "").Replace("/>", "").Replace("\r", "");

        SetHyperlinkColor(noColorMsg);
        SetHyperlinkIndex(noColorMsg);
        CalculateHyprelinkPos();
    }

    /// 
    /// 设置超链接的颜色
    /// 
    private void SetHyperlinkColor(string str)
    {
        for (int i = 0; i < hyperlinks.Count; i++)
        {
            if (str.Contains(hyperlinks[i].url))
            {
                string newStr = "" + hyperlinks[i].url + "";
                str = str.Replace(hyperlinks[i].url, newStr);
            }
        }

        targetText.text = str;
    }

    /// 
    /// 设置超链接的下标
    /// 
    /// 
    private void SetHyperlinkIndex(string str)
    {
        for (int i = 0; i < hyperlinks.Count; i++)
        {
            if (str.Contains(hyperlinks[i].url))
            {
                var startIndex = str.IndexOf(hyperlinks[i].url);
                var endIndex = startIndex + hyperlinks[i].url.Length - 1;
                hyperlinks[i].StartIndex = startIndex;
                hyperlinks[i].EndIndex = endIndex;
            }
        }
    }

    /// 
    /// 计算超链接的范围
    /// 
    private void CalculateHyprelinkPos()
    {
        for (int i = 0; i < hyperlinks.Count; i++)
        {
            var list_1 = CalculateCharPos(hyperlinks[i].StartIndex);
            var list_2 = CalculateCharPos(hyperlinks[i].EndIndex);

            var AreaPos_1 = list_1[0];
            var AreaPos_2 = list_2[1];
            var AreaPos_3 = list_2[2];
            var AreaPos_4 = list_1[3];

            if (AreaPos_1.y < AreaPos_2.y)
                AreaPos_1 = new Vector2(AreaPos_1.x, AreaPos_2.y);
            else
                AreaPos_2 = new Vector2(AreaPos_2.x, AreaPos_1.y);

            if (AreaPos_4.y < AreaPos_3.y)
                AreaPos_3 = new Vector2(AreaPos_3.x, AreaPos_4.y);
            else
                AreaPos_4 = new Vector2(AreaPos_4.x, AreaPos_3.y);

            hyperlinks[i].AreaPos_1 = AreaPos_1;
            hyperlinks[i].AreaPos_2 = AreaPos_2;
            hyperlinks[i].AreaPos_3 = AreaPos_3;
            hyperlinks[i].AreaPos_4 = AreaPos_4;

            hyperlinks[i].centerPos = (list_1[0] + list_2[1] + list_2[2] + list_1[3]) / 4;

            Show(hyperlinks[i]);
        }
    }

    /// 
    /// 计算字符坐标
    /// 
    ///  Text所在的Canvas 
    ///  要计算字符坐在的Text 
    ///  要计算字符在字符串的下标 
    private List<Vector3> CalculateCharPos(int targetCharIndex)
    {
        List<Vector3> list = new List<Vector3>();

        string calculateStr = noColorMsg;

        TextGenerator textGen = new TextGenerator(calculateStr.Length);

        Vector2 extents = targetText.GetComponent<RectTransform>().rect.size;

        textGen.Populate(calculateStr, targetText.GetGenerationSettings(extents));

        int newLine = calculateStr.Substring(0, targetCharIndex).Split('\n').Length - 1;

        int whiteSpace = calculateStr.Substring(0, targetCharIndex).Split(' ').Length - 1;

        int indexOfTextQuad = (targetCharIndex - newLine) * 4;

        Vector3 charPos1 = textGen.verts[indexOfTextQuad].position / targetCanvas.scaleFactor;
        Vector3 charPos2 = textGen.verts[indexOfTextQuad + 1].position / targetCanvas.scaleFactor;
        Vector3 charPos3 = textGen.verts[indexOfTextQuad + 2].position / targetCanvas.scaleFactor;
        Vector3 charPos4 = textGen.verts[indexOfTextQuad + 3].position / targetCanvas.scaleFactor;

        list.Add(charPos1); list.Add(charPos2); list.Add(charPos3); list.Add(charPos4);

        return list;
    }

    private void Show(HyperlinkInfoContains contains)
    {
        if (!isShowHyperlineSign) return;

        var go_1 = GameObject.Instantiate(prefab, prefab.transform.parent);
        go_1.name = contains.url;
        go_1.GetComponent<RectTransform>().anchoredPosition = contains.AreaPos_1;

        var go_2 = GameObject.Instantiate(prefab, prefab.transform.parent);
        go_2.name = contains.url;
        go_2.GetComponent<RectTransform>().anchoredPosition = contains.AreaPos_2;

        var go_3 = GameObject.Instantiate(prefab, prefab.transform.parent);
        go_3.name = contains.url;
        go_3.GetComponent<RectTransform>().anchoredPosition = contains.AreaPos_3;

        var go_4 = GameObject.Instantiate(prefab, prefab.transform.parent);
        go_4.name = contains.url;
        go_4.GetComponent<RectTransform>().anchoredPosition = contains.AreaPos_4;
    }

    /// 
    /// 判断是否在超链接范围内
    /// 
    /// 
    private bool IsInHyprelinkLimit(Vector2 mousePos,ref HyperlinkInfoContains hyperlink)
    {
        bool isIn = false;

        for (int i = 0; i < hyperlinks.Count; i++)
        {
            hyperlink = hyperlinks[i];

            if ((mousePos.x > hyperlink.AreaPos_1.x && mousePos.x < hyperlink.AreaPos_2.x) && 
                (mousePos.y > hyperlink.AreaPos_4.y && mousePos.y < hyperlink.AreaPos_1.y))
            {
                isIn = true;
                break;
            }
        }
        return isIn;
    }
    #endregion

    #region EventSystem
    public void OnPointerEnter(PointerEventData eventData)
    {
        HyperlinkInfoContains hyperlink = new HyperlinkInfoContains();
        if (IsInHyprelinkLimit(ConvertCoordinate(eventData.position), ref hyperlink))
        {

        }
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        HyperlinkInfoContains hyperlink = new HyperlinkInfoContains();
        if (!IsInHyprelinkLimit(ConvertCoordinate(eventData.position), ref hyperlink))
        {

        }
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        HyperlinkInfoContains hyperlink = new HyperlinkInfoContains();
        var mouseUIPos = ConvertCoordinate(eventData.position);
        var result = IsInHyprelinkLimit(mouseUIPos, ref hyperlink);
        if (result)
        {
            ClickEvent(hyperlink);
        }
    }
    #endregion

    /// 
    /// 坐标转换
    /// 
    private Vector2 ConvertCoordinate(Vector3 worldPos)
    {
        Vector2 mouseUIPos = new Vector2(worldPos.x - Screen.width / 2, worldPos.y - Screen.height / 2);

        return mouseUIPos;
    }
    /// 
    /// 鼠标进入
    /// 
    private void EnterEvent(HyperlinkInfoContains hyperlink)
    {
        Debug.Log(hyperlink.url + " Enter");
    }
    /// 
    /// 鼠标退出
    /// 
    private void ExitEvent(HyperlinkInfoContains hyperlink)
    {
        Debug.Log(hyperlink.url + " Exit");
    }
    /// 
    /// 鼠标点击
    /// 
    private void ClickEvent(HyperlinkInfoContains hyperlink)
    {
        Debug.Log(hyperlink.url + " Click");
    }
}

[Serializable]
public class HyperlinkInfoContains
{
    /// 
    /// 超链接
    /// 
    [ReadOnly]
    public string url;
    /// 
    /// 初始下标
    /// 
    [ReadOnly]
    [SerializeField]
    private int startIndex = 0;
    public int StartIndex
    {
        get { return startIndex; }
        set 
        {
            startIndex = value;
        }
    }
    /// 
    /// 结束下标
    /// 
    [ReadOnly]
    [SerializeField]
    private int endIndex = 0;
    public int EndIndex
    {
        get { return endIndex; }
        set 
        {
            endIndex = value;
        }
    }
    /// 
    /// 区域位置
    /// 
    [ReadOnly]
    public Vector2 AreaPos_1;
    public Vector2 AreaPos_2;
    public Vector2 AreaPos_3;
    public Vector2 AreaPos_4;
    /// 
    /// 区域中心位置
    /// 
    public Vector2 centerPos;
    /// 
    /// 相机位置
    /// 
    public Vector3 cameraPos;
}

你可能感兴趣的:(unity,游戏引擎,ui)