sard-uniapp
Version:
sard-uniapp 是一套基于 Uniapp + Vue3 框架开发的兼容多端的 UI 组件库
128 lines (123 loc) • 4.37 kB
JavaScript
/**
```
page
╱
╭───────────────╮ viewport
╭─│─ ─ ─ ─ ─ ─ ─ ─│─╮ ╱
│ │ ╭───────────╮ │ │
│ │ │ element │ │ │
│ │ ╰───────────╯ │ │
╰─│─ ─ ─ ─ ─ ─ ─ ─│─╯
│ │
│ │
╰───────────────╯
```
# 参数
- viewportHeight: viewport 高度
- viewportScrollTop: viewport 垂直滚动值
- elementHeight: element 高度
- elementOffsetTop: element 距离页面顶部距离
# 选项
- position: element 在视窗中的位置(start, center, end, nearest)
- startOffset: element 距离视窗顶部的偏移量
- endOffset: element 距离视窗底部的偏移量
# 结果值
- viewportScrollTop: viewport 新的垂直滚动值
*/
export function getScrollIntoViewValue(viewportHeight, viewportScrollTop, elementHeight, elementOffsetTop, options = {}) {
const { startOffset = 0, endOffset = 0 } = options;
let position = options.position || 'nearest';
const elementToViewportTopOffset = elementOffsetTop - viewportScrollTop - startOffset;
const elementToViewportBottomOffset = elementOffsetTop +
elementHeight -
viewportScrollTop -
viewportHeight +
endOffset;
if (position === 'nearest') {
if (elementToViewportTopOffset >= 0 && elementToViewportBottomOffset <= 0) {
return viewportScrollTop;
}
else {
position =
Math.abs(elementToViewportTopOffset) >
Math.abs(elementToViewportBottomOffset)
? 'end'
: 'start';
}
}
let nextScrollTop = 0;
switch (position) {
case 'start':
nextScrollTop = elementOffsetTop - startOffset;
break;
case 'center':
nextScrollTop =
elementOffsetTop -
(viewportHeight - elementHeight - endOffset - startOffset) / 2 +
startOffset;
break;
case 'end':
nextScrollTop =
elementOffsetTop + elementHeight - viewportHeight + endOffset;
break;
}
return nextScrollTop;
}
/**
* @description: 匹配元素列表中第一个位于滚动盒子可视区域的元素
*/
export async function matchScrollVisible(rects, callback, options = {}) {
const { offset: optionOffset = 0, errorValue = 3 } = options;
const offset = optionOffset + errorValue;
const convertedRect = rects.map((rect, i) => {
return {
top: rect.top,
bottom: i < rects.length - 1 ? rects[i + 1].top : 0,
};
});
for (let i = 0, l = convertedRect.length; i < l; i++) {
const rect = convertedRect[i];
if (i === 0 && rect.top > offset) {
return callback(0);
}
if (rect.top <= offset && rect.bottom > offset) {
return callback(i);
}
if (i === l - 1 && rect.bottom <= offset) {
return callback(i);
}
}
}
export function getAspectFillSize(origWidth, origHeight, containerWidth, containerHeight) {
let width = 0;
let height = 0;
if (origWidth > 0 && origHeight > 0) {
if (origWidth / origHeight > containerWidth / containerHeight) {
height = containerHeight;
width = (origWidth / origHeight) * containerHeight;
}
else {
width = containerWidth;
height = (origHeight / origWidth) * containerWidth;
}
}
return [width, height];
}
export function getAspectFitSize(origWidth, origHeight, containerWidth, containerHeight) {
let width = 0;
let height = 0;
if (origWidth > 0 && origHeight > 0) {
if (origWidth / origHeight > containerWidth / containerHeight) {
width = containerWidth;
height = (origHeight / origWidth) * containerWidth;
}
else {
height = containerHeight;
width = (origWidth / origHeight) * containerHeight;
}
}
return [width, height];
}
export function getTwoPointsDistance(p1, p2) {
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}