// 滚动到指定下标 public void scroll(int index, float time) { if (mItemList.Count == 0) { return; } clampMin(ref time, 0.05f); clamp(ref index, 0, mItemList.Count - 1); // 设置目标值 mTargetOffsetValue = mContainerList[mDefaultFocus].getControlValue() - mItemList[index].getCurControlValue(); if (mLoop) { clampCycle(ref mCurOffset, 0, mMaxControlValue, mMaxControlValue, false); clampCycle(ref mTargetOffsetValue, 0, mMaxControlValue, mMaxControlValue, false); } if (mLoop && abs(mTargetOffsetValue - mCurOffset) > mMaxControlValue * 0.5f) { // 当起始值与目标值差值超过了最大值的一半时,则以当前值为基准,调整目标值的范围 clampCycle(ref mCurOffset, -mMaxControlValue * 0.5f, mMaxControlValue * 0.5f, mMaxControlValue, false); clampCycle(ref mTargetOffsetValue, -mMaxControlValue * 0.5f, mMaxControlValue * 0.5f, mMaxControlValue, false); } mScrollSpeed = (mTargetOffsetValue - mCurOffset) / time; mState = isFloatZero(mScrollSpeed) ? SCROLL_STATE.NONE : SCROLL_STATE.SCROLL_TARGET; mOnScrollItem?.Invoke(mItemList[index], index); }
protected float mDragSensitive = 0.01f; // 拖动的灵敏度 public Scroll(LayoutScript script) { mScript = script; mLoop = false; mState = SCROLL_STATE.SS_NONE; mContainerList = new List <IScrollContainer>(); mItemList = new List <IScrollItem>(); }
protected float mScrollSpeed; // 当前滚动速度 public NGUIScroll(LayoutScript script) { mScript = script; mState = SCROLL_STATE.SS_NONE; mDragDirection = DRAG_DIRECTION.DD_HORIZONTAL; mContainerList = new List <IScrollContainer>(); mItemList = new List <IScrollItem>(); }
// 鼠标在屏幕上抬起 protected void onScreenMouseUp(Vector2 mousePos) { mMouseDown = false; // 正在拖动时鼠标抬起,则开始逐渐减速到0 if (mState == SCROLL_STATE.SS_DRAGING) { mState = SCROLL_STATE.SS_SCROLL_TO_STOP; } }
// 鼠标在屏幕上抬起 protected void onScreenMouseUp(IMouseEventCollect obj, Vector2 mousePos) { mMouseDown = false; // 正在拖动时鼠标抬起,则开始逐渐减速到0 if (mState == SCROLL_STATE.DRAGING) { mState = SCROLL_STATE.SCROLL_TO_STOP; } }
protected bool mMouseDown; // 鼠标是否在窗口内按下,鼠标抬起或者离开窗口都会设置为false,鼠标按下时,跟随鼠标移动,鼠标放开时,按惯性移动 public UGUIScroll(LayoutScript script) { mScript = script; mState = SCROLL_STATE.NONE; mDragDirection = DRAG_DIRECTION.HORIZONTAL; mContainerList = new List <IScrollContainer>(); mItemList = new List <IScrollItem>(); mItemOnCenter = true; mFocusSpeedThreshhold = 2.0f; mDragSensitive = 1.0f; mAttenuateFactor = 2.0f; }
// 滚动到指定下标 public void scroll(int index, float time) { clamp(ref index, 0, mItemList.Count - 1); // 设置目标值 mTargetOffsetValue = mContainerList[mDefaultFocus].getControlValue() - mItemList[index].getCurControlValue(); if (mLoop) { if (Mathf.Abs(mTargetOffsetValue - mCurOffsetValue) > mMaxControlValue / 2.0f) { clampValue(ref mTargetOffsetValue, 0.0f, mMaxControlValue, mMaxControlValue); clampValue(ref mCurOffsetValue, 0.0f, mMaxControlValue, mMaxControlValue); } } mScrollSpeed = (mTargetOffsetValue - mCurOffsetValue) / time; if (!isFloatZero(mScrollSpeed)) { mState = SCROLL_STATE.SS_SCROLL_TARGET; } }
protected void onMouseDown(Vector2 mousePos) { mMouseDown = true; mState = SCROLL_STATE.SS_DRAGING; mScrollSpeed = 0.0f; }
public void update(float elapsedTime) { // 自动匀速滚动到目标点 if (mState == SCROLL_STATE.SS_SCROLL_TARGET) { int preSign = sign(mTargetOffsetValue - mCurOffsetValue); mCurOffsetValue += elapsedTime * mScrollSpeed; int curSign = sign(mTargetOffsetValue - mCurOffsetValue); int speedSign = sign(mScrollSpeed); if (isFloatEqual(mTargetOffsetValue, mCurOffsetValue) || preSign != curSign && preSign == speedSign) { mCurOffsetValue = mTargetOffsetValue; mState = SCROLL_STATE.SS_NONE; } updateItem(mCurOffsetValue); } // 鼠标拖动 else if (mState == SCROLL_STATE.SS_DRAGING) { float curOffset = mContainerList[mDefaultFocus].getControlValue() - mCurOffsetValue; if (mDragDirection == DRAG_DIRECTION.DD_HORIZONTAL) { scroll(curOffset + elapsedTime * mScrollSpeed); } else if (mDragDirection == DRAG_DIRECTION.DD_VERTICAL) { scroll(curOffset + elapsedTime * mScrollSpeed); } } // 鼠标抬起后自动减速到停止 else if (mState == SCROLL_STATE.SS_SCROLL_TO_STOP) { if (!isFloatZero(mScrollSpeed)) { mScrollSpeed = lerp(mScrollSpeed, 0.0f, elapsedTime * mAttenuateFactor, 0.1f); float curOffset = mContainerList[mDefaultFocus].getControlValue() - mCurOffsetValue; scroll(curOffset + elapsedTime * mScrollSpeed); // 当速度小于一定值时才开始选择聚焦到某一项 if (mItemOnCenter) { if (Mathf.Abs(mScrollSpeed) < mFocusSpeedThreshhold) { int focusIndex = getItemIndex(curOffset, true, mLoop); if (focusIndex < 0 || focusIndex >= mItemList.Count) { focusIndex = 0; } float focusTime = Mathf.Abs((curOffset - mItemList[focusIndex].getCurControlValue()) / mScrollSpeed); clampMax(ref focusTime, 1.0f); scroll(focusIndex, focusTime); mState = SCROLL_STATE.SS_SCROLL_TARGET; } } // 逐渐减速到0 else { if (isFloatZero(mScrollSpeed)) { mState = SCROLL_STATE.SS_NONE; } } } // 被意外停止,则回到初始状态 else { if (mItemOnCenter) { float curOffset = mContainerList[mDefaultFocus].getControlValue() - mCurOffsetValue; int focusIndex = getItemIndex(curOffset, true, mLoop); scroll(focusIndex, 0.3f); mState = SCROLL_STATE.SS_SCROLL_TARGET; } else { mState = SCROLL_STATE.SS_NONE; } } } }
public void update(float elapsedTime) { // 自动匀速滚动到目标点 if (mState == SCROLL_STATE.SCROLL_TARGET) { float preOffset = mCurOffset; float newSpeed = sign(mTargetOffsetValue - mCurOffset) * abs(mScrollSpeed); mCurOffset += elapsedTime * newSpeed; if (isReachTarget(preOffset, mCurOffset, mTargetOffsetValue, newSpeed)) { mCurOffset = mTargetOffsetValue; mState = SCROLL_STATE.NONE; } updateItem(mCurOffset); } // 鼠标拖动 else if (mState == SCROLL_STATE.DRAGING) { float curOffset = mContainerList[mDefaultFocus].getControlValue() - mCurOffset; scroll(curOffset + elapsedTime * mScrollSpeed, false); } // 鼠标抬起后自动减速到停止 else if (mState == SCROLL_STATE.SCROLL_TO_STOP) { float curControlValue = mContainerList[mDefaultFocus].getControlValue() - mCurOffset; // 非循环模式下,当前偏移值小于0或者大于最大值时,需要回到正常的范围,偏移值越小,减速越快 bool autoClamp = !mLoop && !inRange(curControlValue, 0.0f, mMaxControlValue, true); if (!isFloatZero(mScrollSpeed)) { if (autoClamp) { float delta = 0.0f; if (curControlValue < 0.0f) { delta = 1.0f - curControlValue * 10.0f; } else if (curControlValue > mMaxControlValue) { delta = 1.0f + (curControlValue - mMaxControlValue) * 10.0f; } mScrollSpeed = lerp(mScrollSpeed, 0.0f, elapsedTime * mAttenuateFactor * delta * delta * 200.0f, 0.1f); } else { mScrollSpeed = lerp(mScrollSpeed, 0.0f, elapsedTime * mAttenuateFactor, 0.1f); } curControlValue += elapsedTime * mScrollSpeed; scroll(curControlValue, false); // 当速度小于一定值时才开始选择聚焦到某一项 if (mItemOnCenter) { if (autoClamp) { if (isFloatZero(mScrollSpeed)) { scrollToTarget(curControlValue, 0.1f, false); } } else { if (abs(mScrollSpeed) < mFocusSpeedThreshhold) { scrollToTarget(curControlValue); } } } // 逐渐减速到0 else { if (isFloatZero(mScrollSpeed)) { if (autoClamp) { scrollToTarget(curControlValue, 0.1f, false); } else { mState = SCROLL_STATE.NONE; } } } } // 鼠标停止后才抬起结束拖拽 else { // 超出范围则回到正常范围内 if (autoClamp) { scrollToTarget(curControlValue, 0.1f, false); } else { if (mItemOnCenter) { scrollToTarget(curControlValue); } else { mState = SCROLL_STATE.NONE; } } } } }