[add] Engine
This commit is contained in:
75
assets/Script/Engine/Utils/ScrollView/ScrollBase.ts
Normal file
75
assets/Script/Engine/Utils/ScrollView/ScrollBase.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { CoroutineV2 } from "../../CatanEngine/CoroutineV2/CoroutineV2";
|
||||
import UIPanel from "../../Component/UIPanel/UIPanel";
|
||||
import ScrollItem from "./ScrollItem";
|
||||
import UISuperLayout from "./UISuperLayout";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
/** Scroll基底 */
|
||||
@ccclass
|
||||
export default class ScrollBase extends UIPanel {
|
||||
//#region 外調參數
|
||||
|
||||
@property({ displayName: "List", type: UISuperLayout })
|
||||
public List: UISuperLayout = null;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region public
|
||||
|
||||
/** ListData */
|
||||
public get ListData(): any[] { throw new Error("ListData必須被override"); }
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region protected
|
||||
|
||||
/** 列表資料 */
|
||||
protected _listData: any[] = [];
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region ScrollView Function
|
||||
|
||||
/**
|
||||
* 創建/刷新列表
|
||||
* @param isScrollTo 0 不滾動
|
||||
* @param isScrollTo 1 滚动到头部
|
||||
* @param isScrollTo 2 滚动到尾部
|
||||
* @param isScrollTo 3 自动居中到最近Item
|
||||
*/
|
||||
public *CreateList(isScrollTo: number = 0): IterableIterator<any> {
|
||||
if (!this.node.active) {
|
||||
return;
|
||||
}
|
||||
this.List?.CreateItem(this.ListData.length);
|
||||
yield CoroutineV2.WaitTime(5 / cc.game.getFrameRate());
|
||||
switch (isScrollTo) {
|
||||
case 1: {
|
||||
this.List?.scrollToHeader(0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
this.List?.scrollToFooter(0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: {
|
||||
this.List?.scrollToCenter();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public OnRefreshEvent(node: cc.Node, index: number): void {
|
||||
let listData: any[] = this.ListData;
|
||||
let info: any = listData[index];
|
||||
node.getComponent(ScrollItem).ImplementSet(info, this, index);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
10
assets/Script/Engine/Utils/ScrollView/ScrollBase.ts.meta
Normal file
10
assets/Script/Engine/Utils/ScrollView/ScrollBase.ts.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "3e607467-693c-46a9-ac93-ab973e52024d",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
8
assets/Script/Engine/Utils/ScrollView/ScrollItem.ts
Normal file
8
assets/Script/Engine/Utils/ScrollView/ScrollItem.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
@ccclass
|
||||
export default class ScrollItem extends cc.Component {
|
||||
ImplementSet(...iniData: any[]): void {
|
||||
//
|
||||
}
|
||||
}
|
10
assets/Script/Engine/Utils/ScrollView/ScrollItem.ts.meta
Normal file
10
assets/Script/Engine/Utils/ScrollView/ScrollItem.ts.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "0a733d8c-80ae-4e0b-be1b-07dba226c237",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
1460
assets/Script/Engine/Utils/ScrollView/UISuperLayout.ts
Normal file
1460
assets/Script/Engine/Utils/ScrollView/UISuperLayout.ts
Normal file
File diff suppressed because it is too large
Load Diff
10
assets/Script/Engine/Utils/ScrollView/UISuperLayout.ts.meta
Normal file
10
assets/Script/Engine/Utils/ScrollView/UISuperLayout.ts.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "67f1a0e4-877e-4ad0-bc1b-e1175c620ca1",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
547
assets/Script/Engine/Utils/ScrollView/UISuperScrollView.ts
Normal file
547
assets/Script/Engine/Utils/ScrollView/UISuperScrollView.ts
Normal file
@@ -0,0 +1,547 @@
|
||||
import UISuperLayout from "./UISuperLayout";
|
||||
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
const quintEaseOut: (time: number) => number = (time: number) => {
|
||||
time -= 1;
|
||||
return (time * time * time * time * time + 1);
|
||||
};
|
||||
const EPSILON = 1e-4;
|
||||
const OUT_OF_BOUNDARY_BREAKING_FACTOR = 0.05;
|
||||
var _tempVec2: cc.Vec2 = new cc.Vec2();
|
||||
export enum ScrollViewDirection {
|
||||
HORIZONTAL,
|
||||
VERTICAL,
|
||||
NONE,
|
||||
}
|
||||
|
||||
@ccclass
|
||||
export default class UISuperScrollview extends cc.ScrollView {
|
||||
private direction: ScrollViewDirection = ScrollViewDirection.NONE;
|
||||
private _layout: UISuperLayout;
|
||||
@property({
|
||||
tooltip: "注意!向上传递事件只会发送当前滑动相反方向,如果开启horizontal则会发送vertical事件。如果开启vertical则会发送horizontal事件。同时开启horizontal和vertical 不会发送任何事件"
|
||||
}) isTransmitEvent: boolean = false;
|
||||
@property pullRefresh: boolean = false;
|
||||
@property({
|
||||
displayName: "顶部偏移量",
|
||||
tooltip: "下拉时超过此偏移会发送下拉事件",
|
||||
visible: function () { return (this as any).pullRefresh; }
|
||||
}) headerOutOffset: number = 200;
|
||||
@property({
|
||||
displayName: "满足触发Header的倍数",
|
||||
visible: function () { return (this as any).pullRefresh; }
|
||||
}) headerMultiple: number = 2;
|
||||
@property({
|
||||
displayName: "底部偏移量",
|
||||
tooltip: "上拉时超过此偏移会发送上拉事件",
|
||||
visible: function () { return (this as any).pullRefresh; }
|
||||
}) footerOutOffset: number = 200;
|
||||
@property({
|
||||
displayName: "满足触发Footer的倍数",
|
||||
visible: function () { return (this as any).pullRefresh; }
|
||||
}) footerMultiple: number = 2;
|
||||
@property({
|
||||
type: cc.Component.EventHandler,
|
||||
visible: function () { return (this as any).pullRefresh; }
|
||||
}) headerEvents: cc.Component.EventHandler[] = [];
|
||||
@property({
|
||||
type: cc.Component.EventHandler,
|
||||
visible: function () { return (this as any).pullRefresh; }
|
||||
}) footerEvents: cc.Component.EventHandler[] = [];
|
||||
prevLocation: cc.Vec2 = new cc.Vec2();
|
||||
location: cc.Vec2 = new cc.Vec2();
|
||||
set autoScrolling(value: boolean) { (this as any)._autoScrolling = value; }
|
||||
private _touchBeganPosition = new cc.Vec2();
|
||||
private _touchEndPosition = new cc.Vec2();
|
||||
private isMoveHeader: boolean = false;
|
||||
private isMoveFooter: boolean = false;
|
||||
private isLockHeader: boolean = false;
|
||||
private isLockFooter: boolean = false;
|
||||
private headerProgress: number = 0;
|
||||
private footerProgress: number = 0;
|
||||
private isCustomScroll: boolean = false;
|
||||
canTouchMove: boolean = true;
|
||||
get view(): cc.Node { return this["_view"]; }
|
||||
onLoad() {
|
||||
if (this.layout && this.layout.autoCenter) {
|
||||
this.brake = 0.7;
|
||||
}
|
||||
}
|
||||
public onEnable() {
|
||||
super.onEnable();
|
||||
this.node.on("scroll-ended-with-threshold", this.dispatchPageTurningEvent, this);
|
||||
}
|
||||
public onDisable() {
|
||||
super.onDisable();
|
||||
this.node.off("scroll-ended-with-threshold", this.dispatchPageTurningEvent, this);
|
||||
}
|
||||
get layout() {
|
||||
if (!this._layout) {
|
||||
this._layout = this.content && this.content.getComponent(UISuperLayout);
|
||||
}
|
||||
return this._layout;
|
||||
}
|
||||
private isCallSoonFinish: boolean = false;
|
||||
get _curPageIdx() {
|
||||
return this.layout["_currPageIndex"];
|
||||
}
|
||||
getPages() {
|
||||
return new Array(this.layout.itemTotal);
|
||||
}
|
||||
protected _getContentTopBoundary() {
|
||||
if (!this.content) {
|
||||
return -1;
|
||||
}
|
||||
let offset = this.layout.isOfTopBoundary == 0 ? this["_topBoundary"] : this.layout.isOfTopBoundary;
|
||||
return offset;
|
||||
}
|
||||
protected _getContentBottomBoundary() {
|
||||
if (!this.content) {
|
||||
return -1;
|
||||
}
|
||||
let offset = this.layout.isOfButtomBoundary == 0 ? this["_bottomBoundary"] : this.layout.isOfButtomBoundary;
|
||||
return offset;
|
||||
}
|
||||
protected _getContentLeftBoundary() {
|
||||
if (!this.content) {
|
||||
return -1;
|
||||
}
|
||||
let offset = this.layout.isOfLeftBoundary == 0 ? this["_leftBoundary"] : this.layout.isOfLeftBoundary;
|
||||
return offset;
|
||||
}
|
||||
protected _getContentRightBoundary() {
|
||||
if (!this.content) {
|
||||
return -1;
|
||||
}
|
||||
let offset = this.layout.isOfRightBoundary == 0 ? this["_rightBoundary"] : this.layout.isOfRightBoundary;
|
||||
return offset;
|
||||
}
|
||||
|
||||
public _onTouchBegan(event: cc.Event.EventTouch, captureListeners?: Node[]): void {
|
||||
this.isCallSoonFinish = false;
|
||||
this.isCustomScroll = false;
|
||||
this.layout["onTouchBegin"]();
|
||||
if (!this.canTouchMove) {
|
||||
return;
|
||||
}
|
||||
this.direction = ScrollViewDirection.NONE;
|
||||
if (this.layout.isPageView) {
|
||||
_tempVec2 = event.getLocation();
|
||||
// cc.Vec2.set(this._touchBeganPosition, _tempVec2.x, _tempVec2.y)
|
||||
this._touchBeganPosition = cc.v2(_tempVec2.x, _tempVec2.y);
|
||||
}
|
||||
super["_onTouchBegan"](event, captureListeners);
|
||||
if (this.isTransmitEvent) {
|
||||
this.transmitEvent(event, cc.Node.EventType.TOUCH_START);
|
||||
}
|
||||
}
|
||||
public _onTouchMoved(event: cc.Event.EventTouch, captureListeners: any) {
|
||||
this.isCallSoonFinish = false;
|
||||
this.isCustomScroll = false;
|
||||
|
||||
if (!this.canTouchMove) return;
|
||||
if (this.isTransmitEvent) {
|
||||
if (this.direction == ScrollViewDirection.NONE) {
|
||||
var start = event.getStartLocation();
|
||||
var curre = event.getLocation();
|
||||
var xOffset = Math.abs(start.x - curre.x);
|
||||
var yOffset = Math.abs(start.y - curre.y);
|
||||
if (xOffset > yOffset) {
|
||||
// 本ScrollView滑动方向过程中达到一定偏移量是也可以向上发送事件
|
||||
// if (this.vertical) {
|
||||
// if (xOffset - yOffset > 50) {
|
||||
// this.direction = UIScrollViewDirection.HORIZONTAL
|
||||
// }
|
||||
// }
|
||||
this.direction = ScrollViewDirection.HORIZONTAL;
|
||||
|
||||
} else if (yOffset > xOffset) {
|
||||
// 本ScrollView滑动方向过程中达到一定偏移量是也可以向上发送事件
|
||||
// if (this.horizontal) {
|
||||
// if (yOffset - xOffset > 50) {
|
||||
// this.direction = UIScrollViewDirection.VERTICAL
|
||||
// }
|
||||
// }
|
||||
this.direction = ScrollViewDirection.VERTICAL;
|
||||
}
|
||||
}
|
||||
var canTransmit = (this.vertical && this.direction === ScrollViewDirection.HORIZONTAL) || this.horizontal && this.direction == ScrollViewDirection.VERTICAL;
|
||||
if (canTransmit) {
|
||||
this.transmitEvent(event, cc.Node.EventType.TOUCH_MOVE);
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.prevLocation = event.touch.getPreviousLocation();
|
||||
this.location = event.touch.getLocation();
|
||||
super["_onTouchMoved"](event, captureListeners);
|
||||
if (this.pullRefresh) {
|
||||
let outOfBoundary = this["_getHowMuchOutOfBoundary"]();
|
||||
let offset = this.vertical ? outOfBoundary.y : -outOfBoundary.x;
|
||||
if (offset > 0 && !this.isLockHeader && !this.isLockFooter) {
|
||||
this.headerProgress = offset < EPSILON ? 0 : offset / this.headerOutOffset;
|
||||
this.isMoveHeader = this.headerProgress >= this.headerMultiple;
|
||||
cc.Component.EventHandler.emitEvents(this.headerEvents, this, { action: false, progress: this.headerProgress, stage: this.isMoveHeader ? "wait" : "touch" });
|
||||
cc.Component.EventHandler.emitEvents(this.footerEvents, this, { action: false, progress: 0, stage: "release" });
|
||||
} else if (offset < 0 && !this.isLockHeader && !this.isLockFooter) {
|
||||
this.footerProgress = -offset < EPSILON ? 0 : -offset / this.footerOutOffset;
|
||||
this.isMoveFooter = this.footerProgress >= this.footerMultiple;
|
||||
cc.Component.EventHandler.emitEvents(this.footerEvents, this, { action: false, progress: this.footerProgress, stage: this.isMoveFooter ? "wait" : "touch" });
|
||||
cc.Component.EventHandler.emitEvents(this.headerEvents, this, { action: false, progress: 0, stage: "release" });
|
||||
} else if (offset == 0 && !this.isLockHeader && !this.isLockFooter) {
|
||||
this.clearProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public _onTouchEnded(event: cc.Event.EventTouch, captureListeners: any) {
|
||||
this.isCallSoonFinish = false;
|
||||
this.isCustomScroll = false;
|
||||
if (!this.canTouchMove) return;
|
||||
if (this.layout.isPageView) {
|
||||
_tempVec2 = event.getLocation();
|
||||
// cc.Vec2.set(this._touchEndPosition, _tempVec2.x, _tempVec2.y)
|
||||
this._touchEndPosition = cc.v2(_tempVec2.x, _tempVec2.y);
|
||||
}
|
||||
super["_onTouchEnded"](event, captureListeners);
|
||||
if (this.isTransmitEvent) {
|
||||
this.transmitEvent(event, cc.Node.EventType.TOUCH_END);
|
||||
}
|
||||
}
|
||||
public _onTouchCancelled(event: cc.Event.EventTouch, captureListeners: any) {
|
||||
this.isCallSoonFinish = false;
|
||||
this.isCustomScroll = false;
|
||||
if (!this.canTouchMove) return;
|
||||
if (this.layout.isPageView) {
|
||||
_tempVec2 = event.getLocation();
|
||||
// cc.Vec2.set(this._touchEndPosition, _tempVec2.x, _tempVec2.y)
|
||||
this._touchEndPosition = cc.v2(_tempVec2.x, _tempVec2.y);
|
||||
}
|
||||
if (this.isTransmitEvent) {
|
||||
this.transmitEvent(event, cc.Node.EventType.TOUCH_CANCEL);
|
||||
}
|
||||
super["_onTouchCancelled"](event, captureListeners);
|
||||
}
|
||||
scrollToAny(moveDelta: cc.Vec2, timeInSecond?: number, attenuated: boolean = true) {
|
||||
this.isCustomScroll = true;
|
||||
if (timeInSecond) {
|
||||
this._startAutoScroll(moveDelta, timeInSecond, attenuated, true);
|
||||
} else {
|
||||
this["_moveContent"](moveDelta);
|
||||
}
|
||||
}
|
||||
release() {
|
||||
this.isMoveHeader = false;
|
||||
this.isMoveFooter = false;
|
||||
if (this.isLockHeader || this.isLockFooter) {
|
||||
this.vertical && this.isLockHeader && (this["_topBoundary"] += this.headerOutOffset);
|
||||
this.vertical && this.isLockFooter && (this["_bottomBoundary"] -= this.footerOutOffset);
|
||||
this.horizontal && this.isLockHeader && (this["_leftBoundary"] -= this.headerOutOffset);
|
||||
this.horizontal && this.isLockFooter && (this["_rightBoundary"] += this.footerOutOffset);
|
||||
this.clearProgress();
|
||||
this.layout["onPositionChanged"]();
|
||||
this.isLockHeader = false;
|
||||
this.isLockFooter = false;
|
||||
this.startAutoScroll();
|
||||
}
|
||||
}
|
||||
startAutoScroll() {
|
||||
this["_autoScrolling"] = true;
|
||||
this["_outOfBoundaryAmountDirty"] = true;
|
||||
}
|
||||
protected _startAutoScroll(deltaMove: any, timeInSecond: any, attenuated: any, flag: boolean = false) {
|
||||
if (this.pullRefresh) { // 如果没有刷新/加载的监听者 则不计算
|
||||
if (this.isMoveHeader && !this.isLockHeader) {
|
||||
if (this.vertical) {
|
||||
this["_topBoundary"] -= this.headerOutOffset;
|
||||
deltaMove.y -= this.headerOutOffset;
|
||||
}
|
||||
if (this.horizontal) {
|
||||
this["_leftBoundary"] += this.headerOutOffset;
|
||||
deltaMove.x += this.headerOutOffset;
|
||||
}
|
||||
this.isLockHeader = true;
|
||||
cc.Component.EventHandler.emitEvents(this.headerEvents, this, { action: true, progress: this.headerProgress, stage: 'lock' });
|
||||
} else if (this.isMoveFooter && !this.isLockFooter) {
|
||||
if (this.vertical) {
|
||||
this["_bottomBoundary"] += this.footerOutOffset;
|
||||
deltaMove.y += this.footerOutOffset;
|
||||
}
|
||||
if (this.horizontal) {
|
||||
this["_rightBoundary"] -= this.footerOutOffset;
|
||||
deltaMove.x -= this.footerOutOffset;
|
||||
}
|
||||
this.isLockFooter = true;
|
||||
cc.Component.EventHandler.emitEvents(this.footerEvents, this, { action: true, progress: this.footerProgress, stage: 'lock' });
|
||||
}
|
||||
}
|
||||
|
||||
super["_startAutoScroll"](deltaMove, timeInSecond, attenuated);
|
||||
if (!flag && this.layout.autoCenter) {
|
||||
const touchMoveVelocity = this["_calculateTouchMoveVelocity"]();
|
||||
if (!this.isQuicklyScrollable(touchMoveVelocity)) {
|
||||
this.soonFinish();
|
||||
}
|
||||
}
|
||||
}
|
||||
protected _updateScrollBar(outOfBoundary: any) {
|
||||
super["_updateScrollBar"](cc.v2(outOfBoundary.x, outOfBoundary.y));
|
||||
if (this["_autoScrollBraking"]) return; // 自动回弹时不计算 (非手动)
|
||||
if (!this["_autoScrolling"]) return; // 非自动滚动时不计算
|
||||
if (!this.pullRefresh) return;
|
||||
let offset = this.vertical ? outOfBoundary.y : -outOfBoundary.x;
|
||||
if (offset > 0) { // 下滑
|
||||
let progress = offset < EPSILON ? 0 : offset / this.headerOutOffset; //根据参数 headerOutOffset 计算当前下滑的办百分比
|
||||
if (this.isLockHeader) {
|
||||
this.headerProgress = this.headerProgress == 1 ? this.headerProgress : Math.max(progress, 1);
|
||||
cc.Component.EventHandler.emitEvents(this.headerEvents, this, { action: false, progress: this.headerProgress, stage: "lock" });
|
||||
} else {
|
||||
this.headerProgress = progress < this.headerProgress ? progress : this.headerProgress;
|
||||
cc.Component.EventHandler.emitEvents(this.headerEvents, this, { action: false, progress: this.headerProgress, stage: "release" });
|
||||
}
|
||||
} else if (offset < 0) {
|
||||
let progress = -offset < EPSILON ? 0 : -offset / this.footerOutOffset; //根据参数 footerOutOffset 计算当前下滑的办百分比
|
||||
if (this.isLockFooter) {
|
||||
this.footerProgress = this.footerProgress == 1 ? this.footerProgress : Math.max(progress, 1);
|
||||
cc.Component.EventHandler.emitEvents(this.footerEvents, this, { action: false, progress: this.footerProgress, stage: "lock" });
|
||||
} else {
|
||||
this.footerProgress = progress < this.footerProgress ? progress : this.footerProgress;
|
||||
cc.Component.EventHandler.emitEvents(this.footerEvents, this, { action: false, progress: this.footerProgress, stage: "release" });
|
||||
}
|
||||
} else if (offset == 0) {
|
||||
// 正常滑动时 如果没有锁定头和尾时 释放所有进度
|
||||
if (!this.isLockHeader && !this.isLockFooter) {
|
||||
this.clearProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
private clearProgress() {
|
||||
cc.Component.EventHandler.emitEvents(this.headerEvents, this, { action: false, progress: 0, stage: "release" });
|
||||
cc.Component.EventHandler.emitEvents(this.footerEvents, this, { action: false, progress: 0, stage: "release" });
|
||||
}
|
||||
private dispatchPageTurningEvent() {
|
||||
if (this.layout["_lastPageIndex"] === this.layout["_currPageIndex"]) return;
|
||||
this.layout["_lastPageIndex"] = this.layout["_currPageIndex"];
|
||||
cc.Component.EventHandler.emitEvents(this.layout.pageEvents, this, "page-turning");
|
||||
this.node.emit("page-turning", this);
|
||||
}
|
||||
|
||||
protected _handleReleaseLogic(touch: any) {
|
||||
if (this.layout.isPageView) {
|
||||
this._autoScrollToPage();
|
||||
if (this["_scrolling"]) {
|
||||
this["_scrolling"] = false;
|
||||
if (!this["_autoScrolling"]) {
|
||||
this["_dispatchEvent"](cc.ScrollView.EventType.SCROLL_ENDED);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
super["_handleReleaseLogic"](touch);
|
||||
}
|
||||
|
||||
}
|
||||
protected _autoScrollToPage() {
|
||||
const bounceBackStarted = this["_startBounceBackIfNeeded"]();
|
||||
if (bounceBackStarted) {
|
||||
const bounceBackAmount = this["_getHowMuchOutOfBoundary"]();
|
||||
this["_clampDelta"](bounceBackAmount);
|
||||
if (bounceBackAmount.x > 0 || bounceBackAmount.y < 0) {
|
||||
if (this.layout.horizontal) {
|
||||
if (this.layout.horizontalAxisDirection == UISuperLayout.HorizontalAxisDirection.LEFT_TO_RIGHT) {
|
||||
this.layout["_currPageIndex"] = this.layout.itemTotal === 0 ? 0 : this.layout.itemTotal - 1;
|
||||
} else {
|
||||
this.layout["_currPageIndex"] = 0;
|
||||
}
|
||||
} else {
|
||||
if (this.layout.verticalAxisDirection == UISuperLayout.VerticalAxisDirection.TOP_TO_BOTTOM) {
|
||||
this.layout["_currPageIndex"] = this.layout.itemTotal === 0 ? 0 : this.layout.itemTotal - 1;
|
||||
} else {
|
||||
this.layout["_currPageIndex"] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bounceBackAmount.x < 0 || bounceBackAmount.y > 0) {
|
||||
if (this.layout.horizontal) {
|
||||
if (this.layout.horizontalAxisDirection == UISuperLayout.HorizontalAxisDirection.LEFT_TO_RIGHT) {
|
||||
this.layout["_currPageIndex"] = 0;
|
||||
} else {
|
||||
this.layout["_currPageIndex"] = this.layout.itemTotal === 0 ? 0 : this.layout.itemTotal - 1;
|
||||
}
|
||||
} else {
|
||||
if (this.layout.verticalAxisDirection == UISuperLayout.VerticalAxisDirection.TOP_TO_BOTTOM) {
|
||||
this.layout["_currPageIndex"] = 0;
|
||||
} else {
|
||||
this.layout["_currPageIndex"] = this.layout.itemTotal === 0 ? 0 : this.layout.itemTotal - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.layout.indicator) {
|
||||
this.layout.indicator["_changedState"]();
|
||||
}
|
||||
} else {
|
||||
const moveOffset = new cc.Vec2();
|
||||
// cc.Vec2.subtract(moveOffset, this._touchBeganPosition, this._touchEndPosition)
|
||||
moveOffset.x = this._touchBeganPosition.x - this._touchEndPosition.x;
|
||||
moveOffset.y = this._touchBeganPosition.y - this._touchEndPosition.y;
|
||||
|
||||
|
||||
const index = this.layout["_currPageIndex"];
|
||||
var nextIndex = index + this.getDragDirection(moveOffset);
|
||||
var timeInSecond = this.layout.pageTurningSpeed * Math.abs(index - nextIndex);
|
||||
if (this.layout.footerLoop) {
|
||||
if (nextIndex >= this.layout.itemTotal) {
|
||||
nextIndex = 0;
|
||||
}
|
||||
}
|
||||
if (this.layout.headerLoop) {
|
||||
if (nextIndex < 0) {
|
||||
nextIndex = this.layout.itemTotal - 1;
|
||||
}
|
||||
}
|
||||
const count = this.layout.itemTotal;
|
||||
if (nextIndex < count) {
|
||||
if (this.isScrollable(moveOffset, index, nextIndex)) {
|
||||
this.scrollToPage(nextIndex, timeInSecond);
|
||||
return;
|
||||
} else {
|
||||
const touchMoveVelocity = this["_calculateTouchMoveVelocity"]();
|
||||
if (this.isQuicklyScrollable(touchMoveVelocity)) {
|
||||
this.scrollToPage(nextIndex, timeInSecond);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.scrollToPage(index, timeInSecond);
|
||||
}
|
||||
}
|
||||
savePageIndex(idx: number) {
|
||||
if (idx < 0 || idx >= this.layout.itemTotal) {
|
||||
return false;
|
||||
}
|
||||
this.layout["_currPageIndex"] = idx;
|
||||
if (this.layout.indicator) {
|
||||
this.layout.indicator["_changedState"]();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected scrollToPage(idx: number, timeInSecond = 0.3) {
|
||||
if (idx < 0 || idx >= this.layout.itemTotal) {
|
||||
return;
|
||||
}
|
||||
if (this.savePageIndex(idx)) {
|
||||
this.layout.scrollToIndex(idx, timeInSecond);
|
||||
}
|
||||
}
|
||||
// 快速滑动
|
||||
protected isQuicklyScrollable(touchMoveVelocity: cc.Vec3) {
|
||||
if (this.horizontal) {
|
||||
if (Math.abs(touchMoveVelocity.x) > this.layout.autoPageTurningThreshold) {
|
||||
return true;
|
||||
}
|
||||
} else if (this.vertical) {
|
||||
if (Math.abs(touchMoveVelocity.y) > this.layout.autoPageTurningThreshold) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected getDragDirection(moveOffset: cc.Vec2) {
|
||||
if (this.horizontal) {
|
||||
if (moveOffset.x === 0) {
|
||||
return 0;
|
||||
}
|
||||
if (this.layout.horizontalAxisDirection == UISuperLayout.HorizontalAxisDirection.LEFT_TO_RIGHT) {
|
||||
return (moveOffset.x > 0 ? this.layout.groupItemTotal : -this.layout.groupItemTotal);
|
||||
} else {
|
||||
return (moveOffset.x < 0 ? this.layout.groupItemTotal : -this.layout.groupItemTotal);
|
||||
}
|
||||
} else {
|
||||
// 由于滚动 Y 轴的原点在在右上角所以应该是小于 0
|
||||
if (moveOffset.y === 0) {
|
||||
return 0;
|
||||
}
|
||||
if (this.layout.verticalAxisDirection == UISuperLayout.VerticalAxisDirection.TOP_TO_BOTTOM) {
|
||||
return (moveOffset.y < 0 ? this.layout.groupItemTotal : -this.layout.groupItemTotal);
|
||||
} else {
|
||||
return (moveOffset.y > 0 ? this.layout.groupItemTotal : -this.layout.groupItemTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 是否超过自动滚动临界值
|
||||
protected isScrollable(offset: cc.Vec2, index: number, nextIndex: number) {
|
||||
const viewTrans = this.view;
|
||||
if (!viewTrans) {
|
||||
return false;
|
||||
}
|
||||
if (this.horizontal) {
|
||||
return Math.abs(offset.x) >= viewTrans.width * this.layout.scrollThreshold;
|
||||
} else if (this.vertical) {
|
||||
return Math.abs(offset.y) >= viewTrans.height * this.layout.scrollThreshold;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected transmitEvent(event: any, eventType: string) {
|
||||
var e = new cc.Event.EventTouch(event.getTouches(), event.bubbles);
|
||||
e.type = eventType;
|
||||
e.touch = event.touch;
|
||||
let target: any = event.target;
|
||||
target.parent.dispatchEvent(e);
|
||||
}
|
||||
private soonFinish() {
|
||||
this.isCallSoonFinish = true;
|
||||
this.layout["soonFinish"]();
|
||||
}
|
||||
protected _processAutoScrolling(dt: number) {
|
||||
let isAutoScrollBrake = this["_isNecessaryAutoScrollBrake"]();
|
||||
let brakingFactor = isAutoScrollBrake ? OUT_OF_BOUNDARY_BREAKING_FACTOR : 1;
|
||||
this["_autoScrollAccumulatedTime"] += dt * (1 / brakingFactor);
|
||||
|
||||
let percentage = Math.min(1, this["_autoScrollAccumulatedTime"] / this["_autoScrollTotalTime"]);
|
||||
if (this["_autoScrollAttenuate"]) {
|
||||
percentage = quintEaseOut(percentage);
|
||||
}
|
||||
|
||||
let newPosition = this["_autoScrollStartPosition"].add(this["_autoScrollTargetDelta"].mul(percentage));
|
||||
let reachedEnd = Math.abs(percentage - 1) <= EPSILON;
|
||||
|
||||
let fireEvent = Math.abs(percentage - 1) <= this["getScrollEndedEventTiming"]();
|
||||
if (fireEvent && !this["_isScrollEndedWithThresholdEventFired"]) {
|
||||
this["_dispatchEvent"]('scroll-ended-with-threshold');
|
||||
this["_isScrollEndedWithThresholdEventFired"] = true;
|
||||
}
|
||||
|
||||
if (this.elastic) {
|
||||
let brakeOffsetPosition = newPosition.sub(this["_autoScrollBrakingStartPosition"]);
|
||||
if (isAutoScrollBrake) {
|
||||
brakeOffsetPosition = brakeOffsetPosition.mul(brakingFactor);
|
||||
}
|
||||
newPosition = this["_autoScrollBrakingStartPosition"].add(brakeOffsetPosition);
|
||||
} else {
|
||||
let moveDelta = newPosition.sub(this.getContentPosition());
|
||||
let outOfBoundary = this["_getHowMuchOutOfBoundary"](moveDelta);
|
||||
if (!outOfBoundary.fuzzyEquals(cc.v2(0, 0), EPSILON)) {
|
||||
newPosition = newPosition.add(outOfBoundary);
|
||||
reachedEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (reachedEnd) {
|
||||
this["_autoScrolling"] = false;
|
||||
}
|
||||
if (this.layout.autoCenter && !this.isCallSoonFinish && !this.isCustomScroll) {
|
||||
if (this["_autoScrollTotalTime"] < 2 || percentage >= 0.8) {
|
||||
this.soonFinish();
|
||||
}
|
||||
}
|
||||
let deltaMove = newPosition.sub(this.getContentPosition());
|
||||
this["_moveContent"](this["_clampDelta"](deltaMove), reachedEnd);
|
||||
this["_dispatchEvent"]('scrolling');
|
||||
if (!this["_autoScrolling"]) {
|
||||
this["_isBouncing"] = false;
|
||||
this["_scrolling"] = false;
|
||||
this["_dispatchEvent"]('scroll-ended');
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "dfb04646-c016-4594-b7b3-8d83fa7a925a",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
Reference in New Issue
Block a user