@senspark/ee
Version:
utility library for cocos creator
136 lines (121 loc) • 4.96 kB
text/typescript
const { ccclass, menu, property } = cc._decorator;
/** Get ancestor nodes that contains cc.ScrollView. */
const getAncestors = (event: cc.Event, node: cc.Node) => {
const targets: cc.Node[] = [];
node._getCapturingTargets(event.type, targets);
const views = targets
.filter(item => item.getComponent(cc.ScrollView) !== null)
.map(item => item.getComponent(cc.ScrollView));
return views;
};
const findBestScrollView = (event: cc.Event.EventTouch, target: cc.Node) => {
const firstView = target.getComponent(cc.ScrollView);
let bestView = firstView; // Assume the first view is the best.
if (bestView.horizontal && bestView.vertical) {
// Already capture both directions.
} else {
const delta = event.touch.getDelta();
// Check all ancestor scroll views.
const ancestors = getAncestors(event, target);
if (bestView.vertical && Math.abs(delta.x) > Math.abs(delta.y)) {
ancestors.some(item => {
if (item.horizontal) {
bestView = item;
return true;
}
return false;
});
}
if (bestView.horizontal && Math.abs(delta.x) < Math.abs(delta.y)) {
ancestors.some(item => {
if (item.vertical) {
bestView = item;
return true;
}
return false;
});
}
}
return bestView;
};
('ee/NestedScrollView')
export class NestedScrollView extends cc.Component {
public onEnable(): void {
const scrollView = this.getComponent(cc.ScrollView);
const listener = this.node._touchListener;
if (listener !== null && scrollView !== null) {
this.setupTouchBegan(listener);
this.setupTouchMoved(listener);
this.setupTouchEnded(listener);
this.setupTouchCancelled(listener);
}
}
public onDisable(): void {
// TODO.
}
private setupTouchBegan(listener: cc.TouchOneByOne): void {
listener.onTouchBegan = function (touch: cc.Touch, event: cc.Event.EventTouch): boolean {
const pos = touch.getLocation();
const node = this.owner;
if (node._hitTest(pos, this)) {
event.type = cc.Node.EventType.TOUCH_START;
event.touch = touch;
event.bubbles = true;
node.dispatchEvent(event);
// Continue to propagate (was disabled in _stopPropagationIfTargetIsMe).
// Don't use this: event._propagationStopped = false;
const views = getAncestors(event, node);
views.forEach(view => view.node.dispatchEvent(event));
// Reset best view.
(this as any).__bestView = undefined;
return true;
}
return false;
};
}
private setupTouchMoved(listener: cc.TouchOneByOne): void {
listener.onTouchMoved = function (touch: cc.Touch, event: cc.Event.EventTouch): void {
const node = this.owner;
event.type = cc.Node.EventType.TOUCH_MOVE;
event.touch = touch;
event.bubbles = true;
let bestView: cc.ScrollView = (this as any).__bestView; // Last calculated best view.
if (bestView === undefined) {
bestView = (this as any).__bestView = findBestScrollView(event, node);
}
bestView.node.dispatchEvent(event);
};
}
private setupTouchEnded(listener: cc.TouchOneByOne): void {
listener.onTouchEnded = function (touch: cc.Touch, event: cc.Event.EventTouch): void {
// Original lines in CCScrollView.js
const pos = touch.getLocation();
const node = this.owner;
if (node._hitTest(pos, this)) {
event.type = cc.Node.EventType.TOUCH_END;
} else {
event.type = cc.Node.EventType.TOUCH_CANCEL;
}
event.touch = touch;
event.bubbles = true;
node.dispatchEvent(event);
// Additional lines.
const views = getAncestors(event, node);
views.forEach(view => view.node.dispatchEvent(event));
};
}
private setupTouchCancelled(listener: cc.TouchOneByOne): void {
listener.onTouchCancelled = function (touch: cc.Touch, event: cc.Event.EventTouch): void {
// Original lines in CCScrollView.js
const node = this.owner;
event.type = cc.Node.EventType.TOUCH_CANCEL;
event.touch = touch;
event.bubbles = true;
node.dispatchEvent(event);
// Additional lines.
const views = getAncestors(event, node);
views.forEach(view => view.node.dispatchEvent(event));
};
}
}