macOs程序坞动画效果支持10000个数据的时候的效果unity实现

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

public struct Padding
{
    public int top, bottom, left, right;
}
public struct Cell
{
    public int number;
    public GameObject go;
}
public class macOsDocker : MonoBehaviour,IPointerMoveHandler,IPointerExitHandler
{
    public ScrollRect scrollRect;
    public List<Transform> listItems = new List<Transform>();
    [Header("半轴的长度(世界坐标)")]
    public float halfRange;
    public float yMaxDis;
    public float maxAddScale;
    public RectTransform contentTrans;
    public RectTransform childParentTrans;
    private Padding offsetPadding;
    public LayoutGroup layoutGroup;
    public RectTransform viewportRectTransform;

    private List<Cell> currentCells = new List<Cell>();
    private List<MacOsCell> unRegularCellList = new List<MacOsCell>();
    private List<GameObject> cachedCells = new List<GameObject>();
    private int currentFirstCol;
    private int currentLastCol;
    private float cellX;
    private float spacingX;
    [Header("不够的时候用什么预制体创建")]
    public GameObject cellPrefab;
    [Header("模拟多少个总数数量")]
    public int totalCount;
    public int FirstCol
    {
        get
        {
            return GetColByX(-contentTrans.anchoredPosition.x - offsetPadding.left);
        }
    }
    private GameObject pendingDestroyGo;
    private void GetListItems()
    {
        listItems.Clear();
        for (int i = 0; i < transform.childCount; i++)
        {
            Transform child = transform.GetChild(i);
            if(child.gameObject.activeSelf)
            {
                listItems.Add(child);
            }
        }
    }
    public int GetColByX(float scrollLeftX)
    {
        if (unRegularCellList.Count <= 0)
        {
            var col = (int)(scrollLeftX / (cellX + spacingX));
            return Mathf.Clamp(col, 0, totalCount - 1);
        }
        else
        {
            var col = (int)(scrollLeftX / (cellX + spacingX));
            var begin = unRegularCellList[0].index;
            if (col <= begin)
            {
                return Mathf.Clamp(col,0,totalCount-1);
            }
            else
            {
                var beginX = begin*(cellX+spacingX);
                for (int i = 0; i < unRegularCellList.Count; i++)
                {
                    var cell = unRegularCellList[i];
                    beginX += (cell.GetRealWidth()+spacingX);
                    if (beginX > scrollLeftX)
                    {
                        return begin + i;
                    }
                }
                col = begin + unRegularCellList.Count;
                var remainCol = (int)((scrollLeftX - beginX) / (cellX + spacingX));
                col += remainCol;
                return Mathf.Clamp(col,0,totalCount-1);
            }
        }
    }
    public int LastCol
    {
        get
        {
            return GetColByX(-contentTrans.anchoredPosition.x + ViewportWidth - offsetPadding.left);
        }
    }
    public float ContentWidth
    {
        get => contentTrans.rect.width;
        private set => contentTrans.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, value);
    }
    public float ViewportWidth => viewportRectTransform.rect.width;
    private void Reset()
    {
        scrollRect = GetComponentInParent<ScrollRect>();
        contentTrans = GetComponent<RectTransform>();
        childParentTrans = contentTrans.GetChild(0) as RectTransform;
        layoutGroup = GetComponent<LayoutGroup>();
        viewportRectTransform = scrollRect.viewport;
    }
    private void Start()
    {
        var rect = cellPrefab.GetComponent<RectTransform>().rect;
        cellX = rect.width;
        spacingX = ((HorizontalOrVerticalLayoutGroup)layoutGroup).spacing;
        scrollRect.onValueChanged.AddListener(OnScroll);
        offsetPadding = new Padding
        {
            top = layoutGroup.padding.top,
            bottom = layoutGroup.padding.bottom,
            left = layoutGroup.padding.left,
            right = layoutGroup.padding.right,
        };
        contentTrans.anchorMin = Vector2.up;
        contentTrans.anchorMax = Vector2.up;
        contentTrans.anchoredPosition = Vector2.zero;
        ContentWidth = cellX * totalCount + spacingX * (totalCount - 1) + offsetPadding.left + offsetPadding.right;
        pendingDestroyGo = new GameObject("[Cache Node]");
        pendingDestroyGo.transform.SetParent(transform);
        pendingDestroyGo.transform.localScale = Vector3.one;
        pendingDestroyGo.SetActive(false);
        //根据totalCount创建
        FirstGenerate();
        GetListItems();
    }
    private void FirstGenerate()
    {
        currentFirstCol = FirstCol;
        currentLastCol = LastCol;

        layoutGroup.padding.left = offsetPadding.left + (currentFirstCol == 0
            ? 0
            : (int)(currentFirstCol * cellX + (currentFirstCol - 1) * spacingX));
        layoutGroup.padding.right = offsetPadding.right + (int)((totalCount - LastCol - 1) * (cellX + spacingX));
        for (var c = currentFirstCol; c <= currentLastCol; ++c)
        {
            var index = c;
            if (index >= totalCount) continue;
            GenerateCell(index);
        }
    }
    private int GetFirstGreater(int index)
    {
        var start = 0;
        var end = currentCells.Count;
        while (start != end)
        {
            var middle = start + (end - start) / 2;
            if (currentCells[middle].number <= index)
            {
                start = middle + 1;
            }
            else
            {
                end = middle;
            }
        }

        return start;
    }
    private void GenerateCell(int index)
    {
        MacOsCell iCell;
        GameObject instance = null;
        if (cachedCells.Count>0)
        {
            instance = cachedCells[0];
            instance.transform.SetParent(childParentTrans);
            cachedCells.RemoveAt(0);
            iCell = instance.GetComponent<MacOsCell>();
        }
        else
        {
            instance = Instantiate(cellPrefab, childParentTrans);
            iCell = instance.GetComponent<MacOsCell>();
        }
        iCell.index = index;
        var order = GetFirstGreater(index);
        instance.transform.SetSiblingIndex(order);
        var cell = new Cell { go = instance, number = index };
        currentCells.Insert(order, cell);
        iCell.gameObject.SetActive(true);
        iCell.SetData();
    }
    private void DestroyCell(int index)
    {
        var order = GetFirstGreater(index - 1);
        var cell = currentCells[order];
        currentCells.RemoveAt(order);
        cell.go.SetActive(false);
        cell.go.transform.SetParent(pendingDestroyGo.transform);
        cachedCells.Add(cell.go);
    }
    private void GenerateCol(int col,bool onLeft)
    {
        var index = col;
        if (index >= totalCount) return;
        GenerateCell(index);

        if (onLeft) layoutGroup.padding.left -= (int)(cellX + spacingX);
        else layoutGroup.padding.right -= (int)(cellX + spacingX);
    }
    private void DestroyCol(int col, bool onLeft)
    {
        var index = col;
        if (index >= totalCount) return;
        DestroyCell(index);
        if (onLeft) layoutGroup.padding.left += (int)(cellX + spacingX);
        else layoutGroup.padding.right += (int)(cellX + spacingX);
    }
    private bool isDraging = false;
    private void RecalcContentWidthBaseRegularCellList()
    {
        int beginIndex = currentCells[0].number;
        float width = beginIndex * cellX + (beginIndex - 1) * spacingX;
        for (int i = 0; i < currentCells.Count; i++)
        {
            MacOsCell cell = currentCells[i].go.GetComponent<MacOsCell>();
            width += cell.GetRealWidth();
            RectTransform child = currentCells[i].go.transform.GetChild(0) as RectTransform;
            if (child.anchoredPosition.y> 0)
            {
                unRegularCellList.Add(cell);
            }
        }
        int remainCount = totalCount - beginIndex - currentCells.Count;
        width += (remainCount * cellX + (remainCount - 1) * spacingX);
        width = width + offsetPadding.left + offsetPadding.right;
        ContentWidth = width;
    }
    private void OnBeginScroll()
    {
        isDraging = true;
        RecalcContentWidthBaseRegularCellList();
    }
    private void OnEndScroll()
    {
        //Debug.LogError($"结束滑动");
        isDraging = false;
        GetListItems();
    }
    void LateUpdate()
    {
        if(isDraging)
        {
            if (Input.GetMouseButtonUp(0))
            {
                OnEndScroll();
            }
        }
    }
    private void OnScroll(Vector2 position)
    {
        if(!isDraging)
        {
            //开始滑动
            OnBeginScroll();
        }
        GetListItems();
        if (currentFirstCol > FirstCol)
        {
            // new left col
            for (var col = currentFirstCol - 1; col >= FirstCol; --col)
            {
                GenerateCol(col, true);
            }

            currentFirstCol = FirstCol;
        }

        if (currentLastCol < LastCol)
        {
            // new right col
            for (var col = currentLastCol + 1; col <= LastCol; ++col)
            {
                GenerateCol(col, false);
            }

            currentLastCol = LastCol;
        }

        if (currentFirstCol < FirstCol)
        {
            // left col invisible
            for (var col = currentFirstCol; col < FirstCol; ++col)
            {
                DestroyCol(col, true);
            }

            currentFirstCol = FirstCol;
        }

        if (currentLastCol > LastCol)
        {
            // right col invisible
            for (var col = currentLastCol; col > LastCol; --col)
            {
                DestroyCol(col, false);
            }

            currentLastCol = LastCol;
        }

    }
    public void OnPointerExit(PointerEventData eventData)
    {
        for (int i = 0; i < listItems.Count; i++)
        {
            listItems[i].transform.localScale = Vector3.one;
            RectTransform childRect = listItems[i].GetChild(0) as RectTransform;
            childRect.anchoredPosition = new Vector3(childRect.anchoredPosition.x, 0, 0);
        }
    }

    public void OnPointerMove(PointerEventData eventData)
    {
        float wPointx = eventData.pointerCurrentRaycast.worldPosition.x;
        float leftX = wPointx - halfRange;
        float rightX = wPointx + halfRange;
        for (int i = 0; i < listItems.Count; i++)
        {
            var tran = listItems[i];
            if (tran.position.x<leftX || tran.position.x>rightX)
            {
                tran.localScale = Vector3.one;
                RectTransform childRect = tran.GetChild(0) as RectTransform;
                childRect.anchoredPosition = new Vector3(childRect.anchoredPosition.x,0,0);
            }
            else
            {
                float rate = (tran.position.x - leftX) / (halfRange * 2);
                float sinValue = Mathf.Sin(rate*Mathf.PI);
                float rate2 = 1 + sinValue * maxAddScale;
                tran.localScale = Vector3.one * rate2;
                RectTransform childRect = tran.GetChild(0) as RectTransform;
                childRect.anchoredPosition = new Vector3(childRect.anchoredPosition.x, sinValue*yMaxDis, 0);
            }
        }
        RectTransform rect = transform as RectTransform;
        LayoutRebuilder.ForceRebuildLayoutImmediate(rect);
        RecalcContentWidthBaseRegularCellList();
    }
}

在这里插入图片描述
要支持10000个数据,必须要使用无尽的重用item的循环列表,但是由于有缩放关系item是不规则尺寸,真实尺寸是item size*缩放,当锚点在左上角的时候滑动scroll rect就是滑动content,content在左侧的x坐标就是相反数就是往左滑动的距离,距离/(cell Size)就是跳过的item数量可以求出当前列表最左边对应数据的index的起点多少,同理求出终点,然后设置数据,由于跟随鼠标的不规则尺寸问题,content的size要滑动的时候要实时计算,拖动是监听scroll rect的onvaluechanged,ondrag和onpointmove是两个事件根据事件上报可以孩子没有实现可以交给父亲处理。
预览视频:https://www.bilibili.com/video/BV1z7vUeEE7t/?vd_source=67191c5099647637079847e343544b3f

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
图像识别技术在病虫害检测中的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像中提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程中,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统中,可以是移动应用、网页服务或集成到智能农业设备中。 7. **实时监测**:在实际应用中,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测中的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JustEasyCode

谢谢您

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值