Unity 鼠标悬浮时文本滚动(Text Mesh Pro)

效果

Unity 鼠标悬浮时文本滚动(Text Mesh Pro)_第1张图片
直接将脚本挂载在Text Mesh Pro上,但是需要滚动的文本必须在Scroll View中,否侧会定位错误,还需要给Scroll View中看需求添加垂直或者水平布局的组件

代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using TMPro;
using UnityEngine.EventSystems;

public class TextScroll : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
    // TextMeshPro的文本框
    private TextMeshProUGUI text;

    private string saveStr; // 保存文本内容,可以保存,但是没有必要,需要实现动态文本
    private Vector3 savePostion; // 保存文本位置
    private Vector2 savesizeDelta; // 保存尺寸
    private float saveMoveWeight;
    private RectTransform rect; // 文本的方形转换器


    [Tooltip("开启自动权重")]
    public bool AutoMoveWeight = true;

    // 如果开启自动权重那么对该变量修改不在起作用
    [Tooltip("溢出文本移动的权重,会根据权重的值,来对溢出内容的多少进行加速")]
    public float moveWeight = 3;
    private void OnEnable() {
        text = GetComponent<TextMeshProUGUI>();
        rect = text.gameObject.GetComponent<RectTransform>();
        Init();
    }

    /// 
    /// 初始化文本内容
    /// 
    public void Init() {
        saveStr = text.text;
        savePostion = rect.position;
        savesizeDelta = rect.sizeDelta;
        saveMoveWeight = moveWeight;
    }
    
    private Coroutine coroutine; // 接收协程

    /// 
    /// 鼠标进入
    /// 
    /// 传入事件数据,鼠标位置等
    public void OnPointerEnter(PointerEventData eventData) 
    {
        // Debug.Log("鼠标进入开始文本滚动");
        // saveStr = text.text;

        // 是否存在截断
        float fontsLenght = CalculateTextWidth(text);
        if (fontsLenght < rect.sizeDelta.x ) return;
    
        // 处理上一次退出后未完成恢复完成就再次进入
        if (coroutine != null) {
            StopCoroutine(coroutine);
            Reset();
        }
        // 是否启动自动更新
        if (AutoMoveWeight) {
            moveWeight = (fontsLenght - rect.sizeDelta.x) / 100;
        }

        // 计算所需时间
        float sumTime = (fontsLenght - rect.sizeDelta.x) / text.fontSize / moveWeight;
        rect.sizeDelta = new Vector2(fontsLenght + 100, rect.sizeDelta.y);
        coroutine = StartCoroutine(IETextScroll(sumTime, false));
    }
   
    /// 
    /// 鼠标移出
    /// 
    /// 
    public void OnPointerExit(PointerEventData eventData) {

        // Debug.Log("text begine reset");
        // 过滤
        if (text == null || (coroutine == null && CalculateTextWidth(text) < rect.sizeDelta.x) || totalDistance == 0) return;
        if (coroutine != null) { // 文本正在向左滚动
            StopCoroutine(coroutine);
        } 
        coroutine = StartCoroutine(IETextScroll(totalTime / 3, true));
        // Reset();
    }

    /// 
    /// 计算文本内容宽度
    /// 
    /// 
    /// 
    private float CalculateTextWidth(TextMeshProUGUI text) {
        float width = text.preferredWidth;
        return width;
    }


    private float totalDistance = 0;
    private float totalTime = 0;
    /// 
    /// 文本滚动的协程
    /// 
    /// 协程运行时间
    /// 是否是恢复时启动的协程
    /// 
    private IEnumerator IETextScroll(float time, bool isReset) {
        // float moveSpeed = 0;

        float perDistance = 0;
        if (!isReset) {
            while (time > 0) {
                // Time.deltaTime 是一个不确定的量,需要每帧更新。
                perDistance = moveWeight * text.fontSize * Time.deltaTime;
                rect.position = new Vector3(rect.position.x - perDistance, rect.position.y);
                time -= Time.deltaTime;

                totalDistance += perDistance;
                totalTime += Time.deltaTime;
                yield return null;
            }
        } else { // 恢复

            //moveSpeed = totalDistance / time;
            //while (time > 0) {
            //    perDistance = moveSpeed * Time.deltaTime;
            //    rect.position = new Vector3(rect.position.x + perDistance, rect.position.y);
            //    time -= Time.deltaTime;
            //    yield return null;
            //}

            Reset();
        }
        // Debug.Log("移动权重: " + moveWeight + " 每次距离: " + totalDistance + " 花费时间: " + totalTime);

        yield return null;
    }

    /// 
    /// 恢复
    /// 
    private void Reset() 
    {
        if (text == null) return;
        // text.text = saveStr;
        rect.position = savePostion;
        rect.sizeDelta = savesizeDelta;
        moveWeight = saveMoveWeight; // 采用自动权重时会再次自动计算权重

        totalDistance = 0;
        totalTime = 0;
    }
}

你可能感兴趣的:(unity)