mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
fix(Rate): support precisely selected (#10500)
* perf(Rate): Precisely selected * test(Rate): update rectY * fix(Rate): CR 问题修复 * Update Rate.tsx Co-authored-by: neverland <chenjiahan.jait@bytedance.com>
This commit is contained in:
parent
edd93851a4
commit
c245e0a09d
@ -1,4 +1,4 @@
|
|||||||
import { computed, defineComponent, type ExtractPropTypes } from 'vue';
|
import { computed, defineComponent, ref, type ExtractPropTypes } from 'vue';
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {
|
import {
|
||||||
@ -83,6 +83,7 @@ export default defineComponent({
|
|||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const touch = useTouch();
|
const touch = useTouch();
|
||||||
const [itemRefs, setItemRefs] = useRefs();
|
const [itemRefs, setItemRefs] = useRefs();
|
||||||
|
const groupRef = ref<Element>();
|
||||||
|
|
||||||
const untouchable = () =>
|
const untouchable = () =>
|
||||||
props.readonly || props.disabled || !props.touchable;
|
props.readonly || props.disabled || !props.touchable;
|
||||||
@ -100,28 +101,69 @@ export default defineComponent({
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let ranges: Array<{ left: number; score: number }>;
|
let ranges: Array<{
|
||||||
|
left: number;
|
||||||
|
top: number;
|
||||||
|
height: number;
|
||||||
|
score: number;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
let groupRefRect: DOMRect;
|
||||||
|
let minRectTop = Number.MAX_SAFE_INTEGER;
|
||||||
|
let maxRectTop = Number.MIN_SAFE_INTEGER;
|
||||||
|
|
||||||
const updateRanges = () => {
|
const updateRanges = () => {
|
||||||
|
groupRefRect = useRect(groupRef);
|
||||||
|
|
||||||
const rects = itemRefs.value.map(useRect);
|
const rects = itemRefs.value.map(useRect);
|
||||||
|
|
||||||
ranges = [];
|
ranges = [];
|
||||||
rects.forEach((rect, index) => {
|
rects.forEach((rect, index) => {
|
||||||
|
minRectTop = Math.min(rect.top, minRectTop);
|
||||||
|
maxRectTop = Math.max(rect.top, maxRectTop);
|
||||||
|
|
||||||
if (props.allowHalf) {
|
if (props.allowHalf) {
|
||||||
ranges.push(
|
ranges.push(
|
||||||
{ score: index + 0.5, left: rect.left },
|
{
|
||||||
{ score: index + 1, left: rect.left + rect.width / 2 }
|
score: index + 0.5,
|
||||||
|
left: rect.left,
|
||||||
|
top: rect.top,
|
||||||
|
height: rect.height,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
score: index + 1,
|
||||||
|
left: rect.left + rect.width / 2,
|
||||||
|
top: rect.top,
|
||||||
|
height: rect.height,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ranges.push({ score: index + 1, left: rect.left });
|
ranges.push({
|
||||||
|
score: index + 1,
|
||||||
|
left: rect.left,
|
||||||
|
top: rect.top,
|
||||||
|
height: rect.height,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getScoreByPosition = (x: number) => {
|
const getScoreByPosition = (x: number, y: number) => {
|
||||||
for (let i = ranges.length - 1; i > 0; i--) {
|
for (let i = ranges.length - 1; i > 0; i--) {
|
||||||
if (x > ranges[i].left) {
|
if (y >= groupRefRect.top && y <= groupRefRect.bottom) {
|
||||||
return ranges[i].score;
|
if (
|
||||||
|
x > ranges[i].left &&
|
||||||
|
y >= ranges[i].top &&
|
||||||
|
y <= ranges[i].top + ranges[i].height
|
||||||
|
) {
|
||||||
|
return ranges[i].score;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const curTop = y < groupRefRect.top ? minRectTop : maxRectTop;
|
||||||
|
|
||||||
|
if (x > ranges[i].left && ranges[i].top === curTop) {
|
||||||
|
return ranges[i].score;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return props.allowHalf ? 0.5 : 1;
|
return props.allowHalf ? 0.5 : 1;
|
||||||
@ -151,9 +193,9 @@ export default defineComponent({
|
|||||||
touch.move(event);
|
touch.move(event);
|
||||||
|
|
||||||
if (touch.isHorizontal()) {
|
if (touch.isHorizontal()) {
|
||||||
const { clientX } = event.touches[0];
|
const { clientX, clientY } = event.touches[0];
|
||||||
preventDefault(event);
|
preventDefault(event);
|
||||||
select(getScoreByPosition(clientX));
|
select(getScoreByPosition(clientX, clientY));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -185,7 +227,9 @@ export default defineComponent({
|
|||||||
|
|
||||||
const onClickItem = (event: MouseEvent) => {
|
const onClickItem = (event: MouseEvent) => {
|
||||||
updateRanges();
|
updateRanges();
|
||||||
select(allowHalf ? getScoreByPosition(event.clientX) : score);
|
select(
|
||||||
|
allowHalf ? getScoreByPosition(event.clientX, event.clientY) : score
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -226,6 +270,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div
|
||||||
|
ref={groupRef}
|
||||||
role="radiogroup"
|
role="radiogroup"
|
||||||
class={bem({
|
class={bem({
|
||||||
readonly: props.readonly,
|
readonly: props.readonly,
|
||||||
|
@ -8,6 +8,8 @@ function mockGetBoundingClientRect(items: DOMWrapper<Element>[]) {
|
|||||||
({
|
({
|
||||||
left: index * 25,
|
left: index * 25,
|
||||||
width: 25,
|
width: 25,
|
||||||
|
top: 0,
|
||||||
|
height: 25,
|
||||||
} as DOMRect);
|
} as DOMRect);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user