UIImageFilledSide

获取Image在filled模式下当前填充的位置
UIImageFilledSide

/* 
** Created by lvzj
** DateTime: 2021-09-21 16:24:51
** Description: ui特效跟随fillamount位置
*/

using System;
using UnityEngine;
using UnityEngine.UI;

// [ExecuteAlways]
public class UIFilledExtend : MonoBehaviour
{
    public GameObject obj;

    // 是否翻转图片
    public bool flip;

    // 映射到图片边缘
    public bool onSide;

    // 距离旋转点偏移量
    [Range(0, 1)]
    public float offset = 0.5f;

    Vector2[] _points = new Vector2[3];

    private Image _image;

    private RectTransform _rectTransform;

    // 旋转
    private Vector3 _tempRotate = Vector3.zero;

    // 测试点位
    public Image[] pointImages = new Image[3];

    private bool CheckFilledExtend()
    {
        if (obj == null) return false;
        _image = transform.GetComponent<Image>();
        return _image.type == Image.Type.Filled;
    }

    private void Start()
    {
        _image = transform.GetComponent<Image>();
        _rectTransform = transform.GetComponent<RectTransform>();
    }

    private void Update()
    {
        if (CheckFilledExtend())
        {
            GetPosition();
            SetObjPosition();
        }
    }
    
    private void GetPosition()
    {
        _image = transform.GetComponent<Image>();
        _rectTransform = transform.GetComponent<RectTransform>();
        float fillAmount = _image.fillAmount;
        bool fillClockwise = _image.fillClockwise;

        int fillOrigin = _image.fillOrigin;
        float amount = Mathf.Pow(-1, fillOrigin);
        float pos = fillAmount * amount + fillOrigin;

        // 原点
        float point0X;
        float point0Y;

        // 目标点
        float tempPointX;
        float tempPointY;

        float deltaX;
        float deltaY;
        float absX;
        float absY;
        switch (_image.fillMethod)
        {
            case Image.FillMethod.Horizontal:
                point0X = tempPointX = pos;
                point0Y = 0;
                tempPointY = 1f;
                _tempRotate = Vector3.zero;
                break;
            case Image.FillMethod.Vertical:
                point0X = 0;
                point0Y = tempPointY = pos;
                tempPointX = 1f;
                _tempRotate = Vector3.zero;
                break;
            case Image.FillMethod.Radial90:
                point0X = fillOrigin < 2 ? 0 : 1;
                point0Y = fillOrigin < 2 ? fillOrigin % 2 : (fillOrigin - 1) % 2;
                float rad;
                bool isTop = fillOrigin % 3 != 0;
                fillClockwise = isTop ? !fillClockwise : fillClockwise;
                rad = Trans01(fillAmount, fillClockwise == fillOrigin < 2) * 90f * Mathf.Deg2Rad;
                tempPointX = Trans01(Mathf.Cos(rad), fillOrigin >= 2);
                tempPointY = Trans01(Mathf.Sin(rad), isTop);

                if (onSide)
                {
                    deltaX = tempPointX - point0X;
                    deltaY = tempPointY - point0Y;
                    absX = Mathf.Abs(deltaX);
                    absY = Mathf.Abs(deltaY);
                    if (absX > absY)
                    {
                        tempPointY = deltaY * (1.0f / absX) + point0Y;
                        tempPointX = fillOrigin >= 2 ? 0 : 1;
                    }
                    else
                    {
                        tempPointX = deltaX * (1.0f / absY) + point0X;
                        tempPointY = isTop ? 0 : 1;
                    }
                }

                break;
            case Image.FillMethod.Radial180:
                point0X = Mathf.Abs((fillOrigin - 1) / 2.0f);
                point0Y = fillOrigin % 2 == 0 ? fillOrigin / 2.0f : 0.5f;

                //bottom
                if (fillOrigin == 0)
                {
                    tempPointX = Mathf.Cos(Trans01(fillAmount, fillClockwise) * 180f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                    tempPointY = Mathf.Sin(fillAmount * 180f * Mathf.Deg2Rad);
                }

                //top
                else if (fillOrigin == 2)
                {
                    tempPointX = Mathf.Cos(Trans01(fillAmount, !fillClockwise) * 180f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                    tempPointY = 1 - Mathf.Sin(fillAmount * 180f * Mathf.Deg2Rad);
                }
                //left
                else if (fillOrigin == 1)
                {
                    tempPointX = Mathf.Sin(fillAmount * 180f * Mathf.Deg2Rad);
                    tempPointY = Mathf.Cos(Trans01(fillAmount, !fillClockwise) * 180f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                }
                // right fillOrigin == 3
                else
                {
                    tempPointX = 1 - Mathf.Sin(fillAmount * 180f * Mathf.Deg2Rad);
                    tempPointY = Mathf.Cos(Trans01(fillAmount, fillClockwise) * 180f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                }

                if (onSide)
                {
                    deltaX = (tempPointX - point0X) / (fillOrigin % 2 == 1 ? 2.0f : 1.0f);
                    deltaY = (tempPointY - point0Y) / (fillOrigin % 2 == 0 ? 2.0f : 1.0f);
                    absX = Mathf.Abs(deltaX);
                    absY = Mathf.Abs(deltaY);
                    if (absX > absY)
                    {
                        tempPointY = deltaY / (fillOrigin % 2 == 1 ? 2.0f : 1.0f) * (1.0f / absX) + point0Y;
                        tempPointX = deltaX >= 0 ? 1 : 0;
                    }
                    else
                    {
                        tempPointX = deltaX / (fillOrigin % 2 == 0 ? 2.0f : 1.0f) * (1.0f / absY) + point0X;
                        tempPointY = deltaY >= 0 ? 1 : 0;
                    }
                }

                break;
            case Image.FillMethod.Radial360:
                point0X = point0Y = 0.5f;

                // right
                if (fillOrigin == 1)
                {
                    tempPointX = Mathf.Cos(Trans01(fillAmount, fillClockwise) * 360f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                    tempPointY = Mathf.Sin(Trans01(fillAmount, fillClockwise) * 360f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                }
                // left
                else if (fillOrigin == 3)
                {
                    tempPointX = 1 - Mathf.Cos(Trans01(fillAmount, fillClockwise) * 360f * Mathf.Deg2Rad) / 2.0f - 0.5f;
                    tempPointY = Mathf.Sin(Trans01(fillAmount, !fillClockwise) * 360f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                }
                // bottom
                else if (fillOrigin == 0)
                {
                    tempPointX = Mathf.Sin(Trans01(fillAmount, fillClockwise) * 360f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                    tempPointY = 1 - Mathf.Cos(Trans01(fillAmount, !fillClockwise) * 360f * Mathf.Deg2Rad) / 2.0f -
                                 0.5f;
                }
                // top
                else
                {
                    tempPointX = Mathf.Sin(Trans01(fillAmount, !fillClockwise) * 360f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                    tempPointY = Mathf.Cos(Trans01(fillAmount, fillClockwise) * 360f * Mathf.Deg2Rad) / 2.0f + 0.5f;
                }

                if (onSide)
                {
                    deltaX = tempPointX - point0X;
                    deltaY = tempPointY - point0Y;
                    absX = Mathf.Abs(deltaX);
                    absY = Mathf.Abs(deltaY);
                    if (absX > absY)
                    {
                        tempPointY = deltaY * (0.5f / absX) + point0Y;
                        tempPointX = deltaX >= 0 ? 1 : 0;
                    }
                    else
                    {
                        tempPointX = deltaX * (0.5f / absY) + point0X;
                        tempPointY = deltaY >= 0 ? 1 : 0;
                    }
                }

                break;
            default:
                throw new ArgumentOutOfRangeException();
        }

        // 旋转
        _tempRotate = new Vector3(0, 0,
            Mathf.Atan((tempPointY - point0Y) / (tempPointX - point0X)) * Mathf.Rad2Deg + (flip ? (-90) : 90));
        // [0,180]->[0,360]
        if (tempPointX - point0X < 0)
        {
            _tempRotate.z += 180;
        }

        // offset
        Vector2 vector2 = new Vector2(tempPointX - point0X, tempPointY - point0Y);
        vector2 *= offset;
        tempPointX = vector2.x + point0X;
        tempPointY = vector2.y + point0Y;

        // 设置点位
        _points = new[]
        {
            new Vector2(point0X, point0Y),
            new Vector2((point0X + tempPointX) / 2, (point0Y + tempPointY) / 2),
            new Vector2(tempPointX, tempPointY),
        };

        // 对应到ui点上(测试点位)
        for (int i = 0; i < pointImages.Length; i++)
        {
            pointImages[i].rectTransform.anchoredPosition = new Vector2(
                (_points[i].x - 0.5f) * _rectTransform.sizeDelta.x + _rectTransform.anchoredPosition.x,
                (_points[i].y - 0.5f) * _rectTransform.sizeDelta.y + _rectTransform.anchoredPosition.y);
            pointImages[i].transform.rotation = Quaternion.Euler(_tempRotate);
        }
    }

    private void SetObjPosition()
    {
        if (!obj) return;
        var sizeDelta = _rectTransform.sizeDelta;
        var position = _rectTransform.transform.localPosition;
        obj.GetComponent<RectTransform>().transform.localPosition = new Vector2(
            (_points[2].x - 0.5f) * sizeDelta.x + position.x,
            (_points[2].y - 0.5f) * sizeDelta.y + position.y);
        obj.GetComponent<RectTransform>().transform.rotation = Quaternion.Euler(_tempRotate);
    }

    private float Trans01(float value, bool needTrans)
    {
        if (needTrans)
            return 1 - value;
        return value;
    }
}
上一篇:转:浅谈UNIX下Apache的MPM及httpd.conf配置文件中相关参数配置


下一篇:C#中常用的公式总结