Skip to content

Commit

Permalink
fix(Rate): support precisely selected (#10500)
Browse files Browse the repository at this point in the history
* perf(Rate): Precisely selected

* test(Rate): update rectY

* fix(Rate): CR 问题修复

* Update Rate.tsx

Co-authored-by: neverland <chenjiahan.jait@bytedance.com>
  • Loading branch information
JakeLaoyu and chenjiahan committed Apr 14, 2022
1 parent edd9385 commit c245e0a
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 11 deletions.
67 changes: 56 additions & 11 deletions packages/vant/src/rate/Rate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { computed, defineComponent, type ExtractPropTypes } from 'vue';
import { computed, defineComponent, ref, type ExtractPropTypes } from 'vue';

// Utils
import {
Expand Down Expand Up @@ -83,6 +83,7 @@ export default defineComponent({
setup(props, { emit }) {
const touch = useTouch();
const [itemRefs, setItemRefs] = useRefs();
const groupRef = ref<Element>();

const untouchable = () =>
props.readonly || props.disabled || !props.touchable;
Expand All @@ -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 = () => {
groupRefRect = useRect(groupRef);

const rects = itemRefs.value.map(useRect);

ranges = [];
rects.forEach((rect, index) => {
minRectTop = Math.min(rect.top, minRectTop);
maxRectTop = Math.max(rect.top, maxRectTop);

if (props.allowHalf) {
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 {
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--) {
if (x > ranges[i].left) {
return ranges[i].score;
if (y >= groupRefRect.top && y <= groupRefRect.bottom) {
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;
Expand Down Expand Up @@ -151,9 +193,9 @@ export default defineComponent({
touch.move(event);

if (touch.isHorizontal()) {
const { clientX } = event.touches[0];
const { clientX, clientY } = event.touches[0];
preventDefault(event);
select(getScoreByPosition(clientX));
select(getScoreByPosition(clientX, clientY));
}
};

Expand Down Expand Up @@ -185,7 +227,9 @@ export default defineComponent({

const onClickItem = (event: MouseEvent) => {
updateRanges();
select(allowHalf ? getScoreByPosition(event.clientX) : score);
select(
allowHalf ? getScoreByPosition(event.clientX, event.clientY) : score
);
};

return (
Expand Down Expand Up @@ -226,6 +270,7 @@ export default defineComponent({

return () => (
<div
ref={groupRef}
role="radiogroup"
class={bem({
readonly: props.readonly,
Expand Down
2 changes: 2 additions & 0 deletions packages/vant/src/rate/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ function mockGetBoundingClientRect(items: DOMWrapper<Element>[]) {
({
left: index * 25,
width: 25,
top: 0,
height: 25,
} as DOMRect);
return true;
});
Expand Down

0 comments on commit c245e0a

Please sign in to comment.