我正在尝试创建一个滑块测验,我想要的是在滑块上的标签悬停时出现工具提示
现在,当我将鼠标悬停在拇指及其鼠标位置上时,我可以看到工具提示 这是图片
这是我如何使用它的代码
<PrettoSlider1
ValueLabelComponent={ValueLabelComponent2}
/>
const ValueLabelComponent2 = (props) => {
const { children, value } = props;
if (value === 0) {
return (
<Tooltip placement="top" title={"Strongly disagree"}>
{children}
</Tooltip>
);
} else if (value <= 1) {
return (
<Tooltip placement="top" title={"Disagree"}>
{children}
</Tooltip>
);
} else if (value <= 2) {
return (
<Tooltip placement="top" title={"Neutral"}>
{children}
</Tooltip>
);
} else if (value <= 3) {
return (
<Tooltip placement="top" title={"Agree"}>
{children}
</Tooltip>
);
} else if (value <= 4) {
return (
<Tooltip placement="top" title={"Strongly agree"}>
{children}
</Tooltip>
);
} else {
return (
<Tooltip placement="top" title={""}>
{children}
</Tooltip>
);
}
};
是否有可能,如果我像第二张图片中那样悬停,我可以在没有拇指的情况下获得工具提示
我必须实现一个类似的用例并提出以下解决方案。因此,如果您偶然发现这个问题,您可能会发现它很有用。
在我的解决方案中,我跟踪滑块内的鼠标光标 X 坐标,并使用到鼠标光标的距离计算最近的标记索引。当用户将鼠标悬停在滑块上时,将显示关闭标记的工具提示并跟随光标。看起来像这样:
因此,用户在单击当前位置时会看到将要选择的标记的工具提示(似乎滑块组件使用类似的机制来确定要选择哪个谨慎的步骤/标记)。
它可能不是最优雅或最高性能的解决方案,但它非常适合我的用例。
代码如下:
import * as React from "react";
import Box from "@mui/material/Box";
import Slider from "@mui/material/Slider";
import { Tooltip } from "@mui/material";
export default function SliderWithTooltips() {
const [markTooltip, setMarkTooltip] = React.useState("");
const handleMouseMove = React.useCallback(
(event: React.MouseEvent<HTMLDivElement>) => {
// Determines the closest mark index to the mouse cursor by calculating
// the distance of the relative X coordinate (relative to the slider element) of
// the mouse cursor and the mark dom element.
const mouseRelativeX =
event.clientX - event.currentTarget.getBoundingClientRect().left;
const sliderMarks = extractMarkElementRelativeXValues(
event.currentTarget
);
let closestMarkIndex = 0;
let closestDistance = Number.MAX_VALUE;
let lastDistance = closestDistance;
for (const mark of sliderMarks) {
const distance = Math.abs(mouseRelativeX - mark.relativeX);
// If the distance is increasing again, we have passed the closest mark and can abort the loop.
if (distance > lastDistance) {
break;
}
if (distance < closestDistance) {
closestDistance = distance;
closestMarkIndex = mark.index;
}
lastDistance = distance;
}
setMarkTooltip(markTooltips[closestMarkIndex]);
},
[setMarkTooltip]
);
return (
<Box sx={{ width: 600, p: 4 }}>
<Tooltip title={markTooltip} followCursor>
<Slider
valueLabelDisplay="auto"
step={null}
marks={marks}
min={0}
max={9}
onMouseMove={handleMouseMove}
/>
</Tooltip>
</Box>
);
}
function extractMarkElementRelativeXValues(sliderElement: HTMLSpanElement) {
const sliderLeftX = sliderElement.getBoundingClientRect().left;
return Array.from(sliderElement.getElementsByClassName("MuiSlider-mark")).map(
(element) => ({
index: Number(element.getAttribute("data-index")),
relativeX: element.getBoundingClientRect().left - sliderLeftX,
})
);
}
const marks = [
{ value: 0 },
{ value: 1, label: "1" },
{ value: 2, label: "2" },
{ value: 3, label: "3" },
{ value: 4, label: "4" },
{ value: 5, label: "5" },
{ value: 6, label: "6" },
{ value: 7, label: "7" },
{ value: 8, label: "8" },
{ value: 9, label: "9" },
];
const markTooltips = [
"No value",
"Some tooltip 1",
"Some tooltip 2",
"Some tooltip 3",
"Some tooltip 4",
"Some tooltip 5",
"Some tooltip 6",
"Some tooltip 7",
"Some tooltip 8",
"Some tooltip 9",
];
我还在此处创建了一个 CodeSandbox 示例:https://codesandbox.io/p/sandbox/goofy-lehmann-5ljcdn?file=%2Fsrc%2FDemo.tsx
HTH, 本