Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preview for the pointer with strokeWidth #169

Open
mung3477 opened this issue Aug 27, 2024 · 2 comments
Open

Preview for the pointer with strokeWidth #169

mung3477 opened this issue Aug 27, 2024 · 2 comments

Comments

@mung3477
Copy link

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

First, thank you for implementing this package. It was the only one among canvas drawing packages that supported various devices.

To enhance the user experience, I hope to see where the cursor is positioned and current stroke width.
Something like this!

Example

Describe the solution you'd like
A clear and concise description of what you want to happen.

To solve this problem, I made a custom hook to implement this.
It quite works well, and I think this feature would make this package better!

import { forwardRef, useEffect, useRef, useState } from "react";

interface StrokePreviewProps {
  top: string;
  left: string;
  strokeWidth: number;
}
const StrokePreview = forwardRef<HTMLDivElement, StrokePreviewProps>(
  ({ top, left, strokeWidth }, ref) => (
    <div
      style={{
        top,
        left,
        width: `${strokeWidth}px`,
        height: `${strokeWidth}px`,
        transform: "translate(-50%, -50%)"
      }}
      className="absolute rounded-full bg-[rgba(182,146,246,0.75)]"
      ref={ref}
    />
  )
);

function useStrokePreview() {
  const [top, setTop] = useState<string>("0px");
  const [left, setLeft] = useState<string>("0px");
  const canvasContainerRef = useRef<HTMLDivElement>(null);
  const cursorFollowerRef = useRef<HTMLDivElement>(null);
  const timeoutId = useRef<ReturnType<typeof setTimeout>>();

  useEffect(() => {
    const positionCursorFollower = (e: MouseEvent | PointerEvent) => {
      timeoutId.current = setTimeout(() => {
        if (canvasContainerRef.current) {
          const { offsetHeight, offsetWidth } = canvasContainerRef.current;

          setTop(`${Math.min(offsetHeight, Math.max(0, e.offsetY))}px`);
          setLeft(`${Math.min(offsetWidth, Math.max(0, e.offsetX))}px`);
        }
      }, 1);
    };

    if (canvasContainerRef.current) {
      canvasContainerRef.current.addEventListener(
        "mousemove",
        positionCursorFollower
      );
      canvasContainerRef.current.addEventListener(
        "pointermove",
        positionCursorFollower
      );
    }

    return () => {
      if (timeoutId.current) {
        clearTimeout(timeoutId.current);
      }
      canvasContainerRef?.current?.removeEventListener(
        "mousemove",
        positionCursorFollower
      );
      canvasContainerRef?.current?.removeEventListener(
        "pointermove",
        positionCursorFollower
      );
    };
  }, [!!canvasContainerRef.current]);

  return { top, left, canvasContainerRef, cursorFollowerRef };
}

export default StrokePreview;
export { useStrokePreview };

<div className="relative">
          <StrokePreview
            top={strokeTop}
            left={strokeLeft}
            strokeWidth={strokeWidth}
            ref={cursorFollowerRef}
          />
          <div className="mb-[20px] flex flex-col" ref={canvasContainerRef}>
            <img src={imgSrc} alt="original" />
            <ReactSketchCanvas
              style={{
                position: "absolute",
                top: 0,
                left: 0,
                cursor: "none"
              }}
              canvasColor="transparent"
              strokeColor="rgba(182, 146, 246, 0.75)"
              strokeWidth={strokeWidth}
              eraserWidth={strokeWidth}
              onStroke={onChange}
              ref={skectchCanvasRef}
            />
          </div>
</div>

And the result seems like this.
Screenshot 2024-08-27 at 4 42 45 PM

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

As I am novice in handling interactions with devices like tablets and mobile phones, I think I may have missed sth.
Thank you for reading!

@xjamundx
Copy link

Thanks for sharing this snippet. Was looking for this feature!

@mung3477
Copy link
Author

mung3477 commented Oct 31, 2024

I appreciate that you made my snippet as a part of the new PR. Thx @xjamundx !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants