Unity text scrolling when mouse hovers (Text Mesh Pro)

Effect

Please add image description
Mount the script directly on Text Mesh Pro, but the text that needs to be scrolled must be in the Scroll View, otherwise the positioning will be wrong. You also need to add vertical or horizontal layout components to the Scroll View to see the requirements.

code

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();
    }

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

    /// <summary>
    /// 鼠标进入
    /// </summary>
    /// <param name="eventData">传入事件数据,鼠标位置等</param>
    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));
    }
   
    /// <summary>
    /// 鼠标移出
    /// </summary>
    /// <param name="eventData"></param>
    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();
    }

    /// <summary>
    /// 计算文本内容宽度
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    private float CalculateTextWidth(TextMeshProUGUI text) {
    
    
        float width = text.preferredWidth;
        return width;
    }


    private float totalDistance = 0;
    private float totalTime = 0;
    /// <summary>
    /// 文本滚动的协程
    /// </summary>
    /// <param name="time">协程运行时间</param>
    /// <param name="isReset">是否是恢复时启动的协程</param>
    /// <returns></returns>
    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;
    }

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

        totalDistance = 0;
        totalTime = 0;
    }
}

Guess you like

Origin blog.csdn.net/blastospore/article/details/133468805