@better-scroll/wheel
Advanced tools
Comparing version 2.0.0-beta.10 to 2.0.0
import BScroll from '@better-scroll/core'; | ||
import { EaseItem } from '@better-scroll/shared-utils'; | ||
export declare type wheelOptions = Partial<WheelConfig>; | ||
export declare type WheelOptions = Partial<WheelConfig> | true; | ||
export interface WheelConfig { | ||
@@ -13,10 +13,17 @@ selectedIndex: number; | ||
declare module '@better-scroll/core' { | ||
interface Options { | ||
wheel: wheelOptions; | ||
interface CustomOptions { | ||
wheel?: WheelOptions; | ||
} | ||
interface CustomAPI { | ||
wheel: PluginAPI; | ||
} | ||
} | ||
export default class Wheel { | ||
interface PluginAPI { | ||
wheelTo(index?: number, time?: number, ease?: EaseItem): void; | ||
getSelectedIndex(): number; | ||
} | ||
export default class Wheel implements PluginAPI { | ||
scroll: BScroll; | ||
static pluginName: string; | ||
options: wheelOptions; | ||
options: WheelConfig; | ||
wheelItemsAllDisabled: boolean; | ||
@@ -29,6 +36,10 @@ items: HTMLCollection; | ||
init(): void; | ||
private tapIntoHooks; | ||
refresh(): void; | ||
private handleBScroll; | ||
private handleOptions; | ||
private handleHooks; | ||
private refreshBoundary; | ||
private handleSelectedIndex; | ||
getSelectedIndex(): number; | ||
wheelTo(index?: number, time?: number, ease?: EaseItem, isSlient?: boolean): void; | ||
wheelTo(index?: number, time?: number, ease?: EaseItem): boolean; | ||
private wheelToAfterClick; | ||
private transitionDuration; | ||
@@ -38,4 +49,4 @@ private timeFunction; | ||
private findNearestValidWheel; | ||
private normalizeOptions; | ||
private checkWheelAllDisabled; | ||
} | ||
export {}; |
@@ -9,8 +9,25 @@ /*! | ||
var ua = inBrowser && navigator.userAgent.toLowerCase(); | ||
var isWeChatDevTools = ua && /wechatdevtools/.test(ua); | ||
var isWeChatDevTools = !!(ua && /wechatdevtools/.test(ua)); | ||
var isAndroid = ua && ua.indexOf('android') > 0; | ||
var isIOSBadVersion = (function () { | ||
if (typeof ua === 'string') { | ||
var regex = /os (\d\d?_\d(_\d)?)/; | ||
var matches = regex.exec(ua); | ||
if (!matches) | ||
return false; | ||
var parts = matches[1].split('_').map(function (item) { | ||
return parseInt(item, 10); | ||
}); | ||
// ios version >= 13.4 issue 982 | ||
return !!(parts[0] >= 13 && parts[1] >= 4); | ||
} | ||
return false; | ||
})(); | ||
function isPlainObject(v) { | ||
return typeof v === 'object' && v !== null; | ||
} | ||
var extend = function (target, source) { | ||
for (var key in source) { | ||
target[key] = source[key]; | ||
} | ||
return target; | ||
}; | ||
@@ -23,12 +40,28 @@ var elementStyle = (inBrowser && | ||
} | ||
var transformNames = { | ||
webkit: 'webkitTransform', | ||
Moz: 'MozTransform', | ||
O: 'OTransform', | ||
ms: 'msTransform', | ||
standard: 'transform' | ||
}; | ||
for (var key in transformNames) { | ||
if (elementStyle[transformNames[key]] !== undefined) { | ||
return key; | ||
var transformNames = [ | ||
{ | ||
key: 'standard', | ||
value: 'transform', | ||
}, | ||
{ | ||
key: 'webkit', | ||
value: 'webkitTransform', | ||
}, | ||
{ | ||
key: 'Moz', | ||
value: 'MozTransform', | ||
}, | ||
{ | ||
key: 'O', | ||
value: 'OTransform', | ||
}, | ||
{ | ||
key: 'ms', | ||
value: 'msTransform', | ||
}, | ||
]; | ||
for (var _i = 0, transformNames_1 = transformNames; _i < transformNames_1.length; _i++) { | ||
var obj = transformNames_1[_i]; | ||
if (elementStyle[obj.value] !== undefined) { | ||
return obj.key; | ||
} | ||
@@ -61,23 +94,5 @@ } | ||
transformOrigin: prefixStyle('transformOrigin'), | ||
transitionEnd: prefixStyle('transitionEnd') | ||
transitionEnd: prefixStyle('transitionEnd'), | ||
transitionProperty: prefixStyle('transitionProperty'), | ||
}; | ||
function getRect(el) { | ||
if (el instanceof window.SVGElement) { | ||
var rect = el.getBoundingClientRect(); | ||
return { | ||
top: rect.top, | ||
left: rect.left, | ||
width: rect.width, | ||
height: rect.height | ||
}; | ||
} | ||
else { | ||
return { | ||
top: el.offsetTop, | ||
left: el.offsetLeft, | ||
width: el.offsetWidth, | ||
height: el.offsetHeight | ||
}; | ||
} | ||
} | ||
function hasClass(el, className) { | ||
@@ -112,33 +127,2 @@ var reg = new RegExp('(^|\\s)' + className + '(\\s|$)'); | ||
var DEFAULT_INTERVAL = 100 / 60; | ||
var windowCompat = inBrowser && window; | ||
function noop() { } | ||
var requestAnimationFrame = (function () { | ||
if (!inBrowser) { | ||
/* istanbul ignore if */ | ||
return noop; | ||
} | ||
return (windowCompat.requestAnimationFrame || | ||
windowCompat.webkitRequestAnimationFrame || | ||
windowCompat.mozRequestAnimationFrame || | ||
windowCompat.oRequestAnimationFrame || | ||
// if all else fails, use setTimeout | ||
function (callback) { | ||
return window.setTimeout(callback, (callback.interval || DEFAULT_INTERVAL) / 2); // make interval as precise as possible. | ||
}); | ||
})(); | ||
var cancelAnimationFrame = (function () { | ||
if (!inBrowser) { | ||
/* istanbul ignore if */ | ||
return noop; | ||
} | ||
return (windowCompat.cancelAnimationFrame || | ||
windowCompat.webkitCancelAnimationFrame || | ||
windowCompat.mozCancelAnimationFrame || | ||
windowCompat.oCancelAnimationFrame || | ||
function (id) { | ||
window.clearTimeout(id); | ||
}); | ||
})(); | ||
var sourcePrefix = 'plugins.wheel'; | ||
@@ -163,3 +147,3 @@ var propertiesMap = [ | ||
var CONSTANTS = { | ||
rate: 4 | ||
rate: 4, | ||
}; | ||
@@ -169,30 +153,46 @@ var Wheel = /** @class */ (function () { | ||
this.scroll = scroll; | ||
this.options = this.scroll.options.wheel; | ||
this.init(); | ||
} | ||
Wheel.prototype.init = function () { | ||
if (this.options) { | ||
this.normalizeOptions(); | ||
this.refresh(); | ||
this.tapIntoHooks(); | ||
this.wheelTo(this.selectedIndex); | ||
this.scroll.proxy(propertiesConfig); | ||
} | ||
this.handleBScroll(); | ||
this.handleOptions(); | ||
this.handleHooks(); | ||
// init boundary for Wheel | ||
this.refreshBoundary(); | ||
this.handleSelectedIndex(); | ||
}; | ||
Wheel.prototype.tapIntoHooks = function () { | ||
Wheel.prototype.handleBScroll = function () { | ||
this.scroll.proxy(propertiesConfig); | ||
}; | ||
Wheel.prototype.handleOptions = function () { | ||
var userOptions = (this.scroll.options.wheel === true | ||
? {} | ||
: this.scroll.options.wheel); | ||
var defaultOptions = { | ||
wheelWrapperClass: 'wheel-scroll', | ||
wheelItemClass: 'wheel-item', | ||
rotate: 25, | ||
adjustTime: 400, | ||
selectedIndex: 0, | ||
wheelDisabledItemClass: 'wheel-disabled-item', | ||
}; | ||
this.options = extend(defaultOptions, userOptions); | ||
}; | ||
Wheel.prototype.handleHooks = function () { | ||
var _this = this; | ||
var scroller = this.scroll.scroller; | ||
var actionsHandler = scroller.actionsHandler; | ||
var scrollBehaviorY = scroller.scrollBehaviorY; | ||
var animater = scroller.animater; | ||
var actionsHandler = scroller.actionsHandler, scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY, animater = scroller.animater; | ||
// BScroll | ||
this.scroll.on(this.scroll.hooks.eventTypes.refresh, function () { | ||
_this.refresh(); | ||
this.scroll.hooks.on(this.scroll.hooks.eventTypes.beforeInitialScrollTo, function (position) { | ||
position.x = 0; | ||
position.y = -(_this.selectedIndex * _this.itemHeight); | ||
}); | ||
// Scroller | ||
scroller.hooks.on(scroller.hooks.eventTypes.checkClick, function () { | ||
var index = Array.from(_this.items).indexOf(_this.target); | ||
var index = Array.prototype.slice | ||
.call(_this.items, 0) | ||
.indexOf(_this.target); | ||
if (index === -1) | ||
return true; | ||
_this.wheelTo(index, _this.options.adjustTime, ease.swipe); | ||
_this.wheelToAfterClick(index, _this.options.adjustTime, ease.swipe); | ||
return true; | ||
@@ -211,5 +211,2 @@ }); | ||
}); | ||
scroller.hooks.on(scroller.hooks.eventTypes.ignoreDisMoveForSamePos, function () { | ||
return true; | ||
}); | ||
// ActionsHandler | ||
@@ -219,6 +216,23 @@ actionsHandler.hooks.on(actionsHandler.hooks.eventTypes.beforeStart, function (e) { | ||
}); | ||
// ScrollBehaviorX | ||
// Wheel has no x direction now | ||
scrollBehaviorX.hooks.on(scrollBehaviorX.hooks.eventTypes.computeBoundary, function (boundary) { | ||
boundary.maxScrollPos = 0; | ||
boundary.minScrollPos = 0; | ||
}); | ||
// ScrollBehaviorY | ||
scrollBehaviorY.hooks.on(scrollBehaviorY.hooks.eventTypes.computeBoundary, function (boundary) { | ||
_this.items = _this.scroll.scroller.content.children; | ||
_this.checkWheelAllDisabled(); | ||
_this.itemHeight = | ||
_this.items.length > 0 | ||
? scrollBehaviorY.contentSize / _this.items.length | ||
: 0; | ||
boundary.maxScrollPos = -_this.itemHeight * (_this.items.length - 1); | ||
boundary.minScrollPos = 0; | ||
}); | ||
scrollBehaviorY.hooks.on(scrollBehaviorY.hooks.eventTypes.momentum, function (momentumInfo, distance) { | ||
momentumInfo.rate = CONSTANTS.rate; | ||
momentumInfo.destination = _this.findNearestValidWheel(momentumInfo.destination).y; | ||
// TODO algorithm optimize | ||
var maxDistance = 1000; | ||
@@ -246,5 +260,15 @@ var minDuration = 800; | ||
_this.target = _this.items[_this.findNearestValidWheel(y).index]; | ||
// don't dispatch scrollEnd when it is a click operation | ||
// don't dispatch scrollEnd when forceStop from transition or animation | ||
return true; | ||
}); | ||
// bs.stop() to make wheel stop at a correct position | ||
animater.hooks.on(animater.hooks.eventTypes.callStop, function () { | ||
var index = Array.prototype.slice | ||
.call(_this.items, 0) | ||
.indexOf(_this.target); | ||
if (index > 0) { | ||
var y = -(index * _this.itemHeight); | ||
animater.translate({ x: 0, y: y }); | ||
} | ||
}); | ||
// Translater | ||
@@ -256,32 +280,32 @@ animater.translater.hooks.on(animater.translater.hooks.eventTypes.translate, function (endPoint) { | ||
}; | ||
Wheel.prototype.refresh = function () { | ||
var scroller = this.scroll.scroller; | ||
var scrollBehaviorY = scroller.scrollBehaviorY; | ||
// adjust contentSize | ||
var contentRect = getRect(scroller.content); | ||
scrollBehaviorY.contentSize = contentRect.height; | ||
this.items = scroller.content.children; | ||
this.checkWheelAllDisabled(); | ||
this.itemHeight = this.items.length | ||
? scrollBehaviorY.contentSize / this.items.length | ||
: 0; | ||
if (this.selectedIndex === undefined) { | ||
this.selectedIndex = this.options.selectedIndex || 0; | ||
} | ||
this.scroll.maxScrollX = 0; | ||
this.scroll.maxScrollY = -this.itemHeight * (this.items.length - 1); | ||
this.scroll.minScrollX = 0; | ||
this.scroll.minScrollY = 0; | ||
scrollBehaviorY.hasScroll = | ||
scrollBehaviorY.options && this.scroll.maxScrollY < this.scroll.minScrollY; | ||
Wheel.prototype.refreshBoundary = function () { | ||
var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY; | ||
scrollBehaviorX.refresh(); | ||
scrollBehaviorY.refresh(); | ||
}; | ||
Wheel.prototype.handleSelectedIndex = function () { | ||
this.selectedIndex = this.options.selectedIndex; | ||
}; | ||
Wheel.prototype.getSelectedIndex = function () { | ||
return this.selectedIndex; | ||
}; | ||
Wheel.prototype.wheelTo = function (index, time, ease, isSlient) { | ||
Wheel.prototype.wheelTo = function (index, time, ease) { | ||
if (index === void 0) { index = 0; } | ||
if (time === void 0) { time = 0; } | ||
var y = -index * this.itemHeight; | ||
this.scroll.scrollTo(0, y, time, ease, isSlient); | ||
var currentY = Math.round(this.scroll.y); | ||
this.scroll.scrollTo(0, y, time, ease); | ||
return y === currentY; | ||
}; | ||
Wheel.prototype.wheelToAfterClick = function (index, time, ease) { | ||
if (index === void 0) { index = 0; } | ||
if (time === void 0) { time = 0; } | ||
var needDispatchScrollEnd = this.wheelTo(index, time, ease); | ||
// startpoint === endpoint | ||
// manually trigger scrollEnd | ||
if (needDispatchScrollEnd) { | ||
var hooks = this.scroll.scroller.hooks; | ||
hooks.trigger(hooks.eventTypes.scrollEnd); | ||
} | ||
}; | ||
Wheel.prototype.transitionDuration = function (time) { | ||
@@ -302,3 +326,5 @@ for (var i = 0; i < this.items.length; i++) { | ||
var deg = rotate * (y / this.itemHeight + i); | ||
this.items[i].style[style.transform] = "rotateX(" + deg + "deg)"; | ||
// Too small value is invalid in some phones, issue 1026 | ||
var SafeDeg = deg.toFixed(3); | ||
this.items[i].style[style.transform] = "rotateX(" + SafeDeg + "deg)"; | ||
} | ||
@@ -339,28 +365,7 @@ }; | ||
index: this.wheelItemsAllDisabled ? -1 : currentIndex, | ||
y: -currentIndex * this.itemHeight | ||
y: -currentIndex * this.itemHeight, | ||
}; | ||
}; | ||
Wheel.prototype.normalizeOptions = function () { | ||
var options = (this.options = isPlainObject(this.options) | ||
? this.options | ||
: {}); | ||
if (!options.wheelWrapperClass) { | ||
options.wheelWrapperClass = 'wheel-scroll'; | ||
} | ||
if (!options.wheelItemClass) { | ||
options.wheelItemClass = 'wheel-item'; | ||
} | ||
if (!options.rotate) { | ||
options.rotate = 25; | ||
} | ||
if (!options.adjustTime) { | ||
options.adjustTime = 400; | ||
} | ||
if (!options.wheelDisabledItemClass) { | ||
options.wheelDisabledItemClass = 'wheel-disabled-item'; | ||
} | ||
}; | ||
Wheel.prototype.checkWheelAllDisabled = function () { | ||
var wheelDisabledItemClassName = this.options | ||
.wheelDisabledItemClass; | ||
var wheelDisabledItemClassName = this.options.wheelDisabledItemClass; | ||
var items = this.items; | ||
@@ -367,0 +372,0 @@ this.wheelItemsAllDisabled = true; |
@@ -9,4 +9,4 @@ /*! | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global = global || self, global.Wheel = factory()); | ||
}(this, function () { 'use strict'; | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Wheel = factory()); | ||
}(this, (function () { 'use strict'; | ||
@@ -16,8 +16,25 @@ // ssr support | ||
var ua = inBrowser && navigator.userAgent.toLowerCase(); | ||
var isWeChatDevTools = ua && /wechatdevtools/.test(ua); | ||
var isWeChatDevTools = !!(ua && /wechatdevtools/.test(ua)); | ||
var isAndroid = ua && ua.indexOf('android') > 0; | ||
var isIOSBadVersion = (function () { | ||
if (typeof ua === 'string') { | ||
var regex = /os (\d\d?_\d(_\d)?)/; | ||
var matches = regex.exec(ua); | ||
if (!matches) | ||
return false; | ||
var parts = matches[1].split('_').map(function (item) { | ||
return parseInt(item, 10); | ||
}); | ||
// ios version >= 13.4 issue 982 | ||
return !!(parts[0] >= 13 && parts[1] >= 4); | ||
} | ||
return false; | ||
})(); | ||
function isPlainObject(v) { | ||
return typeof v === 'object' && v !== null; | ||
} | ||
var extend = function (target, source) { | ||
for (var key in source) { | ||
target[key] = source[key]; | ||
} | ||
return target; | ||
}; | ||
@@ -30,12 +47,28 @@ var elementStyle = (inBrowser && | ||
} | ||
var transformNames = { | ||
webkit: 'webkitTransform', | ||
Moz: 'MozTransform', | ||
O: 'OTransform', | ||
ms: 'msTransform', | ||
standard: 'transform' | ||
}; | ||
for (var key in transformNames) { | ||
if (elementStyle[transformNames[key]] !== undefined) { | ||
return key; | ||
var transformNames = [ | ||
{ | ||
key: 'standard', | ||
value: 'transform', | ||
}, | ||
{ | ||
key: 'webkit', | ||
value: 'webkitTransform', | ||
}, | ||
{ | ||
key: 'Moz', | ||
value: 'MozTransform', | ||
}, | ||
{ | ||
key: 'O', | ||
value: 'OTransform', | ||
}, | ||
{ | ||
key: 'ms', | ||
value: 'msTransform', | ||
}, | ||
]; | ||
for (var _i = 0, transformNames_1 = transformNames; _i < transformNames_1.length; _i++) { | ||
var obj = transformNames_1[_i]; | ||
if (elementStyle[obj.value] !== undefined) { | ||
return obj.key; | ||
} | ||
@@ -68,23 +101,5 @@ } | ||
transformOrigin: prefixStyle('transformOrigin'), | ||
transitionEnd: prefixStyle('transitionEnd') | ||
transitionEnd: prefixStyle('transitionEnd'), | ||
transitionProperty: prefixStyle('transitionProperty'), | ||
}; | ||
function getRect(el) { | ||
if (el instanceof window.SVGElement) { | ||
var rect = el.getBoundingClientRect(); | ||
return { | ||
top: rect.top, | ||
left: rect.left, | ||
width: rect.width, | ||
height: rect.height | ||
}; | ||
} | ||
else { | ||
return { | ||
top: el.offsetTop, | ||
left: el.offsetLeft, | ||
width: el.offsetWidth, | ||
height: el.offsetHeight | ||
}; | ||
} | ||
} | ||
function hasClass(el, className) { | ||
@@ -119,33 +134,2 @@ var reg = new RegExp('(^|\\s)' + className + '(\\s|$)'); | ||
var DEFAULT_INTERVAL = 100 / 60; | ||
var windowCompat = inBrowser && window; | ||
function noop() { } | ||
var requestAnimationFrame = (function () { | ||
if (!inBrowser) { | ||
/* istanbul ignore if */ | ||
return noop; | ||
} | ||
return (windowCompat.requestAnimationFrame || | ||
windowCompat.webkitRequestAnimationFrame || | ||
windowCompat.mozRequestAnimationFrame || | ||
windowCompat.oRequestAnimationFrame || | ||
// if all else fails, use setTimeout | ||
function (callback) { | ||
return window.setTimeout(callback, (callback.interval || DEFAULT_INTERVAL) / 2); // make interval as precise as possible. | ||
}); | ||
})(); | ||
var cancelAnimationFrame = (function () { | ||
if (!inBrowser) { | ||
/* istanbul ignore if */ | ||
return noop; | ||
} | ||
return (windowCompat.cancelAnimationFrame || | ||
windowCompat.webkitCancelAnimationFrame || | ||
windowCompat.mozCancelAnimationFrame || | ||
windowCompat.oCancelAnimationFrame || | ||
function (id) { | ||
window.clearTimeout(id); | ||
}); | ||
})(); | ||
var sourcePrefix = 'plugins.wheel'; | ||
@@ -170,3 +154,3 @@ var propertiesMap = [ | ||
var CONSTANTS = { | ||
rate: 4 | ||
rate: 4, | ||
}; | ||
@@ -176,30 +160,46 @@ var Wheel = /** @class */ (function () { | ||
this.scroll = scroll; | ||
this.options = this.scroll.options.wheel; | ||
this.init(); | ||
} | ||
Wheel.prototype.init = function () { | ||
if (this.options) { | ||
this.normalizeOptions(); | ||
this.refresh(); | ||
this.tapIntoHooks(); | ||
this.wheelTo(this.selectedIndex); | ||
this.scroll.proxy(propertiesConfig); | ||
} | ||
this.handleBScroll(); | ||
this.handleOptions(); | ||
this.handleHooks(); | ||
// init boundary for Wheel | ||
this.refreshBoundary(); | ||
this.handleSelectedIndex(); | ||
}; | ||
Wheel.prototype.tapIntoHooks = function () { | ||
Wheel.prototype.handleBScroll = function () { | ||
this.scroll.proxy(propertiesConfig); | ||
}; | ||
Wheel.prototype.handleOptions = function () { | ||
var userOptions = (this.scroll.options.wheel === true | ||
? {} | ||
: this.scroll.options.wheel); | ||
var defaultOptions = { | ||
wheelWrapperClass: 'wheel-scroll', | ||
wheelItemClass: 'wheel-item', | ||
rotate: 25, | ||
adjustTime: 400, | ||
selectedIndex: 0, | ||
wheelDisabledItemClass: 'wheel-disabled-item', | ||
}; | ||
this.options = extend(defaultOptions, userOptions); | ||
}; | ||
Wheel.prototype.handleHooks = function () { | ||
var _this = this; | ||
var scroller = this.scroll.scroller; | ||
var actionsHandler = scroller.actionsHandler; | ||
var scrollBehaviorY = scroller.scrollBehaviorY; | ||
var animater = scroller.animater; | ||
var actionsHandler = scroller.actionsHandler, scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY, animater = scroller.animater; | ||
// BScroll | ||
this.scroll.on(this.scroll.hooks.eventTypes.refresh, function () { | ||
_this.refresh(); | ||
this.scroll.hooks.on(this.scroll.hooks.eventTypes.beforeInitialScrollTo, function (position) { | ||
position.x = 0; | ||
position.y = -(_this.selectedIndex * _this.itemHeight); | ||
}); | ||
// Scroller | ||
scroller.hooks.on(scroller.hooks.eventTypes.checkClick, function () { | ||
var index = Array.from(_this.items).indexOf(_this.target); | ||
var index = Array.prototype.slice | ||
.call(_this.items, 0) | ||
.indexOf(_this.target); | ||
if (index === -1) | ||
return true; | ||
_this.wheelTo(index, _this.options.adjustTime, ease.swipe); | ||
_this.wheelToAfterClick(index, _this.options.adjustTime, ease.swipe); | ||
return true; | ||
@@ -218,5 +218,2 @@ }); | ||
}); | ||
scroller.hooks.on(scroller.hooks.eventTypes.ignoreDisMoveForSamePos, function () { | ||
return true; | ||
}); | ||
// ActionsHandler | ||
@@ -226,6 +223,23 @@ actionsHandler.hooks.on(actionsHandler.hooks.eventTypes.beforeStart, function (e) { | ||
}); | ||
// ScrollBehaviorX | ||
// Wheel has no x direction now | ||
scrollBehaviorX.hooks.on(scrollBehaviorX.hooks.eventTypes.computeBoundary, function (boundary) { | ||
boundary.maxScrollPos = 0; | ||
boundary.minScrollPos = 0; | ||
}); | ||
// ScrollBehaviorY | ||
scrollBehaviorY.hooks.on(scrollBehaviorY.hooks.eventTypes.computeBoundary, function (boundary) { | ||
_this.items = _this.scroll.scroller.content.children; | ||
_this.checkWheelAllDisabled(); | ||
_this.itemHeight = | ||
_this.items.length > 0 | ||
? scrollBehaviorY.contentSize / _this.items.length | ||
: 0; | ||
boundary.maxScrollPos = -_this.itemHeight * (_this.items.length - 1); | ||
boundary.minScrollPos = 0; | ||
}); | ||
scrollBehaviorY.hooks.on(scrollBehaviorY.hooks.eventTypes.momentum, function (momentumInfo, distance) { | ||
momentumInfo.rate = CONSTANTS.rate; | ||
momentumInfo.destination = _this.findNearestValidWheel(momentumInfo.destination).y; | ||
// TODO algorithm optimize | ||
var maxDistance = 1000; | ||
@@ -253,5 +267,15 @@ var minDuration = 800; | ||
_this.target = _this.items[_this.findNearestValidWheel(y).index]; | ||
// don't dispatch scrollEnd when it is a click operation | ||
// don't dispatch scrollEnd when forceStop from transition or animation | ||
return true; | ||
}); | ||
// bs.stop() to make wheel stop at a correct position | ||
animater.hooks.on(animater.hooks.eventTypes.callStop, function () { | ||
var index = Array.prototype.slice | ||
.call(_this.items, 0) | ||
.indexOf(_this.target); | ||
if (index > 0) { | ||
var y = -(index * _this.itemHeight); | ||
animater.translate({ x: 0, y: y }); | ||
} | ||
}); | ||
// Translater | ||
@@ -263,32 +287,32 @@ animater.translater.hooks.on(animater.translater.hooks.eventTypes.translate, function (endPoint) { | ||
}; | ||
Wheel.prototype.refresh = function () { | ||
var scroller = this.scroll.scroller; | ||
var scrollBehaviorY = scroller.scrollBehaviorY; | ||
// adjust contentSize | ||
var contentRect = getRect(scroller.content); | ||
scrollBehaviorY.contentSize = contentRect.height; | ||
this.items = scroller.content.children; | ||
this.checkWheelAllDisabled(); | ||
this.itemHeight = this.items.length | ||
? scrollBehaviorY.contentSize / this.items.length | ||
: 0; | ||
if (this.selectedIndex === undefined) { | ||
this.selectedIndex = this.options.selectedIndex || 0; | ||
} | ||
this.scroll.maxScrollX = 0; | ||
this.scroll.maxScrollY = -this.itemHeight * (this.items.length - 1); | ||
this.scroll.minScrollX = 0; | ||
this.scroll.minScrollY = 0; | ||
scrollBehaviorY.hasScroll = | ||
scrollBehaviorY.options && this.scroll.maxScrollY < this.scroll.minScrollY; | ||
Wheel.prototype.refreshBoundary = function () { | ||
var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY; | ||
scrollBehaviorX.refresh(); | ||
scrollBehaviorY.refresh(); | ||
}; | ||
Wheel.prototype.handleSelectedIndex = function () { | ||
this.selectedIndex = this.options.selectedIndex; | ||
}; | ||
Wheel.prototype.getSelectedIndex = function () { | ||
return this.selectedIndex; | ||
}; | ||
Wheel.prototype.wheelTo = function (index, time, ease, isSlient) { | ||
Wheel.prototype.wheelTo = function (index, time, ease) { | ||
if (index === void 0) { index = 0; } | ||
if (time === void 0) { time = 0; } | ||
var y = -index * this.itemHeight; | ||
this.scroll.scrollTo(0, y, time, ease, isSlient); | ||
var currentY = Math.round(this.scroll.y); | ||
this.scroll.scrollTo(0, y, time, ease); | ||
return y === currentY; | ||
}; | ||
Wheel.prototype.wheelToAfterClick = function (index, time, ease) { | ||
if (index === void 0) { index = 0; } | ||
if (time === void 0) { time = 0; } | ||
var needDispatchScrollEnd = this.wheelTo(index, time, ease); | ||
// startpoint === endpoint | ||
// manually trigger scrollEnd | ||
if (needDispatchScrollEnd) { | ||
var hooks = this.scroll.scroller.hooks; | ||
hooks.trigger(hooks.eventTypes.scrollEnd); | ||
} | ||
}; | ||
Wheel.prototype.transitionDuration = function (time) { | ||
@@ -309,3 +333,5 @@ for (var i = 0; i < this.items.length; i++) { | ||
var deg = rotate * (y / this.itemHeight + i); | ||
this.items[i].style[style.transform] = "rotateX(" + deg + "deg)"; | ||
// Too small value is invalid in some phones, issue 1026 | ||
var SafeDeg = deg.toFixed(3); | ||
this.items[i].style[style.transform] = "rotateX(" + SafeDeg + "deg)"; | ||
} | ||
@@ -346,28 +372,7 @@ }; | ||
index: this.wheelItemsAllDisabled ? -1 : currentIndex, | ||
y: -currentIndex * this.itemHeight | ||
y: -currentIndex * this.itemHeight, | ||
}; | ||
}; | ||
Wheel.prototype.normalizeOptions = function () { | ||
var options = (this.options = isPlainObject(this.options) | ||
? this.options | ||
: {}); | ||
if (!options.wheelWrapperClass) { | ||
options.wheelWrapperClass = 'wheel-scroll'; | ||
} | ||
if (!options.wheelItemClass) { | ||
options.wheelItemClass = 'wheel-item'; | ||
} | ||
if (!options.rotate) { | ||
options.rotate = 25; | ||
} | ||
if (!options.adjustTime) { | ||
options.adjustTime = 400; | ||
} | ||
if (!options.wheelDisabledItemClass) { | ||
options.wheelDisabledItemClass = 'wheel-disabled-item'; | ||
} | ||
}; | ||
Wheel.prototype.checkWheelAllDisabled = function () { | ||
var wheelDisabledItemClassName = this.options | ||
.wheelDisabledItemClass; | ||
var wheelDisabledItemClassName = this.options.wheelDisabledItemClass; | ||
var items = this.items; | ||
@@ -388,2 +393,2 @@ this.wheelItemsAllDisabled = true; | ||
})); | ||
}))); |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Wheel=t()}(this,function(){"use strict";var o="undefined"!=typeof window,e=o&&navigator.userAgent.toLowerCase();e&&/wechatdevtools/.test(e),e&&e.indexOf("android");var i=o&&document.createElement("div").style,t=function(){if(!o)return!1;var e={webkit:"webkitTransform",Moz:"MozTransform",O:"OTransform",ms:"msTransform",standard:"transform"};for(var t in e)if(void 0!==i[e[t]])return t;return!1}();function n(e){return!1===t?e:"standard"===t?"transitionEnd"===e?"transitionend":e:t+e.charAt(0).toUpperCase()+e.substr(1)}t&&"standard"!==t&&t.toLowerCase();var s=n("transform"),r=(n("transition"),o&&n("perspective"),s),l=n("transitionTimingFunction"),a=n("transitionDuration");n("transitionDelay"),n("transformOrigin"),n("transitionEnd");function h(e,t){return new RegExp("(^|\\s)"+t+"(\\s|$)").test(e.className)}var c={style:"cubic-bezier(0.23, 1, 0.32, 1)",fn:function(e){return 1+--e*e*e*e*e}},d=o&&window;function m(){}o&&(d.requestAnimationFrame||d.webkitRequestAnimationFrame||d.mozRequestAnimationFrame||d.oRequestAnimationFrame),o&&(d.cancelAnimationFrame||d.webkitCancelAnimationFrame||d.mozCancelAnimationFrame||d.oCancelAnimationFrame);var f=[{key:"wheelTo",name:"wheelTo"},{key:"getSelectedIndex",name:"getSelectedIndex"}].map(function(e){return{key:e.key,sourceKey:"plugins.wheel."+e.name}}),u=4;function p(e){this.scroll=e,this.options=this.scroll.options.wheel,this.init()}return p.prototype.init=function(){this.options&&(this.normalizeOptions(),this.refresh(),this.tapIntoHooks(),this.wheelTo(this.selectedIndex),this.scroll.proxy(f))},p.prototype.tapIntoHooks=function(){var o=this,e=this.scroll.scroller,t=e.actionsHandler,i=e.scrollBehaviorY,n=e.animater;this.scroll.on(this.scroll.hooks.eventTypes.refresh,function(){o.refresh()}),e.hooks.on(e.hooks.eventTypes.checkClick,function(){var e=Array.from(o.items).indexOf(o.target);return-1===e||o.wheelTo(e,o.options.adjustTime,c),!0}),e.hooks.on(e.hooks.eventTypes.scrollTo,function(e){e.y=o.findNearestValidWheel(e.y).y}),e.hooks.on(e.hooks.eventTypes.scrollToElement,function(e,t){if(!h(e,o.options.wheelItemClass))return!0;t.top=o.findNearestValidWheel(t.top).y}),e.hooks.on(e.hooks.eventTypes.ignoreDisMoveForSamePos,function(){return!0}),t.hooks.on(t.hooks.eventTypes.beforeStart,function(e){o.target=e.target}),i.hooks.on(i.hooks.eventTypes.momentum,function(e,t){e.rate=u,e.destination=o.findNearestValidWheel(e.destination).y,t<1e3&&(e.duration=Math.max(800,t/1e3*o.scroll.options.swipeTime))}),i.hooks.on(i.hooks.eventTypes.end,function(e){var t=o.findNearestValidWheel(i.currentPos);e.destination=t.y,e.duration=o.options.adjustTime,o.selectedIndex=t.index}),n.hooks.on(n.hooks.eventTypes.time,function(e){o.transitionDuration(e)}),n.hooks.on(n.hooks.eventTypes.timeFunction,function(e){o.timeFunction(e)}),n.hooks.on(n.hooks.eventTypes.beforeForceStop,function(e){var t=e.y;return o.target=o.items[o.findNearestValidWheel(t).index],!0}),n.translater.hooks.on(n.translater.hooks.eventTypes.translate,function(e){o.rotateX(e.y),o.selectedIndex=o.findNearestValidWheel(e.y).index})},p.prototype.refresh=function(){var e=this.scroll.scroller,t=e.scrollBehaviorY,o=function(e){if(e instanceof window.SVGElement){var t=e.getBoundingClientRect();return{top:t.top,left:t.left,width:t.width,height:t.height}}return{top:e.offsetTop,left:e.offsetLeft,width:e.offsetWidth,height:e.offsetHeight}}(e.content);t.contentSize=o.height,this.items=e.content.children,this.checkWheelAllDisabled(),this.itemHeight=this.items.length?t.contentSize/this.items.length:0,void 0===this.selectedIndex&&(this.selectedIndex=this.options.selectedIndex||0),this.scroll.maxScrollX=0,this.scroll.maxScrollY=-this.itemHeight*(this.items.length-1),this.scroll.minScrollX=0,this.scroll.minScrollY=0,t.hasScroll=t.options&&this.scroll.maxScrollY<this.scroll.minScrollY},p.prototype.getSelectedIndex=function(){return this.selectedIndex},p.prototype.wheelTo=function(e,t,o,i){void 0===e&&(e=0),void 0===t&&(t=0);var n=-e*this.itemHeight;this.scroll.scrollTo(0,n,t,o,i)},p.prototype.transitionDuration=function(e){for(var t=0;t<this.items.length;t++)this.items[t].style[a]=e+"ms"},p.prototype.timeFunction=function(e){for(var t=0;t<this.items.length;t++)this.items[t].style[l]=e},p.prototype.rotateX=function(e){for(var t=this.options.rotate,o=void 0===t?25:t,i=0;i<this.items.length;i++){var n=o*(e/this.itemHeight+i);this.items[i].style[r]="rotateX("+n+"deg)"}},p.prototype.findNearestValidWheel=function(e){e=0<e?0:e<this.scroll.maxScrollY?this.scroll.maxScrollY:e;for(var t=Math.abs(Math.round(-e/this.itemHeight)),o=t,i=this.items,n=this.options.wheelDisabledItemClass;0<=t&&h(i[t],n);)t--;if(t<0)for(t=o;t<=i.length-1&&h(i[t],n);)t++;return t===i.length&&(t=o),{index:this.wheelItemsAllDisabled?-1:t,y:-t*this.itemHeight}},p.prototype.normalizeOptions=function(){var e=this.options=function(e){return"object"==typeof e&&null!==e}(this.options)?this.options:{};e.wheelWrapperClass||(e.wheelWrapperClass="wheel-scroll"),e.wheelItemClass||(e.wheelItemClass="wheel-item"),e.rotate||(e.rotate=25),e.adjustTime||(e.adjustTime=400),e.wheelDisabledItemClass||(e.wheelDisabledItemClass="wheel-disabled-item")},p.prototype.checkWheelAllDisabled=function(){var e=this.options.wheelDisabledItemClass,t=this.items;this.wheelItemsAllDisabled=!0;for(var o=0;o<t.length;o++)if(!h(t[o],e)){this.wheelItemsAllDisabled=!1;break}},p.pluginName="wheel",p}); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Wheel=t()}(this,function(){"use strict";var n="undefined"!=typeof window,o=n&&navigator.userAgent.toLowerCase(),i=(o&&/wechatdevtools/.test(o),o&&o.indexOf("android"),function(){if("string"!=typeof o)return;var e=/os (\d\d?_\d(_\d)?)/.exec(o);if(!e)return;var t=e[1].split("_").map(function(e){return parseInt(e,10)});13<=t[0]&&t[1]}(),n&&document.createElement("div").style),t=function(){if(!n)return!1;for(var e=0,t=[{key:"standard",value:"transform"},{key:"webkit",value:"webkitTransform"},{key:"Moz",value:"MozTransform"},{key:"O",value:"OTransform"},{key:"ms",value:"msTransform"}];e<t.length;e++){var o=t[e];if(void 0!==i[o.value])return o.key}return!1}();function e(e){return!1===t?e:"standard"===t?"transitionEnd"===e?"transitionend":e:t+e.charAt(0).toUpperCase()+e.substr(1)}t&&"standard"!==t&&t.toLowerCase();var s=e("transform"),r=(e("transition"),n&&e("perspective")in i,s),l=e("transitionTimingFunction"),a=e("transitionDuration");e("transitionDelay"),e("transformOrigin"),e("transitionEnd"),e("transitionProperty");function h(e,t){return new RegExp("(^|\\s)"+t+"(\\s|$)").test(e.className)}var c={style:"cubic-bezier(0.23, 1, 0.32, 1)",fn:function(e){return 1+--e*e*e*e*e}},d=[{key:"wheelTo",name:"wheelTo"},{key:"getSelectedIndex",name:"getSelectedIndex"}].map(function(e){return{key:e.key,sourceKey:"plugins.wheel."+e.name}}),u=4;function f(e){this.scroll=e,this.init()}return f.prototype.init=function(){this.handleBScroll(),this.handleOptions(),this.handleHooks(),this.refreshBoundary(),this.handleSelectedIndex()},f.prototype.handleBScroll=function(){this.scroll.proxy(d)},f.prototype.handleOptions=function(){var e=!0===this.scroll.options.wheel?{}:this.scroll.options.wheel;this.options=function(e,t){for(var o in t)e[o]=t[o];return e}({wheelWrapperClass:"wheel-scroll",wheelItemClass:"wheel-item",rotate:25,adjustTime:400,selectedIndex:0,wheelDisabledItemClass:"wheel-disabled-item"},e)},f.prototype.handleHooks=function(){var o=this,e=this.scroll.scroller,t=e.actionsHandler,n=e.scrollBehaviorX,i=e.scrollBehaviorY,s=e.animater;this.scroll.hooks.on(this.scroll.hooks.eventTypes.beforeInitialScrollTo,function(e){e.x=0,e.y=-(o.selectedIndex*o.itemHeight)}),e.hooks.on(e.hooks.eventTypes.checkClick,function(){var e=Array.prototype.slice.call(o.items,0).indexOf(o.target);return-1===e||o.wheelToAfterClick(e,o.options.adjustTime,c),!0}),e.hooks.on(e.hooks.eventTypes.scrollTo,function(e){e.y=o.findNearestValidWheel(e.y).y}),e.hooks.on(e.hooks.eventTypes.scrollToElement,function(e,t){return!h(e,o.options.wheelItemClass)||void(t.top=o.findNearestValidWheel(t.top).y)}),t.hooks.on(t.hooks.eventTypes.beforeStart,function(e){o.target=e.target}),n.hooks.on(n.hooks.eventTypes.computeBoundary,function(e){e.maxScrollPos=0,e.minScrollPos=0}),i.hooks.on(i.hooks.eventTypes.computeBoundary,function(e){o.items=o.scroll.scroller.content.children,o.checkWheelAllDisabled(),o.itemHeight=0<o.items.length?i.contentSize/o.items.length:0,e.maxScrollPos=-o.itemHeight*(o.items.length-1),e.minScrollPos=0}),i.hooks.on(i.hooks.eventTypes.momentum,function(e,t){e.rate=u,e.destination=o.findNearestValidWheel(e.destination).y;t<1e3&&(e.duration=Math.max(800,t/1e3*o.scroll.options.swipeTime))}),i.hooks.on(i.hooks.eventTypes.end,function(e){var t=o.findNearestValidWheel(i.currentPos);e.destination=t.y,e.duration=o.options.adjustTime,o.selectedIndex=t.index}),s.hooks.on(s.hooks.eventTypes.time,function(e){o.transitionDuration(e)}),s.hooks.on(s.hooks.eventTypes.timeFunction,function(e){o.timeFunction(e)}),s.hooks.on(s.hooks.eventTypes.beforeForceStop,function(e){var t=e.y;return o.target=o.items[o.findNearestValidWheel(t).index],!0}),s.hooks.on(s.hooks.eventTypes.callStop,function(){var e,t=Array.prototype.slice.call(o.items,0).indexOf(o.target);0<t&&(e=-(t*o.itemHeight),s.translate({x:0,y:e}))}),s.translater.hooks.on(s.translater.hooks.eventTypes.translate,function(e){o.rotateX(e.y),o.selectedIndex=o.findNearestValidWheel(e.y).index})},f.prototype.refreshBoundary=function(){var e=this.scroll.scroller,t=e.scrollBehaviorX,o=e.scrollBehaviorY;t.refresh(),o.refresh()},f.prototype.handleSelectedIndex=function(){this.selectedIndex=this.options.selectedIndex},f.prototype.getSelectedIndex=function(){return this.selectedIndex},f.prototype.wheelTo=function(e,t,o){void 0===e&&(e=0),void 0===t&&(t=0);var n=-e*this.itemHeight,i=Math.round(this.scroll.y);return this.scroll.scrollTo(0,n,t,o),n===i},f.prototype.wheelToAfterClick=function(e,t,o){var n;void 0===e&&(e=0),void 0===t&&(t=0),this.wheelTo(e,t,o)&&(n=this.scroll.scroller.hooks).trigger(n.eventTypes.scrollEnd)},f.prototype.transitionDuration=function(e){for(var t=0;t<this.items.length;t++)this.items[t].style[a]=e+"ms"},f.prototype.timeFunction=function(e){for(var t=0;t<this.items.length;t++)this.items[t].style[l]=e},f.prototype.rotateX=function(e){for(var t=this.options.rotate,o=void 0===t?25:t,n=0;n<this.items.length;n++){var i=(o*(e/this.itemHeight+n)).toFixed(3);this.items[n].style[r]="rotateX("+i+"deg)"}},f.prototype.findNearestValidWheel=function(e){e=0<e?0:e<this.scroll.maxScrollY?this.scroll.maxScrollY:e;for(var t=Math.abs(Math.round(-e/this.itemHeight)),o=t,n=this.items,i=this.options.wheelDisabledItemClass;0<=t&&h(n[t],i);)t--;if(t<0)for(t=o;t<=n.length-1&&h(n[t],i);)t++;return t===n.length&&(t=o),{index:this.wheelItemsAllDisabled?-1:t,y:-t*this.itemHeight}},f.prototype.checkWheelAllDisabled=function(){var e=this.options.wheelDisabledItemClass,t=this.items;this.wheelItemsAllDisabled=!0;for(var o=0;o<t.length;o++)if(!h(t[o],e)){this.wheelItemsAllDisabled=!1;break}},f.pluginName="wheel",f}); |
{ | ||
"name": "@better-scroll/wheel", | ||
"version": "2.0.0-beta.10", | ||
"version": "2.0.0", | ||
"description": "a BetterScroll plugin to imitate IOS Picker", | ||
@@ -32,5 +32,5 @@ "author": { | ||
"dependencies": { | ||
"@better-scroll/core": "^2.0.0-beta.10" | ||
"@better-scroll/core": "^2.0.0" | ||
}, | ||
"gitHead": "9449aa2e39ec4e979aec3f3d8df82491f8948164" | ||
"gitHead": "f4b08b7bb14781c0e1c05b90b66c3499b07758e6" | ||
} |
214
src/index.ts
@@ -1,13 +0,13 @@ | ||
import BScroll from '@better-scroll/core' | ||
import BScroll, { Boundary } from '@better-scroll/core' | ||
import { | ||
style, | ||
hasClass, | ||
getRect, | ||
ease, | ||
EaseItem, | ||
isPlainObject | ||
extend, | ||
} from '@better-scroll/shared-utils' | ||
import propertiesConfig from './propertiesConfig' | ||
export type wheelOptions = Partial<WheelConfig> | ||
export type WheelOptions = Partial<WheelConfig> | true | ||
export interface WheelConfig { | ||
@@ -23,13 +23,21 @@ selectedIndex: number | ||
declare module '@better-scroll/core' { | ||
interface Options { | ||
wheel: wheelOptions | ||
interface CustomOptions { | ||
wheel?: WheelOptions | ||
} | ||
interface CustomAPI { | ||
wheel: PluginAPI | ||
} | ||
} | ||
interface PluginAPI { | ||
wheelTo(index?: number, time?: number, ease?: EaseItem): void | ||
getSelectedIndex(): number | ||
} | ||
const CONSTANTS = { | ||
rate: 4 | ||
rate: 4, | ||
} | ||
export default class Wheel { | ||
export default class Wheel implements PluginAPI { | ||
static pluginName = 'wheel' | ||
options: wheelOptions | ||
options: WheelConfig | ||
wheelItemsAllDisabled: boolean | ||
@@ -41,3 +49,2 @@ items: HTMLCollection | ||
constructor(public scroll: BScroll) { | ||
this.options = this.scroll.options.wheel | ||
this.init() | ||
@@ -47,27 +54,54 @@ } | ||
init() { | ||
if (this.options) { | ||
this.normalizeOptions() | ||
this.refresh() | ||
this.tapIntoHooks() | ||
this.wheelTo(this.selectedIndex) | ||
this.scroll.proxy(propertiesConfig) | ||
this.handleBScroll() | ||
this.handleOptions() | ||
this.handleHooks() | ||
// init boundary for Wheel | ||
this.refreshBoundary() | ||
this.handleSelectedIndex() | ||
} | ||
private handleBScroll() { | ||
this.scroll.proxy(propertiesConfig) | ||
} | ||
private handleOptions() { | ||
const userOptions = (this.scroll.options.wheel === true | ||
? {} | ||
: this.scroll.options.wheel) as Partial<WheelConfig> | ||
const defaultOptions: WheelConfig = { | ||
wheelWrapperClass: 'wheel-scroll', | ||
wheelItemClass: 'wheel-item', | ||
rotate: 25, | ||
adjustTime: 400, | ||
selectedIndex: 0, | ||
wheelDisabledItemClass: 'wheel-disabled-item', | ||
} | ||
this.options = extend(defaultOptions, userOptions) | ||
} | ||
private tapIntoHooks() { | ||
private handleHooks() { | ||
const scroller = this.scroll.scroller | ||
const actionsHandler = scroller.actionsHandler | ||
const scrollBehaviorY = scroller.scrollBehaviorY | ||
const animater = scroller.animater | ||
const { | ||
actionsHandler, | ||
scrollBehaviorX, | ||
scrollBehaviorY, | ||
animater, | ||
} = scroller | ||
// BScroll | ||
this.scroll.on(this.scroll.hooks.eventTypes.refresh, () => { | ||
this.refresh() | ||
}) | ||
this.scroll.hooks.on( | ||
this.scroll.hooks.eventTypes.beforeInitialScrollTo, | ||
(position: { x: number; y: number }) => { | ||
position.x = 0 | ||
position.y = -(this.selectedIndex * this.itemHeight) | ||
} | ||
) | ||
// Scroller | ||
scroller.hooks.on(scroller.hooks.eventTypes.checkClick, () => { | ||
const index = Array.from(this.items).indexOf(this.target as Element) | ||
const index = Array.prototype.slice | ||
.call(this.items, 0) | ||
.indexOf(this.target as Element) | ||
if (index === -1) return true | ||
this.wheelTo(index, this.options.adjustTime, ease.swipe) | ||
this.wheelToAfterClick(index, this.options.adjustTime, ease.swipe) | ||
return true | ||
@@ -84,3 +118,3 @@ }) | ||
(el: HTMLElement, pos: { top: number; left: number }) => { | ||
if (!hasClass(el, this.options.wheelItemClass!)) { | ||
if (!hasClass(el, this.options.wheelItemClass)) { | ||
return true | ||
@@ -92,5 +126,2 @@ } else { | ||
) | ||
scroller.hooks.on(scroller.hooks.eventTypes.ignoreDisMoveForSamePos, () => { | ||
return true | ||
}) | ||
@@ -105,4 +136,29 @@ // ActionsHandler | ||
// ScrollBehaviorX | ||
// Wheel has no x direction now | ||
scrollBehaviorX.hooks.on( | ||
scrollBehaviorX.hooks.eventTypes.computeBoundary, | ||
(boundary: Boundary) => { | ||
boundary.maxScrollPos = 0 | ||
boundary.minScrollPos = 0 | ||
} | ||
) | ||
// ScrollBehaviorY | ||
scrollBehaviorY.hooks.on( | ||
scrollBehaviorY.hooks.eventTypes.computeBoundary, | ||
(boundary: Boundary) => { | ||
this.items = this.scroll.scroller.content.children | ||
this.checkWheelAllDisabled() | ||
this.itemHeight = | ||
this.items.length > 0 | ||
? scrollBehaviorY.contentSize / this.items.length | ||
: 0 | ||
boundary.maxScrollPos = -this.itemHeight * (this.items.length - 1) | ||
boundary.minScrollPos = 0 | ||
} | ||
) | ||
scrollBehaviorY.hooks.on( | ||
scrollBehaviorY.hooks.eventTypes.momentum, | ||
@@ -121,2 +177,3 @@ ( | ||
).y | ||
// TODO algorithm optimize | ||
const maxDistance = 1000 | ||
@@ -137,3 +194,3 @@ const minDuration = 800 | ||
momentumInfo.destination = validWheel.y | ||
momentumInfo.duration = this.options.adjustTime as number | ||
momentumInfo.duration = this.options.adjustTime | ||
this.selectedIndex = validWheel.index | ||
@@ -158,6 +215,16 @@ } | ||
this.target = this.items[this.findNearestValidWheel(y).index] | ||
// don't dispatch scrollEnd when it is a click operation | ||
// don't dispatch scrollEnd when forceStop from transition or animation | ||
return true | ||
} | ||
) | ||
// bs.stop() to make wheel stop at a correct position | ||
animater.hooks.on(animater.hooks.eventTypes.callStop, () => { | ||
const index = Array.prototype.slice | ||
.call(this.items, 0) | ||
.indexOf(this.target as Element) | ||
if (index > 0) { | ||
const y = -(index * this.itemHeight) | ||
animater.translate({ x: 0, y }) | ||
} | ||
}) | ||
@@ -174,28 +241,10 @@ // Translater | ||
refresh() { | ||
const scroller = this.scroll.scroller | ||
const scrollBehaviorY = scroller.scrollBehaviorY | ||
private refreshBoundary() { | ||
const { scrollBehaviorX, scrollBehaviorY } = this.scroll.scroller | ||
scrollBehaviorX.refresh() | ||
scrollBehaviorY.refresh() | ||
} | ||
// adjust contentSize | ||
const contentRect = getRect(scroller.content) | ||
scrollBehaviorY.contentSize = contentRect.height | ||
this.items = scroller.content.children | ||
this.checkWheelAllDisabled() | ||
this.itemHeight = this.items.length | ||
? scrollBehaviorY.contentSize / this.items.length | ||
: 0 | ||
if (this.selectedIndex === undefined) { | ||
this.selectedIndex = this.options.selectedIndex || 0 | ||
} | ||
this.scroll.maxScrollX = 0 | ||
this.scroll.maxScrollY = -this.itemHeight * (this.items.length - 1) | ||
this.scroll.minScrollX = 0 | ||
this.scroll.minScrollY = 0 | ||
scrollBehaviorY.hasScroll = | ||
scrollBehaviorY.options && this.scroll.maxScrollY < this.scroll.minScrollY | ||
private handleSelectedIndex() { | ||
this.selectedIndex = this.options.selectedIndex | ||
} | ||
@@ -207,7 +256,20 @@ | ||
wheelTo(index = 0, time = 0, ease?: EaseItem, isSlient?: boolean) { | ||
wheelTo(index = 0, time = 0, ease?: EaseItem): boolean { | ||
const y = -index * this.itemHeight | ||
this.scroll.scrollTo(0, y, time, ease, isSlient) | ||
const currentY = Math.round(this.scroll.y) | ||
this.scroll.scrollTo(0, y, time, ease) | ||
return y === currentY | ||
} | ||
private wheelToAfterClick(index = 0, time = 0, ease: EaseItem) { | ||
const needDispatchScrollEnd = this.wheelTo(index, time, ease) | ||
// startpoint === endpoint | ||
// manually trigger scrollEnd | ||
if (needDispatchScrollEnd) { | ||
const hooks = this.scroll.scroller.hooks | ||
hooks.trigger(hooks.eventTypes.scrollEnd) | ||
} | ||
} | ||
private transitionDuration(time: number) { | ||
@@ -231,6 +293,8 @@ for (let i = 0; i < this.items.length; i++) { | ||
for (let i = 0; i < this.items.length; i++) { | ||
let deg = rotate * (y / this.itemHeight + i) | ||
const deg = rotate * (y / this.itemHeight + i) | ||
// Too small value is invalid in some phones, issue 1026 | ||
const SafeDeg = deg.toFixed(3) | ||
;(this.items[i] as HTMLElement).style[ | ||
style.transform as any | ||
] = `rotateX(${deg}deg)` | ||
] = `rotateX(${SafeDeg}deg)` | ||
} | ||
@@ -284,30 +348,8 @@ } | ||
index: this.wheelItemsAllDisabled ? -1 : currentIndex, | ||
y: -currentIndex * this.itemHeight | ||
y: -currentIndex * this.itemHeight, | ||
} | ||
} | ||
private normalizeOptions() { | ||
const options = (this.options = isPlainObject(this.options) | ||
? this.options | ||
: {}) | ||
if (!options.wheelWrapperClass) { | ||
options.wheelWrapperClass = 'wheel-scroll' | ||
} | ||
if (!options.wheelItemClass) { | ||
options.wheelItemClass = 'wheel-item' | ||
} | ||
if (!options.rotate) { | ||
options.rotate = 25 | ||
} | ||
if (!options.adjustTime) { | ||
options.adjustTime = 400 | ||
} | ||
if (!options.wheelDisabledItemClass) { | ||
options.wheelDisabledItemClass = 'wheel-disabled-item' | ||
} | ||
} | ||
private checkWheelAllDisabled() { | ||
const wheelDisabledItemClassName = this.options | ||
.wheelDisabledItemClass as string | ||
const wheelDisabledItemClassName = this.options.wheelDisabledItemClass | ||
const items = this.items | ||
@@ -314,0 +356,0 @@ this.wheelItemsAllDisabled = true |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
56706
1388
0
Updated@better-scroll/core@^2.0.0