提问人:Amitesh Verma 提问时间:11/15/2023 更新时间:11/15/2023 访问量:17
我正在尝试获取在画布上单击以在反应中选择我的时针或分针的坐标,但坐标不准确 [关闭]
I am trying to get the coordinates of click on the canvas to select my hour or minute hand on clock in react but the coordinates are not accurate [closed]
问:
我正在制作一个带有时针和分针的时钟,我应该能够通过单击它们来选择时针/分针。为此,我正在计算点击距离时针和分针末端的距离,并且我选择它。但它没有按预期工作,因为点击的坐标不准确,就像它与我的鼠标点击不同一样,我也通过在点击时画红点在代码中确认了这一点。有人可以帮忙如何获得点击的准确坐标吗?
整个代码是用 React 编写的,并使用顺风 css 设计。
import React, { useEffect, useState } from 'react';
import NumberPanel from '../NumberPanel';
function Clock() {
const [hourHandRotation, setHourHandRotation] = useState(0);
const [minuteHandRotation, setMinuteHandRotation] = useState(0);
const [dragging, setDragging] = useState(false);
const [selectedHand, setSelectedHand] = useState(null);
const handleCheckboxChange = (hand) => {
setSelectedHand(hand);
};
useEffect(() => {
const canvas = document.getElementById("outer-clock-canvas");
const ctx = canvas.getContext("2d");
const x_center_of_clock = canvas.width / 2;
const y_center_of_clock = canvas.height / 2;
const outer_clock_radius = canvas.width / 2;
const padding = 30;
// Creating an input field at each hour
for (let time = 1; time <= 12; time++) {
const angle = (time / 12) * (2 * Math.PI);
const distanceFromCenter = outer_clock_radius - padding;
const x = x_center_of_clock + distanceFromCenter * Math.cos(angle);
const y = y_center_of_clock + distanceFromCenter * Math.sin(angle);
// Creating a new input field for clock time
const inputField = document.createElement("input");
inputField.className = "input-field";
inputField.style.position = "absolute";
inputField.style.width = "30px";
inputField.style.height = "30px";
inputField.style.borderRadius = "50%";
inputField.style.left = x - 15 + "px";
inputField.style.top = y - 15 + "px";
inputField.style.backgroundColor = "#9690EA";
inputField.readOnly = false;
document.getElementById("input-fields-container").appendChild(inputField);
}
ctx.fillStyle = "#FFFFFF";
ctx.strokeStyle = "#FFFFFF";
ctx.lineWidth = 2;
// Clock canvas
const outer_clock_circle = new Path2D();
outer_clock_circle.arc(x_center_of_clock, y_center_of_clock, outer_clock_radius, 0, 2 * Math.PI);
ctx.fill(outer_clock_circle);
ctx.stroke(outer_clock_circle);
// Minute division
const minuteDivisions = 60;
for (let division = 1; division <= minuteDivisions; division++) {
const angle = (division / minuteDivisions) * (2 * Math.PI);
const x1 = x_center_of_clock + (outer_clock_radius - 10) * Math.cos(angle);
const y1 = y_center_of_clock + (outer_clock_radius - 10) * Math.sin(angle);
const x2 = x_center_of_clock + outer_clock_radius * Math.cos(angle);
const y2 = y_center_of_clock + outer_clock_radius * Math.sin(angle);
// Draw the minute division
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.strokeStyle = "#0F2C59";
ctx.lineWidth = 2;
ctx.stroke();
}
drawClockHands(hourHandRotation, minuteHandRotation);
// Adding event functions
canvas.addEventListener("mousedown", handleMouseDown);
canvas.addEventListener("mousemove", handleMouseMove);
canvas.addEventListener("mouseup", handleMouseUp);
return () => {
// Cleanup event listeners on component unmount
canvas.removeEventListener("mousedown", handleMouseDown);
canvas.removeEventListener("mousemove", handleMouseMove);
canvas.removeEventListener("mouseup", handleMouseUp);
// canvasElem.removeEventListener("click", handleCanvasClick);
};
}, [hourHandRotation, minuteHandRotation, dragging]);
// Function to draw clock hands
function drawClockHands(hourAngle, minuteAngle) {
// Getting reference
const canvas = document.getElementById("outer-clock-canvas");
const ctx = canvas.getContext("2d");
const x_center_of_clock = canvas.width / 2;
const y_center_of_clock = canvas.height / 2;
const outer_clock_radius = canvas.width / 2;
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Outline of canvas
ctx.beginPath();
ctx.arc(x_center_of_clock, y_center_of_clock, outer_clock_radius, 0, 2 * Math.PI);
// ctx.stroke();
// Draw minute divisions
drawMinuteDivisions();
// Draw hour hand
ctx.beginPath();
ctx.moveTo(x_center_of_clock, y_center_of_clock);
const hourHandLength = outer_clock_radius * 0.6;
const hourX = x_center_of_clock + hourHandLength * Math.cos(hourHandRotation);
const hourY = y_center_of_clock + hourHandLength * Math.sin(hourHandRotation);
ctx.lineTo(hourX, hourY);
ctx.lineWidth = 20;
ctx.strokeStyle = "#0F2C59";
ctx.stroke();
// Draw minute hand
ctx.beginPath();
ctx.moveTo(x_center_of_clock, y_center_of_clock);
const minuteHandLength = outer_clock_radius * 0.8;
const minuteX = x_center_of_clock + minuteHandLength * Math.cos(minuteHandRotation);
const minuteY = y_center_of_clock + minuteHandLength * Math.sin(minuteHandRotation);
ctx.lineTo(minuteX, minuteY);
ctx.lineWidth = 15;
ctx.strokeStyle = "red";
ctx.stroke();
}
// Function to draw minute divisions
function drawMinuteDivisions() {
// Getting reference
const canvas = document.getElementById("outer-clock-canvas");
const ctx = canvas.getContext("2d");
const x_center_of_clock = canvas.width / 2;
const y_center_of_clock = canvas.height / 2;
const outer_clock_radius = canvas.width / 2;
const minuteDivisions = 60;
for (let division = 1; division <= minuteDivisions; division++) {
const angle = (division / minuteDivisions) * (2 * Math.PI);
const x1 = x_center_of_clock + (outer_clock_radius - 10) * Math.cos(angle);
const y1 = y_center_of_clock + (outer_clock_radius - 10) * Math.sin(angle);
const x2 = x_center_of_clock + outer_clock_radius * Math.cos(angle);
const y2 = y_center_of_clock + outer_clock_radius * Math.sin(angle);
// Draw the minute division
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.strokeStyle = "#0F2C59";
ctx.lineWidth = 2;
ctx.stroke();
}
}
function drawHourHands(ctx, outer_clock_radius, x_center_of_clock, y_center_of_clock) {
// Draw hour hand
const hourHandLength = outer_clock_radius * 0.6;
const hourHandX = x_center_of_clock + hourHandLength * Math.cos(hourHandRotation - Math.PI / 2);
const hourHandY = y_center_of_clock + hourHandLength * Math.sin(hourHandRotation - Math.PI / 2);
ctx.beginPath();
ctx.moveTo(x_center_of_clock, y_center_of_clock);
ctx.lineTo(hourHandX, hourHandY);
ctx.stroke();
}
function drawMinuteHands(ctx, outer_clock_radius, x_center_of_clock, y_center_of_clock) {
// Draw hour hand
const minuteHandLength = outer_clock_radius * 0.8;
const minuteHandX = x_center_of_clock + minuteHandLength * Math.cos(minuteHandRotation - Math.PI / 2);
const minuteHandY = y_center_of_clock + minuteHandLength * Math.sin(minuteHandRotation - Math.PI / 2);
ctx.beginPath();
ctx.moveTo(x_center_of_clock, y_center_of_clock);
ctx.lineTo(minuteHandX, minuteHandY);
ctx.stroke();
}
// function handleMouseDown(event) {
// const canvas = document.getElementById("outer-clock-canvas");
// const x_center_of_clock = canvas.width / 2;
// const y_center_of_clock = canvas.height / 2;
// const outer_clock_radius = canvas.width / 2;
// const mouseX = event.clientX - canvas.getBoundingClientRect().left;
// const mouseY = event.clientY - canvas.getBoundingClientRect().top;
// // Check if the mouse click is within the hour hand
// const hourHandLength = outer_clock_radius * 0.6;
// const hourX = x_center_of_clock + hourHandLength * Math.cos(hourHandRotation);
// const hourY = y_center_of_clock + hourHandLength * Math.sin(minuteHandRotation);
// const distanceToHourHand = Math.sqrt(
// (mouseX - hourX) ** 2 + (mouseY - hourY) ** 2
// );
// // Check if the mouse click is within the minute hand
// const minuteHandLength = outer_clock_radius * 0.8;
// const minuteX = x_center_of_clock + minuteHandLength * Math.cos(hourHandRotation);
// const minuteY = y_center_of_clock + minuteHandLength * Math.sin(minuteHandRotation);
// const distanceToMinuteHand = Math.sqrt(
// (mouseX - minuteX) ** 2 + (mouseY - minuteY) ** 2
// );
// console.log("Hour hand distance: ",distanceToHourHand);
// console.log("Minute hand distance: ",distanceToMinuteHand);
// // Determine which hand is closer to the mouse click
// if (distanceToHourHand < distanceToMinuteHand) {
// console.log("hour");
// setSelectedHand(1);
// } else {
// console.log("minute");
// setSelectedHand(2);
// }
// console.log(selectedHand);
// setDragging(true);
// }
function handleMouseDown(event) {
const canvas = document.getElementById("outer-clock-canvas");
const ctx = canvas.getContext("2d");
const canvasRect = canvas.getBoundingClientRect();
const mouseX = event.clientX - canvasRect.left;
const mouseY = event.clientY - canvasRect.top;
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(mouseX, mouseY, 5, 0, Math.PI * 2);
ctx.fill();
}
function handleMouseMove(event) {
const canvas = document.getElementById("outer-clock-canvas");
const x_center_of_clock = canvas.width / 2;
const y_center_of_clock = canvas.height / 2;
const outer_clock_radius = canvas.width / 2;
if (dragging) {
// const canvas = document.getElementById("outer-clock-canvas");
// const rect = canvas.getBoundingClientRect();
// const x = e.clientX - rect.left - canvas.width / 2;
// const y = e.clientY - rect.top - canvas.height / 2;
const angle = Math.atan2(
event.clientY - y_center_of_clock,
event.clientX - x_center_of_clock
);
if(selectedHand === 1){
// const newHourHandRotation = Math.atan2(y, x) + Math.PI / 2;
// hourAngleForComparison = angle;
setHourHandRotation(angle);
}
if(selectedHand === 2){
// const newMinuteHandRotation = Math.atan2(y, x) + Math.PI / 2;
// minuteAngleForComparison = angle;
setMinuteHandRotation(angle);
}
}
}
function handleMouseUp() {
setDragging(false);
setSelectedHand(0);
}
return (
<div className='mx-auto h-screen flex items-center justify-center my-16'>
<div className="relative bg-testBackground p-8 rounded-3xl h-full w-10/12">
{/* Clock content */}
<div className='absolute'>
<canvas id="outer-clock-canvas" className="p-0 m-0 absolute top-0 left-0 border-solid border-4 border-gray-800" width="700" height="700"></canvas>
<div id="input-fields-container" className="absolute top-0 left-0"></div>
</div>
{/* Buttons for selecting hands */}
<div className="flex flex-col absolute top-16 right-16">
<p className='font-bold text-3xl my-4'>Select the hand which you want to move:-</p>
<label className="flex items-center mb-2 text-2xl font-semibold ">
<input
type="checkbox"
className="form-checkbox h-6 w-6 rounded-full mr-2"
onChange={() => handleCheckboxChange(1)}
checked={selectedHand === 1}
/>
Select hour hand
</label>
<label className="flex items-center text-2xl font-semibold ">
<input
type="checkbox"
className="form-checkbox h-6 w-6 rounded-full mr-2"
onChange={() => handleCheckboxChange(2)}
checked={selectedHand === 2}
/>
Select minute hand
</label>
</div>
{/* <div className='absolute bottom-24 right-40'>
<NumberPanel/>
</div> */}
</div>
</div>
);
}
export default Clock;
我的鼠标点击与我在画布上点击的位置不同,因为我的时针和分针被错误地选择了。
答: 暂无答案
评论