// z-paging // github地址:https://github.com/SmileZXLee/uni-z-paging // dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 // 反馈QQ群:790460711 //微信小程序、QQ小程序、app-vue、h5上使用wxs实现自定义下拉刷新,降低逻辑层与视图层的通信折损,提升性能 function propObserver(newValue, oldValue, ownerInstance, instance) { var state = ownerInstance.getState(); state.currentInstance = instance; var dataset = instance.getDataset(); var loading = dataset.loading == true; if (newValue.indexOf('end') != -1) { _setTransform('translateY(0px)', instance) state.moveDistance = 0; } else if (newValue.indexOf('begin') != -1) { var refresherThreshold = instance.getDataset().refresherthreshold _setTransformValue(refresherThreshold, instance, state); } } function touchstart(e, ownerInstance) { var instance = ownerInstance.getState().currentInstance; var state = instance.getState(); if (_getRefresherTouchDisabled(e, instance)) { return; } var touch = _getCommonTouch(e); state.startY = touch.touchY; state.lastRefresherTouchmove = touch; ownerInstance.callMethod('_handleRefresherTouchstart', touch); } function touchmove(e, ownerInstance) { var touch = _getCommonTouch(e); var instance = ownerInstance.getState().currentInstance; var dataset = instance.getDataset(); var refresherThreshold = dataset.refresherthreshold; var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving); var state = instance.getState(); if (_getRefresherTouchDisabled(e, instance)) { return; } if (!_getAngleIsInRange(e, touch, state, dataset)) { return; } var moveDistance = _getMoveDistance(e, instance); if (moveDistance < 0) { return; } if (e.preventDefault) { e.preventDefault(); } _setTransformValue(moveDistance, instance, state); var oldRefresherStatus = state.refresherStatus; if (moveDistance >= refresherThreshold) { state.refresherStatus = 1; } else { state.refresherStatus = 0; } if (oldRefresherStatus == undefined || oldRefresherStatus != state.refresherStatus || !isTouchmoving) { ownerInstance.callMethod('_handleRefresherTouchmove', moveDistance, touch); } return false; } function touchend(e, ownerInstance) { var touch = _getCommonTouch(e); var instance = ownerInstance.getState().currentInstance; var dataset = instance.getDataset(); var state = instance.getState(); if (_getRefresherTouchDisabled(e, instance)) { return; } state.refresherReachMaxAngle = true; var isTouchmoving = _getIsTrue(instance.getDataset().istouchmoving); if (!isTouchmoving) { return; } var oldMoveDistance = state.moveDistance; var refresherThreshold = instance.getDataset().refresherthreshold var moveDistance = _getMoveDistance(e, instance); ownerInstance.callMethod('_handleRefresherTouchend', moveDistance); if (oldMoveDistance < refresherThreshold) { return; } if (moveDistance >= refresherThreshold) { moveDistance = refresherThreshold; } _setTransformValue(moveDistance, instance, state) } function _setTransformValue(value, instance, state) { value = value || 0; state.moveDistance = value; _setTransform('translateY(' + value + 'px)', instance); } function _setTransform(transform, instance) { instance.requestAnimationFrame(function() { instance.setStyle({ transform: transform, '-webkit-transform': transform }) }) } function _getMoveDistance(e, instance) { var state = instance.getState() var refresherThreshold = instance.getDataset().refresherthreshold var touch = _getCommonTouch(e); var moveDistance = touch.touchY - state.startY; moveDistance = _getFinalRefresherMoveDistance(moveDistance, refresherThreshold); return moveDistance; } function _getCommonTouch(e) { var touch = null; if (e.touches && e.touches.length) { touch = e.touches[0]; } else if (e.changedTouches && e.changedTouches.length) { touch = e.changedTouches[0]; } else if (e.datail && e.datail !== {}) { touch = e.datail; } else { return { touchX: 0, touchY: 0 } } return { touchX: touch.clientX, touchY: touch.clientY }; } function _getFinalRefresherMoveDistance(moveDistance, refresherThreshold) { refresherThreshold = parseFloat(refresherThreshold); moveDistance = moveDistance * 0.7; if (moveDistance >= refresherThreshold) { moveDistance = refresherThreshold + (moveDistance - refresherThreshold) * 0.3; } return moveDistance; } function _getRefresherTouchDisabled(e, instance) { var dataset = instance.getDataset(); var loading = _getIsTrue(dataset.loading); var useChatRecordMode = _getIsTrue(dataset.usechatrecordmode); var refresherEnabled = _getIsTrue(dataset.refresherenabled); var useCustomRefresher = _getIsTrue(dataset.usecustomrefresher); var usePageScroll = _getIsTrue(dataset.usepagescroll); var pageScrollTop = parseFloat(dataset.pagescrolltop); var wxsIsScrollTopInTopRange = _getIsTrue(dataset.wxsisscrolltopintoprange); var scrollTop = parseFloat(dataset.scrolltop); var res = loading || useChatRecordMode || !refresherEnabled || !useCustomRefresher || ( usePageScroll && useCustomRefresher && pageScrollTop > 10) || (!( usePageScroll && useCustomRefresher) && !wxsIsScrollTopInTopRange); return res; } function _getAngleIsInRange(e, touch, state, dataset) { var refresherMaxAngle = dataset.refreshermaxangle; var refresherAecc = _getIsTrue(dataset.refresheraecc); var lastRefresherTouchmove = state.lastRefresherTouchmove; var moveDistance = state.moveDistance; var refresherReachMaxAngle = state.refresherReachMaxAngle; if (!lastRefresherTouchmove) { return true; } if (refresherMaxAngle >= 0 && refresherMaxAngle <= 90 && lastRefresherTouchmove) { if (!refresherAecc && refresherReachMaxAngle != null && !refresherReachMaxAngle) { return false; } var x = Math.abs(touch.touchX - lastRefresherTouchmove.touchX); var y = Math.abs(touch.touchY - lastRefresherTouchmove.touchY); var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); if (x && y) { var angle = Math.asin(y / z) / Math.PI * 180; if (angle < refresherMaxAngle) { state.lastRefresherTouchmove = touch; state.refresherReachMaxAngle = false; return false; } } } state.lastRefresherTouchmove = touch; return true; } function _getIsTrue(value) { value = (typeof(value) === 'string' ? JSON.parse(value) : value) || false; return value == true || value == 'true'; } module.exports = { touchstart: touchstart, touchmove: touchmove, touchend: touchend, propObserver: propObserver }