在weui.js源碼中找到以下方法:
_util2.default.fn.scroll = function (options) {
var _this = this;
var defaults = _util2.default.extend({
items: [], // 數據
scrollable: '.weui-picker__content', // 滾動的元素
offset: 2, // 列表初始化時的偏移量(列表初始化時,選項是聚焦在中間的,通過offset強制往上挪3項,以達到初始選項是為頂部的那項)
rowHeight: 48, // 列表每一行的高度
onChange: _util2.default.noop, // onChange回調
temp: null, // translate的緩存
bodyHeight: 5 * 48 // picker的高度,用於輔助點擊滾動的計算
}, options);
var items = defaults.items.map(function (item) {
return '<div class="weui-picker__item' + (item.disabled ? ' weui-picker__item_disabled' : '') + '">' + ((typeof item === 'undefined' ? 'undefined' : _typeof(item)) == 'object' ? item.label : item) + '</div>';
}).join('');
var $this = (0, _util2.default)(this);
$this.find('.weui-picker__content').html(items);
/*******************添加的內容:動態獲取 weui-picker__item的高度*****************************/
if($this.find(".weui-picker__item").length > 0){
defaults.rowHeight = $this.find(".weui-picker__item")[0].offsetHeight;
defaults.bodyHeight = $this.find(".weui-picker__item")[0].offsetHeight * 5;
}
/***************************************************************************************/
var $scrollable = $this.find(defaults.scrollable); // 可滾動的元素
var start = void 0; // 保存開始按下的位置
var end = void 0; // 保存結束時的位置
var startTime = void 0; // 開始觸摸的時間
var translate = void 0; // 緩存 translate
var points = []; // 記錄移動點
// 首次觸發選中事件
// 如果有緩存的選項,則用緩存的選項,否則使用中間值。
if (defaults.temp !== null && defaults.temp < defaults.items.length) {
var index = defaults.temp;
defaults.onChange.call(this, defaults.items[index], index);
translate = (defaults.offset - index) * defaults.rowHeight;
console.log("translate:"+translate);
} else {
var _index = getDefaultIndex(defaults.items);
defaults.onChange.call(this, defaults.items[_index], _index);
translate = getDefaultTranslate(defaults.offset, defaults.rowHeight, defaults.items);
console.log("translate:"+translate);
}
setTranslate($scrollable, translate);
var stop = function stop(diff) {
translate += diff;
// 移動到最接近的那一行
translate = Math.round(translate / defaults.rowHeight) * defaults.rowHeight;
var max = getMax(defaults.offset, defaults.rowHeight);
var min = getMin(defaults.offset, defaults.rowHeight, defaults.items.length);
// 不要超過最大值或者最小值
if (translate > max) {
translate = max;
}
if (translate < min) {
translate = min;
}
// 如果是 disabled 的就跳過
var index = defaults.offset - translate / defaults.rowHeight;
while (!!defaults.items[index] && defaults.items[index].disabled) {
diff > 0 ? ++index : --index;
}
translate = (defaults.offset - index) * defaults.rowHeight;
setTransition($scrollable, .3);
setTranslate($scrollable, translate);
// 觸發選擇事件
defaults.onChange.call(_this, defaults.items[index], index);
};
function _start(pageY) {
start = pageY;
startTime = +new Date();
}
function _move(pageY) {
end = pageY;
var diff = end - start;
setTransition($scrollable, 0);
setTranslate($scrollable, translate + diff);
startTime = +new Date();
points.push({ time: startTime, y: end });
if (points.length > 40) {
points.shift();
}
}
function _end(pageY) {
if (!start) return;
/**
* 思路:
* 0. touchstart 記錄按下的點和時間
* 1. touchmove 移動時記錄前 40個經過的點和時間
* 2. touchend 松開手時, 記錄該點和時間. 如果松開手時的時間, 距離上一次 move時的時間超過 100ms, 那么認為停止了, 不執行慣性滑動
* 如果間隔時間在 100ms 內, 查找 100ms 內最近的那個點, 和松開手時的那個點, 計算距離和時間差, 算出速度
* 速度乘以慣性滑動的時間, 例如 300ms, 計算出應該滑動的距離
*/
var endTime = new Date().getTime();
var relativeY = $this[0].getBoundingClientRect().top + defaults.bodyHeight / 2;
end = pageY;
// 如果上次時間距離松開手的時間超過 100ms, 則停止了, 沒有慣性滑動
if (endTime - startTime > 100) {
//如果end和start相差小於10,則視為
if (Math.abs(end - start) > 10) {
stop(end - start);
} else {
stop(relativeY - end);
}
} else {
if (Math.abs(end - start) > 10) {
var endPos = points.length - 1;
var startPos = endPos;
for (var i = endPos; i > 0 && startTime - points[i].time < 100; i--) {
startPos = i;
}
if (startPos !== endPos) {
var ep = points[endPos];
var sp = points[startPos];
var t = ep.time - sp.time;
var s = ep.y - sp.y;
var v = s / t; // 出手時的速度
var diff = v * 150 + (end - start); // 滑行 150ms,這里直接影響“靈敏度”
stop(diff);
} else {
stop(0);
}
} else {
stop(relativeY - end);
}
}
start = null;
}
/**
* 因為現在沒有移除匿名函數的方法,所以先暴力移除(offAll),並且改變$scrollable。
*/
$scrollable = $this.offAll().on('touchstart', function (evt) {
_start(evt.changedTouches[0].pageY);
}).on('touchmove', function (evt) {
_move(evt.changedTouches[0].pageY);
evt.preventDefault();
}).on('touchend', function (evt) {
_end(evt.changedTouches[0].pageY);
}).find(defaults.scrollable);
// 判斷是否支持touch事件 https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js
var isSupportTouch = 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch;
if (!isSupportTouch) {
$this.on('mousedown', function (evt) {
_start(evt.pageY);
evt.stopPropagation();
evt.preventDefault();
}).on('mousemove', function (evt) {
if (!start) return;
_move(evt.pageY);
evt.stopPropagation();
evt.preventDefault();
}).on('mouseup mouseleave', function (evt) {
_end(evt.pageY);
evt.stopPropagation();
evt.preventDefault();
});
}
};
動態修改rowHeight,bodyHeight的高度:
if($this.find(".weui-picker__item").length > 0){
defaults.rowHeight = $this.find(".weui-picker__item")[0].offsetHeight;
defaults.bodyHeight = $this.find(".weui-picker__item")[0].offsetHeight * 5;
}
