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

Cannot restrict to viewport #988

Open
andreasvirkus opened this issue Nov 18, 2022 · 3 comments
Open

Cannot restrict to viewport #988

andreasvirkus opened this issue Nov 18, 2022 · 3 comments

Comments

@andreasvirkus
Copy link

Description

I've got an issue with restricting my element to the viewport with both drag and resize. The issue is apparent on pages where the html and body element are shorter than the actual visible content. One such example is https://subtlepatterns.com/, but there are loads others. As I'm using interact in a browser extension, it needs to handle different page structures and styling.

When the user has scrolled past the end of the body, then

  1. Restriction modifiers won't let me drag or resize the element out of the <body> bounds
  2. The reflow() method will make it jump out of the viewport, to where the body element ended.

Here's a small replication of the issue:
https://jsfiddle.net/andreasvirkus/ovqga8w3/1/

And a recording (ideally it should touch the bottom of the screen when dragging down):

Screen.Recording.2022-11-18.at.16.36.44.mov

Here you can see how <body> is cut off, but the content itself stretches further down

Screenshot 2022-11-18 at 16 42 14
Screenshot 2022-11-18 at 16 42 20

Expected behavior

Ideally, I'd want to always restrict the drag and resize to the currently visible window (viewport). No matter if the user has scrolled on the x or y axis. Similarly with reflow, I'd always want the element to reflow to a visible position, not to be offset somewhere off the screen.

Actual behavior

  • With drag/resize, i'm currently bound by the html or body element size.
  • With reflow, the element is offset and either partially or completely hidden.

System configuration

interact.js version: 1.10.7
Browser name and version:

Brave: 1.43.89 Chromium: 105.0.5195.102 (Official Build) (x86_64)
Chrome: 107.0.5304

Operating System: tested on Mac and Windows

@andreasvirkus
Copy link
Author

andreasvirkus commented Nov 18, 2022

I've also tried restricting with restrictRect and while that let's me use the full range of the viewport, now users could drag the element off screen (if document.body.scrollHeight is larger than window.innerHeight)

function getRestriction() {
  const body = document.body
  const box = body.getBoundingClientRect()
  const bottom = Math.max(box.height, body.scrollHeight)
  const right = Math.max(box.width, body.scrollWidth)

  return {
    top: 0,
    left: 0,
    bottom: bottom - 20,
    right,
  }
}

...
modifiers: [
  interact.modifiers.restrictRect({
    restriction: getRestriction(),
  })
]

@andreasvirkus
Copy link
Author

Here's a recording of the buggy reflow behavior, if we've first scrolled beyond the restriction value:

Screen.Recording.2022-11-18.at.16.50.53.mov

@andreasvirkus
Copy link
Author

This is our current workaround (it's called on first init, in a resize listener and in the drag/resize end() hooks)

export function repositionWidget() {
  if (!widget) return
  const box = widget.getBoundingClientRect()
  if (!box) return
  const height = window.innerHeight
  const width = Math.min(window.innerWidth, document.body.clientWidth)

  if (box.top < 0) widget.style.top = '0'
  if (box.left < 0) widget.style.left = '0'
  if (box.right > width) widget.style.left = Math.max(0, width - box.width) + 'px'
  if (box.bottom > height) widget.style.top = Math.max(0, height - box.height) + 'px'

  const newPos = widget.getBoundingClientRect()
  dragTop = newPos.top
  dragLeft = newPos.left
}

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

1 participant