UNPKG

@senspark/ee

Version:

utility library for cocos creator

136 lines (121 loc) 4.96 kB
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; }; @ccclass @menu('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)); }; } }