本文原创,转载请注明出处http://www.cnblogs.com/AdvancePikachu/p/7908754.html
前段时间在做一个类似AnimationCurve的可视化编辑器,其中在做内部缩放的时候略有所感,把利用滚轮+焦点的缩放分享一下。
其中一个脚本处理内部逻辑
public class ResizeScrollEvent : UnityEvent<float> { }
public class UIScroll : MonoBehaviour, IScrollHandler
{
public float minFactor = 1;
public float maxFactor = 3;
public bool wholeSizeFactor = true;
private ResizeScrollEvent _onResize = new ResizeScrollEvent();
private float _sizeFactor = 1f;
public ResizeScrollEvent OnResize { get { return _onResize; } }
public float SizeFactor
{
get
{
if (wholeSizeFactor)
return Mathf.Round(_sizeFactor);
return _sizeFactor;
}
set
{
SetFactor(value);
}
}
[SerializeField]
RectTransform content;
[SerializeField]
RectTransform viewport;
Rect _rect;
Vector2 _focusPos;
void Start()
{
_rect = GetWorldRect(viewport);
_focusPos = _rect.center;
}
public static Rect GetWorldRect(RectTransform rt)
{
Vector3[] cors_ = new Vector3[4];
rt.GetWorldCorners(cors_);
Vector2 center = cors_[0];
float width = Mathf.Abs(cors_[0].x - cors_[2].x);
float height = Mathf.Abs(cors_[0].y - cors_[2].y);
Rect rect_ = new Rect(center.x, center.y, width, height);
return rect_;
}
private void SetFactor(float value)
{
value = ClampFactorValue(value);
if (value != _sizeFactor)
{
_sizeFactor = value;
ChangeSizeFactor(_sizeFactor);
_onResize.Invoke(_sizeFactor);
}
}
private void ChangeSizeFactor(float v)
{
Vector2 viewportSize_ = _rect.size;
//缩放过程中的焦点位置(此处为中心位置)
//_focusPos = _rect.center;
Rect contentRect_ = GetWorldRect(content);
Vector2 contentSize_ = contentRect_.size;
Vector2 contentCenter_ = contentRect_.center;
Vector2 contentCenter2ViewportCenter_ = _focusPos - contentCenter_;
float centerPosPercentX_ = contentCenter2ViewportCenter_.x / contentSize_.x;
float centerPosPercentY_ = contentCenter2ViewportCenter_.y / contentSize_.y;
Vector2 scorllSize_ = viewportSize_ + (v - 1) * viewportSize_ / 5;
content.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, scorllSize_.x);
content.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, scorllSize_.y);
Vector2 sizeDelta_ = scorllSize_ - contentSize_;
Vector2 posOffset_ = new Vector2(sizeDelta_.x * -centerPosPercentX_, sizeDelta_.y * -centerPosPercentY_);
content.anchoredPosition += posOffset_;
Vector3[] viewCorner_ = new Vector3[4];
Vector3[] contentCorner_ = new Vector3[4];
viewport.GetWorldCorners(viewCorner_);
content.GetWorldCorners(contentCorner_);
float xFixDelta_ = 0;
float yFixDelta_ = 0;
if (viewCorner_[0].x < contentCorner_[0].x) xFixDelta_ = viewCorner_[0].x - contentCorner_[0].x;
if (viewCorner_[0].y < contentCorner_[0].y) yFixDelta_ = viewCorner_[0].y - contentCorner_[0].y;
if (viewCorner_[2].x > contentCorner_[2].x) xFixDelta_ = viewCorner_[2].x - contentCorner_[2].x;
if (viewCorner_[2].y > contentCorner_[2].y) yFixDelta_ = viewCorner_[2].y - contentCorner_[2].y;
content.anchoredPosition += new Vector2(xFixDelta_, yFixDelta_);
}
private float ClampFactorValue(float value)
{
float factor_ = Mathf.Clamp(value, minFactor, maxFactor);
if (wholeSizeFactor) factor_ = Mathf.Round(factor_);
return factor_;
}
public void OnScroll(PointerEventData eventData)
{
if (!isActiveAndEnabled) return;
_focusPos = eventData.position;//焦点为鼠标所在位置
float delta_ = 0;
if (Mathf.Abs(eventData.scrollDelta.x) > Mathf.Abs(eventData.scrollDelta.y))
delta_ = eventData.scrollDelta.x;
else delta_ = eventData.scrollDelta.y;
SetFactor(_sizeFactor + delta_);
}
}
另一个脚本做触发
public class NewBehaviourScript : MonoBehaviour
{
[SerializeField]
Slider scaleSlider;
[SerializeField]
Text sliderValue;
[SerializeField]
UIScroll scrollView;
void Start ()
{
scaleSlider.wholeNumbers = true;
scaleSlider.minValue = 1;
scaleSlider.maxValue = 10;
scaleSlider.onValueChanged.AddListener(OnSliderValueChange);
scrollView.minFactor = scaleSlider.minValue;
scrollView.maxFactor = scaleSlider.maxValue;
scrollView.wholeSizeFactor = true;
scrollView.OnResize.AddListener(OnScrollResized);
scrollView.SizeFactor = 1;
}
private void OnScrollResized(float value)
{
scaleSlider.value = value;
}
private void OnSliderValueChange(float value)
{
scrollView.SizeFactor = value;
sliderValue.text = value.ToString();
}
}
PS:刚开始以为是版本问题,后来发现是我的Cavans设置有问题,修改后问题解决!
附5.6.4f1项目文件https://files.cnblogs.com/files/AdvancePikachu/scroll.rar