init
This commit is contained in:
138
uni_modules/lime-shared/getRect/index.ts
Normal file
138
uni_modules/lime-shared/getRect/index.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
// @ts-nocheck
|
||||
// #ifdef UNI-APP-X && APP
|
||||
// export * from './uvue.uts'
|
||||
export { getRect, getAllRect } from './uvue.uts'
|
||||
// #endif
|
||||
|
||||
|
||||
// #ifndef UNI-APP-X && APP
|
||||
// export * from './vue.ts'
|
||||
export { getRect, getAllRect } from './vue.ts'
|
||||
// #endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取视口滚动条位置信息
|
||||
*/
|
||||
export function getViewportScrollInfo() : Promise<any> {
|
||||
return new Promise(resolve => {
|
||||
uni.createSelectorQuery()
|
||||
.selectViewport()
|
||||
.scrollOffset((res) => {
|
||||
resolve(res);
|
||||
}).exec();
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
```
|
||||
page
|
||||
╱
|
||||
╭───────────────╮ viewport
|
||||
╭─│─ ─ ─ ─ ─ ─ ─ ─│─╮ ╱
|
||||
│ │ ╭───────────╮ │ │
|
||||
│ │ │ element │ │ │
|
||||
│ │ ╰───────────╯ │ │
|
||||
╰─│─ ─ ─ ─ ─ ─ ─ ─│─╯
|
||||
│ │
|
||||
│ │
|
||||
╰───────────────╯
|
||||
```
|
||||
|
||||
# 参数
|
||||
- viewportHeight: viewport 高度
|
||||
- viewportScrollTop: viewport 垂直滚动值
|
||||
- elementHeight: element 高度
|
||||
- elementOffsetTop: element 距离页面顶部距离
|
||||
|
||||
# 选项
|
||||
- position: element 在视窗中的位置(start, center, end, nearest)
|
||||
- startOffset: element 距离视窗顶部的偏移量
|
||||
- endOffset: element 距离视窗底部的偏移量
|
||||
|
||||
# 结果值
|
||||
- viewportScrollTop: viewport 新的垂直滚动值
|
||||
|
||||
*/
|
||||
|
||||
export type ScrollIntoViewOptions = {
|
||||
/** 元素顶部需要保留的缓冲距离(默认 0) */
|
||||
startOffset ?: number;
|
||||
/** 元素底部需要保留的缓冲距离(默认 0) */
|
||||
endOffset ?: number;
|
||||
/** 滚动对齐方式:start/center/end/nearest(默认 nearest) */
|
||||
position ?: 'start' | 'center' | 'end' | 'nearest';
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算元素需要滚动到可视区域的目标滚动位置
|
||||
* @param viewportHeight 视口高度(像素)
|
||||
* @param viewportScrollTop 当前滚动位置(像素)
|
||||
* @param elementHeight 元素高度(像素)
|
||||
* @param elementOffsetTop 元素相对于父容器顶部的偏移量(像素)
|
||||
* @param options 配置选项
|
||||
* @returns 计算后的目标滚动位置(像素)
|
||||
*
|
||||
* @example
|
||||
* // 示例:将元素滚动到视口顶部对齐
|
||||
* const scrollTop = getScrollIntoViewValue(
|
||||
* 500, // 视口高度
|
||||
* 200, // 当前滚动位置
|
||||
* 100, // 元素高度
|
||||
* 300, // 元素偏移量
|
||||
* { position: 'start' }
|
||||
* );
|
||||
*/
|
||||
export function getScrollIntoViewValue(
|
||||
viewportHeight : number,
|
||||
viewportScrollTop : number,
|
||||
elementHeight : number,
|
||||
elementOffsetTop : number,
|
||||
options : ScrollIntoViewOptions = {}
|
||||
) : number {
|
||||
let { startOffset = 0, endOffset = 0, position = 'nearest'} = options;
|
||||
|
||||
// 计算元素相对于视口的上下偏移量
|
||||
const elementToViewportTopOffset = elementOffsetTop - viewportScrollTop - startOffset;
|
||||
const elementToViewportBottomOffset =
|
||||
elementOffsetTop +
|
||||
elementHeight -
|
||||
viewportScrollTop -
|
||||
viewportHeight +
|
||||
endOffset;
|
||||
|
||||
// 处理 nearest 模式,自动选择最近边缘
|
||||
if (position == 'nearest') {
|
||||
if (elementToViewportTopOffset >= 0 && elementToViewportBottomOffset <= 0) {
|
||||
return viewportScrollTop;
|
||||
}
|
||||
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;
|
||||
}
|
17
uni_modules/lime-shared/getRect/uvue.uts
Normal file
17
uni_modules/lime-shared/getRect/uvue.uts
Normal file
@@ -0,0 +1,17 @@
|
||||
// @ts-nocheck
|
||||
export function getRect(selector : string, context: ComponentPublicInstance):Promise<NodeInfo> {
|
||||
return new Promise((resolve)=>{
|
||||
uni.createSelectorQuery().in(context).select(selector).boundingClientRect(res =>{
|
||||
resolve(res as NodeInfo)
|
||||
}).exec();
|
||||
})
|
||||
}
|
||||
|
||||
export function getAllRect(selector : string, context: ComponentPublicInstance):Promise<NodeInfo[]> {
|
||||
return new Promise((resolve)=>{
|
||||
uni.createSelectorQuery().in(context).selectAll(selector).boundingClientRect(res =>{
|
||||
resolve(res as NodeInfo[])
|
||||
}).exec();
|
||||
})
|
||||
}
|
||||
|
117
uni_modules/lime-shared/getRect/vue.ts
Normal file
117
uni_modules/lime-shared/getRect/vue.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
// @ts-nocheck
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
// 当编译环境是 APP-NVUE 时,引入 uni.requireNativePlugin('dom'),具体插件用途未知
|
||||
const dom = uni.requireNativePlugin('dom')
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* 获取节点信息
|
||||
* @param selector 选择器字符串
|
||||
* @param context ComponentInternalInstance 对象
|
||||
* @param node 是否获取node
|
||||
* @returns 包含节点信息的 Promise 对象
|
||||
*/
|
||||
export function getRect(selector : string, context : ComponentInternalInstance|ComponentPublicInstance, node: boolean = false) {
|
||||
// 之前是个对象,现在改成实例,防止旧版会报错
|
||||
if(context== null) {
|
||||
return Promise.reject('context is null')
|
||||
}
|
||||
if(context.context){
|
||||
context = context.context
|
||||
}
|
||||
// #ifdef MP || VUE2
|
||||
if (context.proxy) context = context.proxy
|
||||
// #endif
|
||||
return new Promise<UniNamespace.NodeInfo>((resolve, reject) => {
|
||||
// #ifndef APP-NVUE
|
||||
const dom = uni.createSelectorQuery().in(context).select(selector);
|
||||
const result = (rect: UniNamespace.NodeInfo) => {
|
||||
if (rect) {
|
||||
resolve(rect)
|
||||
} else {
|
||||
reject('no rect')
|
||||
}
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
dom.boundingClientRect(result).exec()
|
||||
} else {
|
||||
dom.fields({
|
||||
node: true,
|
||||
size: true,
|
||||
rect: true
|
||||
}, result).exec()
|
||||
}
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
const refs = context.refs || context.$refs
|
||||
if (/#|\./.test(selector) && refs) {
|
||||
selector = selector.replace(/#|\./, '')
|
||||
if (refs[selector]) {
|
||||
selector = refs[selector]
|
||||
if(Array.isArray(selector)) {
|
||||
selector = selector[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
dom.getComponentRect(selector, (res) => {
|
||||
if (res.size) {
|
||||
resolve(res.size)
|
||||
} else {
|
||||
reject('no rect')
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export function getAllRect(selector : string, context: ComponentInternalInstance|ComponentPublicInstance, node:boolean = false) {
|
||||
if(context== null) {
|
||||
return Promise.reject('context is null')
|
||||
}
|
||||
// #ifdef MP || VUE2
|
||||
if (context.proxy) context = context.proxy
|
||||
// #endif
|
||||
return new Promise<UniNamespace.NodeInfo>((resolve, reject) => {
|
||||
// #ifndef APP-NVUE
|
||||
const dom = uni.createSelectorQuery().in(context).selectAll(selector);
|
||||
const result = (rect: UniNamespace.NodeInfo[]) => {
|
||||
if (rect) {
|
||||
resolve(rect)
|
||||
} else {
|
||||
reject('no rect')
|
||||
}
|
||||
}
|
||||
if (!node) {
|
||||
dom.boundingClientRect(result).exec()
|
||||
} else {
|
||||
dom.fields({
|
||||
node: true,
|
||||
size: true,
|
||||
rect: true
|
||||
}, result).exec()
|
||||
}
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
let { context } = options
|
||||
if (/#|\./.test(selector) && context.refs) {
|
||||
selector = selector.replace(/#|\./, '')
|
||||
if (context.refs[selector]) {
|
||||
selector = context.refs[selector]
|
||||
if(Array.isArray(selector)) {
|
||||
selector = selector[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
dom.getComponentRect(selector, (res) => {
|
||||
if (res.size) {
|
||||
resolve([res.size])
|
||||
} else {
|
||||
reject('no rect')
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
});
|
||||
};
|
Reference in New Issue
Block a user