zoukankan      html  css  js  c++  java
  • RectTransform简析

    UGUI简述

      UGUI主要提供了两个能力

    1. UI元素的渲染与适配(其中UI元素的Mesh中的position信息就是通过RectTransform生成的,本文重点)
    2. 设备事件的响应与处理(EventSystem系统,及封装的Button、Toggle等常用组件)

    RectTransform序列化的内容


      也就是说RectTransform是通过这四个属性来确定RectTransform的四个顶点的(position)。

    如何确定顶点信息

    额外属性的含义

    1. anchorMin:左下角锚点距离父节点左下角的标准距离(父节点所确定四个顶点的矩形的左下角看作(0,0),右上角看作(1,1))。
    2. anchorMax:右上角距离父节点左下角的标准距离。
    3. pivot:中心点距离自身所确定的矩形的左下角的标准距离。
    4. sizeDelta:自身所确定的矩形长宽相对于anchorMin、anchorMax所确定的矩形的偏移量(偏移时会按照pivot的比例来偏移,举个例子:pivot是(0.3,pY),sizeDelta是(100, sY),那么自身的矩形左下角会相对于anchorMin负向偏移30,右上角会相对anchorMax正向偏移70,整体将矩形扩大了100。y轴一样)。
    5. anchoredPosition:自身矩形的中心点相对于anchorMin、anchorMax所确定的矩形中心点的位置(或者也可以理解为偏移量,下面会说)

    如何通过这几个参数来确定自身的矩形

      通过一个例子来说明一个RectTransform的形状是如何通过上面的几个参数确定的。
      父节点信息

      子节点信息

    1.确定anchorMin、anchorMax代表的矩形

      父节点的长宽为(1920,1080),子节点的anchorMin为(0.2,0.3),所以如果把父节点矩形的左下角看作原点,那么anchorMin所代标的点的坐标即为(1920 * 0.2,1080 * 0.3),也就是(384,324)。同理,得到anchorMax代表点的坐标(1152,972)。
      也就是一个左下角坐标为(384,324),长宽为(1152 - 384,972 - 324),即(768,648)的矩形。
      用RectTransform来表示的话就是下图这样,anchorMin、anchorMax、pivot都为(0,0),Pos为(384,324),长宽(768,648)。

    2.通过sizeDelta和pivot确定自身矩形的大小

      因为sizeDelta是(100,300),所以接下来对上一步确定的矩形的左下角平移(-100 * 0.4, -300 * 0.5),平移后为(344,174)。右上角的点平移(100 * 0.6, 300 * 0.5),平移后为(1212,1122)。
      用RectTransform来表示的话就是下图这样,anchorMin、anchorMax、pivot都为(0,0),Pos为(344,174),长宽(868,948)。

    3.通过anchoredPosition对自身进行平移

      把上一步确定的矩形平移子节点的anchoredPositino(60,-200)。
      用RectTransform来表示的话就是下图这样,anchorMin、anchorMax、pivot都为(0,0),Pos为(404,-26),长宽(868,948)。
      这个RectTransform所表示的矩形正好可以和子节点的重合,虽然参数不一样。

    注意

      严格来说并不是左下角或者右上角,而是指的anchorMin、anchorMax所确定的点。向左、向右指的是父节点空间内的负方向和正方向。但是因为绝大多数情况下anchorMin的xy坐标会小于anchorMax的xy坐标,这样才是一个几何意义明显的矩形。

    RectTransform的Inspector面板

    1. 就是anchorsMin、anchorsMax、pivot,上面已经说过了,这理解不说了。
    2. 是就是Transform的localRotaion和localScale属性,也没啥好说的。
    3. 这四个数值是对sizeDelta和anchoredPosition的封装。让开发者可以更直观的进行位置和大小的调整。
      具体来说就是左侧的两个值代表了sizeDelta和anchoredPosition的x值,右侧的两个值代表了y值。
      下面就来说一下左边两个值的具体含义,当anchorsMin和anchorsMax的x值相等时,也就是这两个锚点的x坐标重合。这个时候这两个值会变成PosX和Width,其实就是anchoredPosition.x和sizeDelta.x的几何意义。
      anchoreMin和anchoreMax的x值不等时,也就是这两个锚点的x坐标分离时。会变成left,right。分别代表子节点左侧、右侧相对于anchoredMin、Max确定的矩形向内的偏移量,十分直观。其实还是对anchoredPosition.x和sizeDelta.x的封装。
      右边的两个值就对应anchoredPosition.y和sizeDelta.y。
    4. 就是localPosition的z值。在Inspetor中,把localPostion.xy隐藏了,只暴露了z值出来,因为localPositino的xy值一般不会主动去修改,是通过RectorTranform中这几个额外的属性动态算出来的。
    5. 一些预设的常用值,纵向代表y,横向代表x。
    6. 这两个按钮是蓝图模式和原始模式,蓝图模式就是在Scene中的那个小框是把RectTranform包起来,还是展示通过这几个额外属性确定的矩形(不考虑旋转和缩放)


      原始模式就是在调整anchors和pivot的时候是否需要动态调整sizeDelta和anchoredPosition来保持该节点的矩形区域不变。选中时代表不动态调整。

    localPosition与anchoredPosition的关系

      localPosition就是tranform所确定的坐标系原点在父tranform所确定的坐标系下的位置。在RectTransform中,自身所确定的坐标系原点位置在RectTransform确定的矩形的中心。
      所以在RectTranform下,localPosition也可以理解为自身矩形与父节点确定的矩形中心的相对位置(偏移量)。

    localPosition与anchoredPosition的转换

      先建立以父节点左下角为原点的坐标系o。
      定义:
      childPivotPos代表子节点中心点在o中的坐标。
      parentPivotPos代表父节点中心点在o中的坐标。
      anchorsPivotPos代表子节点anchors确定的矩形的中心点在o中的坐标。
      则有:
      localPosition.xy
      = childPivotPos - parentPivotPos
      = (childPivotPos - anchorsPivotPos) + (anchorsPivotPos - parentPivotPos)
      = anchoredPosition + (anchorsPivotPos - parentPivotPos)
      = anchoredPosition + anchorsPivotPos相对于父节点中心的偏移量
      接下来就可以实际上进行计算了。
      定义:
      pSize代表父节点的长宽(除了根Canvas外,其他所有的RectTransform所确定的矩形都是依赖于父节点的。所以我们跳过父节点矩形的计算,直接用rect属性获取父节点长宽)。
      pPivot代表父节点的pivot。
      cAnchorsMin、cAnchorsMax、cPivot代表子节点的anchorsMin、anchorsMax、pivot。
      则有:
      parentPivotPos = Vector2.Scale(pSize, pPivot)
      anchorsPivotPos = Vector2.Scale(pSize, cAnchorsMin) + Vector.Scale(pSize, (cAnchorsMax - cAnchorsMin) * cPivot)
      anchorsPivotPos - parentPivotPos = Vector2.Scale(pSize,cAnchorsMin + (cAnchorsMax - cAnchorsMin) * cPivot - pPivot)
      简单测一下,随便调调父节点和子节点的属性。

    public class PositionTest : MonoBehaviour
    {
        public Vector3 localPosition;
        public Vector2 anchoredPosition;
        public Vector3 delta;
        public Vector3 calculation;
    
        // Update is called once per frame
        void Update()
        {
            var parentRectTrans = (transform.parent as RectTransform);
            var rectTrans = transform as RectTransform;
            localPosition = rectTrans.localPosition;
            anchoredPosition = rectTrans.anchoredPosition;
            //差值
            delta = (Vector2)localPosition - anchoredPosition;
            //通过公式计算的插值
            calculation = Vector2.Scale(
                parentRectTrans.rect.size,
                rectTrans.anchorMin + (rectTrans.anchorMax - rectTrans.anchorMin) * rectTrans.pivot - parentRectTrans.pivot
            );
        }
    }
    

  • 相关阅读:
    【JMeter_14】JMeter逻辑控制器__交替控制器<Interleave Controller>
    【JMeter_13】JMeter逻辑控制器__执行时间控制器<Runtime Controller>
    【JMeter_12】JMeter逻辑控制器__包括控制器<Include Controller>
    【JMeter_11】JMeter逻辑控制器__Switch控制器<Switch Controller>
    【JMeter_10】JMeter逻辑控制器__ForEach控制器<ForEach Controller>
    【JMeter_09】JMeter逻辑控制器__临界部分控制器<Critical Section Controller>
    【JMeter_08】JMeter逻辑控制器__While控制器<While Controller>
    【JMeter_07】JMeter逻辑控制器__循环控制器<Loop Controller>
    【JMeter_06】JMeter逻辑控制器__If控制器<If Controller>
    【JMeter_05】创建第一个简单的接口脚本
  • 原文地址:https://www.cnblogs.com/blueberryzzz/p/13737501.html
Copyright © 2011-2022 走看看