spiridonov-oa / react-whiteboard-pdf

MIT License
9 stars 11 forks source link

Is it possible to control the scope of the infinitely expanding sketch board? #12

Closed bedcoding closed 11 months ago

bedcoding commented 1 year ago
  1. Is it possible to adjust the scope of the sketch board? (I want to scroll just a little bit.) my sketch board stretches forever. So it feels like sailing on an open sea.

  2. Is it possible to display a scroll on the sketch board? There were times when I couldn't find where I was.

https://github.com/spiridonov-oa/react-whiteboard-pdf/assets/33927558/4a68b3d7-d7c9-47a9-a6db-8cd2d4293768

nabhiraj commented 1 year ago

hi, @spiridonov-oa , @bedcoding :)

great project !

I saw that we can scroll down/up forever and after long work it becomes difficult to find the original starting position, I have added the button to go back to the initial location where we have started, if you like the changes we call pull them, looking forward to working and learning more with you.

https://github.com/nabhiraj/react-whiteboard-pdf

bedcoding commented 1 year ago

I saw your code. Good idea.

        if(vpt[5]>600) vpt[5]=600;
        if(vpt[5]<-600) vpt[5]=-600




I modified your code like this. thank you. (I modified it to take the value of the current scale as a parameter.)

        // Limit y-axis range based on current scale
        const windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

        const addScroll = 600;
        const scale = params ? params.scale : 1;
        const zoomInMinusValue = (windowHeight * scale - (windowHeight));
        const zoomOutPlusValue = (windowHeight * (1 - scale));

        // top
        if (vpt[5] > addScroll * scale) {
          vpt[5] = addScroll * scale;
        }

        // zoom in && bottom
        else if (scale >= 1 && vpt[5] < -(addScroll * scale) - zoomInMinusValue) {
          vpt[5] = -(addScroll * scale) - zoomInMinusValue;
        }

        // zoom out && bottom
        else if (scale < 1 && vpt[5] < -(addScroll * scale) + zoomOutPlusValue) {
          vpt[5] = -(addScroll * scale) + zoomOutPlusValue;
        }

https://github.com/spiridonov-oa/react-whiteboard-pdf/assets/33927558/4e435449-4fab-4e7e-b931-26611546afcb

bedcoding commented 11 months ago

I checked and it was more accurate to use useRef.

    const canvasRef = useRef(null);
    const containerElement = this.canvasRef.current;
    const containerSize = axis === "x" ? containerElement.offsetWidth : containerElement.offsetHeight;

example)

        const e = opt.e;
        let vpt = canvas.viewportTransform;
        vpt[4] -= e.deltaX;
        vpt[5] -= e.deltaY;

        // ----- add axis limit -----
        try {
          vpt[4] = that.axisLimit({ params, vpt: vpt[4], axis: "x" });
          vpt[5] = that.axisLimit({ params, vpt: vpt[5], axis: "y" });
        } catch (error) {
          console.log(error);
        }
  axisLimit({ params, vpt, axis }) {
    const containerElement = this.canvasRef.current;
    if (!containerElement) {
      return vpt;
    }

    let result = vpt;
    const containerSize = (axis === "x") ? containerElement.offsetWidth : containerElement.offsetHeight;

    const addScroll = 600;
    const scale = params ? params.scale : 1;
    const zoomInMinusValue = (containerSize * scale - (containerSize));
    const zoomOutPlusValue = (containerSize * (1 - scale));

    // left || top
    if (result > addScroll * scale) {
      result = addScroll * scale;
    }

    // zoom in && right || zoom in && bottom
    else if (scale >= 1 && result < -(addScroll * scale) - zoomInMinusValue) {
      result = -(addScroll * scale) - zoomInMinusValue;
    }

    // zoom out && right || zoom out && bottom
    else if (scale < 1 && result < -(addScroll * scale) + zoomOutPlusValue) {
      result = -(addScroll * scale) + zoomOutPlusValue;
    }

    return result;
  }
bedcoding commented 11 months ago

When I limited the scope of the sketch, it sometimes went out of scope when I reduced the magnification at the end of the screen.

So, when I reduced the magnification at the end, I forced the screen to move inward, but it was not adjusted precisely. Is there a better way?

  // <Before change>
  changeZoom({ point, scale }) {
    if (!point) {
      const width = this.canvas.width;
      const height = this.canvas.height;
      point = { x: width / 2, y: height / 2 };
    }

    const minZoom = this.canvasConfig.minZoom;
    const maxZoom = this.canvasConfig.maxZoom;

    scale = this.canvas.getZoom() * scale;
    scale = scale < minZoom ? minZoom : scale > maxZoom ? maxZoom : scale;

    this.canvas.zoomToPoint(point, scale);
    this.onZoom({ point, scale });
  }


  // <after>
  changeZoom2({ point, scale }) {
    if (!point) {
      const width = this.canvas.width;
      const height = this.canvas.height;
      point = { x: width / 2, y: height / 2 };
    }

    const minZoom = this.canvasConfig.minZoom;
    const maxZoom = this.canvasConfig.maxZoom;

    scale = this.canvas.getZoom() * scale;
    scale = scale < minZoom ? minZoom : scale > maxZoom ? maxZoom : scale;

    const originalVpt = this.canvas.viewportTransform;  // Position before changing the magnification  // 배율 변경 전 위치
    this.canvas.zoomToPoint(point, scale);
    this.onZoom({ point, scale });

    // The logic I added because there was a problem with the screen going out of the transparent wall border I had set when I zoomed out while reaching the end of the wall.  // 벽 끝에 닿은 상태에서 화면 축소를 하면 내가 설정한 투명벽 테두리를 벗어나는 문제가 있어서 추가한 로직
    if(scale < 1) {
      const fineTuningLine = 3;

      // Baseline to check whether you are currently close to the wall (Note: If this number is large, it will not work at magnifications below 50%, so set it appropriately small)  // 현재 벽 쪽에 가까이 간 상태인지 체크하기 위한 기준선 (참고: 이 수치가 크면 50% 이하 배율에서는 안 먹혀서 적당히 작게 설정함)
      const containerElement = this.canvasRef.current;
      const widthBaseline = containerElement.offsetWidth / fineTuningLine;
      const heightBaseline = containerElement.offsetHeight / fineTuningLine;

      // Press to zoom out. Compare previous and next values.  // 화면 축소 누르기 이전 값과 이후 값을 비교함
      const newVpt = this.canvas.viewportTransform;  // Position after changing magnification  // 배율 변경 후 위치
      let widthDifference =  Math.abs(originalVpt[4] - newVpt[4]);
      let heightDifference = Math.abs(originalVpt[5] - newVpt[5]);

      // ex) left: 1920 || right: -1920
      if(newVpt[4] > widthBaseline) {
        console.log("biased to the left - 왼쪽에 치우침");
        newVpt[4] -= widthDifference;
      } else if(newVpt[4] < -widthBaseline) {
        console.log("biased to the right - 오른쪽에 치우침");
        newVpt[4] += widthDifference;
      }

      // ex) top: 1080 || bottom: -1080
      if(newVpt[5] > heightBaseline) {
        console.log("biased towards the top - 위쪽에 치우침");
        newVpt[5] -= heightDifference;
      } else if(newVpt[5] < -heightBaseline) {
        console.log("biased towards the bottom - 아래쪽에 치우침");
        newVpt[5] += heightDifference;
      }
    }
  }
bedcoding commented 11 months ago

I think I solved the problem. I will later consider whether it can be reflected in this library as well.

  changeZoom2({ point, scale }) {
    if (!point) {
      const width = this.canvas.width;
      const height = this.canvas.height;
      point = { x: width / 2, y: height / 2 };
    }

    const minZoom = this.canvasConfig.minZoom;
    const maxZoom = this.canvasConfig.maxZoom;

    scale = this.canvas.getZoom() * scale;
    scale = scale < minZoom ? minZoom : scale > maxZoom ? maxZoom : scale;

    const originalVpt = this.canvas.viewportTransform;  // Position before changing the magnification  // 배율 변경 전 위치
    this.canvas.zoomToPoint(point, scale);
    this.onZoom({ point, scale });

    // Logic added because there was an issue where the screen went out of bounds that I had set when the screen was reduced while reaching the end of the wall.  // 벽 끝에 닿은 상태에서 화면 축소를 하면 내가 설정한 투명벽 테두리를 벗어나는 문제가 있어서 추가한 로직
    if(addCount < 0) {
      const newVpt = this.canvas.viewportTransform;
      const windowWidth = window.screen.width || window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
      const windowHeight = window.screen.height || window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

      // Set how much to increase the scope of the sketch board  //스케치 판의 범위를 얼마나 늘릴지 설정
      const sketchWidth = (windowWidth > 1920) ? windowWidth : 1920;
      const sketchHeight = (windowHeight > 1080) ? windowHeight : 1080;

      // final limit range  // 최종 제한 범위
      const xLimit = (sketchWidth * scale);
      const yLimit = (sketchHeight * scale);

      // [Check whether it has touched the wall]  // [벽에 닿았는지 체크]
      // ex) left: 1920 || right: -1920
      if(originalVpt[4] > xLimit) {
        console.log("left - 왼쪽에 치우침");
        newVpt[4] = xLimit;
      } else if(originalVpt[4] < -xLimit) {
        console.log("right - 오른쪽에 치우침");
        newVpt[4] = -xLimit;
      }

      // ex) top: 1080 || bottom: -1080
      if(originalVpt[5] > yLimit) {
        console.log("top - 위쪽에 치우침");
        newVpt[5] = yLimit;
      } else if(originalVpt[5] < -yLimit) {
        console.log("bottom - 아래쪽에 치우침");
        newVpt[5] = -yLimit;
      }
    }
  }
bedcoding commented 11 months ago

I finished working on this and submitted a pull request. https://github.com/spiridonov-oa/react-whiteboard-pdf/pull/17

spiridonov-oa commented 11 months ago

I finished working on this and submitted a pull request. #17

Thanks. I will take a look soon

spiridonov-oa commented 11 months ago

Is there a way to set the size of the borders? In case I need to use it for a vertical screen or want to set a square size?

spiridonov-oa commented 11 months ago

Also, make sure it works well in all directions - up, down, left, right.

spiridonov-oa commented 11 months ago

Could you also check it with a PDF file with pagination? And when you switch tabs. Thank you

bedcoding commented 11 months ago

I am trying to film each video and attach it. However, on GitHub, videos could not be attached if the size was over 10MB. (message: This video is too big.) I am trying to resolve this issue and will respond sequentially once it is resolved.

https://deploy-preview-17--statuesque-muffin-fb224e.netlify.app/

bedcoding commented 11 months ago

Also, make sure it works well in all directions - up, down, left, right.

Could you also check it with a PDF file with pagination? And when you switch tabs. Thank you

I am attaching a video to answer this question.


In the video below, we switched pages in a multi-page PDF file and tested the scroll limit. (up)

https://github.com/spiridonov-oa/react-whiteboard-pdf/assets/33927558/a4ea9b7f-e1dc-4cc6-b88c-5d3b29ed797b


I kept exceeding the file size limit on GitHub, so I had no choice but to split the video. (up + right, down + right)

https://github.com/spiridonov-oa/react-whiteboard-pdf/assets/33927558/5dee9e71-7eaf-4d93-9efb-0da8842b37b9


In the video below, tabs were created by attaching multiple PDF files, and then scroll limits were tested on two tabs. pdf1 : left + up pdf2: left + down

https://github.com/spiridonov-oa/react-whiteboard-pdf/assets/33927558/5a69e5de-04db-4eb0-9702-ea2c1bc7880b

bedcoding commented 11 months ago

Is there a way to set the size of the borders? In case I need to use it for a vertical screen or want to set a square size?

The range is controlled by the three variables below. sketchWidthLimit: Left and right size of the sketch board (current standard: left and right size of the user's monitor) sketchHeightLimit: Top and bottom size of the sketch board (current standard: top and bottom size of the user's monitor) limitScale: Adjust the weight based on the size specified above

If you apply a criterion other than the monitor size, set limitScale to 1 and set the remaining values arbitrarily. And you need to remove the logic on the 2 lines below that reset the range based on the size of the user monitor. (There is no correct answer, so it is okay to remove it.)

this.sketchWidthLimit = ... // delete this.sketchHeightLimit = ... // delete

  limitScale = 10;
  sketchWidthLimit = 1920 * this.limitScale;
  sketchHeightLimit = 1080 * this.limitScale;

  constructor(params) {
    // [Sketch range limits]
    const windowWidth = this.limitScale * (window.screen.width || window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
    const windowHeight = this.limitScale * (window.screen.height || window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight);
    this.sketchWidthLimit = (windowWidth > this.sketchWidthLimit) ? windowWidth : this.sketchWidthLimit;
    this.sketchHeightLimit = (windowHeight > this.sketchHeightLimit) ? windowHeight : this.sketchHeightLimit;

스크린샷 2023-11-10 오전 10 14 22

To summarize the rest of the logic, it is the logic that 'if it exceeds the range I specified, force it to return to its original position.'

↓ Forced to return to the maximum position when the user scrolls up and goes beyond the range

        try {
          // [Sketch range limits]
          const scale = params ? params.scale : 1;
          vpt[4] = that.axisLimit({ scale, vpt: vpt[4], axis: "x" });
          vpt[5] = that.axisLimit({ scale, vpt: vpt[5], axis: "y" });

          ...

↓ Force it to the maximum range if it goes beyond the range when it is reduced.

    // [Sketch range limits] Modified so that when the screen is reduced while reaching the end of the wall, it does not go beyond the border of the transparent wall that I set.
    if(scale < 1) {
      const newVpt = this.canvas.viewportTransform;
      const x = this.axisLimit({ scale, vpt: this.nowX, axis: "x" });
      const y = this.axisLimit({ scale, vpt: this.nowY, axis: "y" });

      newVpt[4] = x;
      newVpt[5] = y;

↓ Common logic that both use

  // [Sketch range limits]
  axisLimit({ scale, vpt, axis }) {
    let result = vpt;
    const containerElement = this.canvasRef.current;
    if (!containerElement) {
      return vpt;
    }

    // Determined by whether it is the x-axis or y-axis
    const containerSize = (axis === "x") ? containerElement.offsetWidth : containerElement.offsetHeight;  
    const addScroll = (axis === "x") ? this.sketchWidthLimit : this.sketchHeightLimit;

    // Range adjustment when zooming in/out
    const zoomInMinusValue = (containerSize * scale - (containerSize));
    const zoomOutPlusValue = (containerSize * (1 - scale));

    // left || top
    if (result > addScroll * scale) {
      result = addScroll * scale;
    }

    // zoom in && right || zoom in && bottom
    else if (scale >= 1 && result < -(addScroll * scale) - zoomInMinusValue) {
      result = -(addScroll * scale) - zoomInMinusValue;
    }

    // zoom out && right || zoom out && bottom
    else if (scale < 1 && result < -(addScroll * scale) + zoomOutPlusValue) {
      result = -(addScroll * scale) + zoomOutPlusValue;
    }

    return result;
  }

However, if the sketch size is adjusted too small, it may exceed the scope from the beginning. Therefore, I specified a large range so that it would not go over the range even if I reduced the scale to 5%.

bedcoding commented 11 months ago

I'm thinking of revising the code below later.

Before modification:

      const x = this.axisLimit({ scale, vpt: this.nowX, axis: "x" });
      const y = this.axisLimit({ scale, vpt: this.nowY, axis: "y" });

      newVpt[4] = x;
      newVpt[5] = y;

After modification:

      newVpt[4] = this.axisLimit({ scale, vpt: this.nowX, axis: "x" });
      newVpt[5] = this.axisLimit({ scale, vpt: this.nowY, axis: "y" });