【发布时间】:2022-07-03 19:53:30
【问题描述】:
我正在为只有两个可能答案的问题开发自定义输入,例如:“是” 或 “否”。 Here's 一个工作示例,here 你可以阅读源代码(它也适用于触摸屏)。
这个想法是使用与“滑动打开”滑块输入类似的原理,但我试图让拇指施加一点阻力。我的实现包括计算拖动运动的速度并让拇指对其做出响应,因此,尽管指针(手指或鼠标)可能接近答案,但如果速度降低,拇指会回到原点。因此,与其说是实际拖动拇指,不如说是快速将指针朝所需答案的方向移动。
问题是,它目前有点不稳定和不稳定。那么,有没有办法让拇指移动更顺畅呢?我的实现中没有任何部分是永久性的,因此请随意尝试和修改任何内容。另外,我无论如何都不是JS方面的专家,所以请不要太过分,好吗?提前致谢。干杯
代码也在这里。
HTML
<!DOCTYPE html>
<html>
<head>
<title>Yes or No?</title>
</head>
<body>
<canvas id="display"></canvas>
</body>
</html>
JS
const displayCanvas = document.querySelector("#display");
const displayContext = displayCanvas.getContext("2d");
const maxX = displayCanvas.width = 400;
const maxY = displayCanvas.height = 100;
const bgColor = "#000";
const fgColor = "#fff";
const thumbRestX = maxX / 2;
let thumbX = thumbRestX;
let thumbY = maxY / 2;
let yesAnswerX = (maxX / 6) * 5;
let yesAnswerY = maxY / 2;
let noAnswerX = maxX / 6;
let noAnswerY = maxY / 2;
let pointerPrevX = thumbX;
let pointerX = thumbX;
let isDragging = false;
let isAnswered = false;
const setup = () => {
const startDragging = () => {
isDragging = true;
};
const stopDragging = () => {
isDragging = false;
};
const monitorPointer = (newX) => {
pointerPrevX = pointerX;
pointerX = newX;
};
displayCanvas
.addEventListener("mousedown", startDragging);
displayCanvas
.addEventListener("mouseup", stopDragging);
displayCanvas
.addEventListener("mousemove", (e) => {
monitorPointer(
e.clientX - e.target.getBoundingClientRect().left);
});
displayCanvas
.addEventListener("touchstart", (e) => {
e.preventDefault();
startDragging();
});
displayCanvas
.addEventListener("touchend", stopDragging);
displayCanvas
.addEventListener("touchmove", (e) => {
const touch = e.touches[0];
monitorPointer(
touch.clientX - e.target.getBoundingClientRect().left);
});
};
const evaluate = () => {
if (!isAnswered && isDragging) {
thumbX = thumbRestX + (pointerX - pointerPrevX - 1) * 2;
if (thumbX >= yesAnswerX) {
isAnswered = true;
thumbX = yesAnswerX;
}
if (thumbX <= noAnswerX) {
isAnswered = true;
thumbX = noAnswerX;
}
}
};
const render = () => {
const ctx = displayContext;
ctx.clearRect(0, 0, maxX, maxY);
// Background
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, maxX, maxY);
// Thumb
ctx.fillStyle = fgColor;
ctx.beginPath();
ctx.arc(thumbX, thumbY, 20, 0, Math.PI * 2, true);
ctx.fill();
// Yes answer
ctx.fillStyle = fgColor;
ctx.font = "50px monospace";
ctx.textAlign = "center";
ctx.fillText("YES", yesAnswerX, yesAnswerY);
// No answer
ctx.fillStyle = fgColor;
ctx.font = "50px monospace";
ctx.textAlign = "center";
ctx.fillText("NO", noAnswerX, noAnswerY);
};
function run () {
const evaluateTimeoutRate = 20;
let evaluateTimeoutID;
setup();
const evaluateLoop = () => {
evaluate();
evaluateTimeoutID =
setTimeout(evaluateLoop, evaluateTimeoutRate);
};
evaluateTimeoutID =
setTimeout(evaluateLoop, evaluateTimeoutRate);
const renderLoop = () => {
render();
requestAnimationFrame(renderLoop);
};
requestAnimationFrame(renderLoop);
}
run();
【问题讨论】:
标签: javascript canvas mouseevent touch-event