我正在尝试获取在画布上单击以在反应中选择我的时针或分针的坐标,但坐标不准确 [关闭]

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]

提问人:Amitesh Verma 提问时间:11/15/2023 更新时间:11/15/2023 访问量:17

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将帮助其他人回答这个问题。

7天前关闭。

我正在制作一个带有时针和分针的时钟,我应该能够通过单击它们来选择时针/分针。为此,我正在计算点击距离时针和分针末端的距离,并且我选择它。但它没有按预期工作,因为点击的坐标不准确,就像它与我的鼠标点击不同一样,我也通过在点击时画红点在代码中确认了这一点。有人可以帮忙如何获得点击的准确坐标吗?

整个代码是用 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;

我的鼠标点击与我在画布上点击的位置不同,因为我的时针和分针被错误地选择了。

reactjs html5-canvas 顺风-css 时钟

评论


答: 暂无答案