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

fix: don't clear canvas on mobile browsers' height change #66

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

michchan
Copy link

@michchan michchan commented Nov 20, 2021

The resize events kept being triggered when user scrolled/touched on the mobile browser like Safari on iOS 15,
as the window height changed a little bit if a user scrolled/touched, particularly on iOS Safari the navigation bar will keep expand/collapse as user scrolls.

Fixes #65

Related links for resize problem:
https://titanwolf.org/Network/Articles/Article?AID=488d4b0c-53df-4102-99af-6983a915ea8d
https://stackoverflow.com/questions/8898412/iphone-ipad-triggering-unexpected-resize-events

@agilgur5 agilgur5 changed the title (fix): Fix canvas being constantly cleared on mobile browser like Saf… fix: don't clear canvas on mobile browsers' height change Feb 6, 2022
Copy link
Owner

@agilgur5 agilgur5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this issue and submitting this PR!

I haven't looked at this in detail yet, but signature_pad recommends listening to orientation change instead on mobile, which might be more optimal and resilient than ignoring height changes.

There is also szimek/signature_pad#446 that implements a different workaround to the resize handling here and may make the resize handling and all its various workarounds unnecessary.

Comment on lines +91 to +96
this._handleResize(() => {
if (!this.props.clearOnResize) {
return
}
this._resizeCanvas()
})
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods can get called very frequently during each frame of a resize (esp. as they're not throttled), so instead of creating anonymous closures each time, it's better to have another helper method for this. That optimization is also why the rest of the code is written as such

@@ -3,6 +3,9 @@ import React, { Component } from 'react'
import SignaturePad from 'signature_pad'
import trimCanvas from 'trim-canvas'

const userAgent = window.navigator.userAgent
const isTouchDevice = userAgent.indexOf("iPhone") >= 0 || userAgent.indexOf("iPad") >= 0 || userAgent.indexOf("Android") >= 0
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is fully inclusive of all mobile browsers. This SO answer lists quite a bit more.

isMobile is also probably better naming as laptops can have touchscreens too.

But while I like the DX of auto-detection, I'm not sure this is foolproof enough to work consistently. A prop isMobile might make more sense... but the developer might use the same method to set that prop 😅

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detect-it can also be used to check device support for touch screen and if the touch screen is the primary input method (which should filter out laptop touchscreens I think? though I'm not sure the compatibility of both checks).

There are still some edge cases not covered there, for instance, multi-tasking mode on mobile where you split the screen... 😕

Adding a clearOnOrientationChange prop may make things more clear for developers and be fully backward-compatible as well. Then they can decide whether to use that for their users, e.g. clearOnResize={false} clearOnOrientationChange, and each developer should know their users best.

That's probably the easiest solution, though I do prefer the DX of auto-detection

@agilgur5
Copy link
Owner

agilgur5 commented Feb 6, 2022

Ok so I was thinking changing the on and off methods to work differently for mobile, i.e. detect the orientationchange event instead of resize, but apparently that's been deprecated, as was Screen.onorietationchange. And the replacement API, ScreenOrientation, isn't supported by Safari yet... oof.

According to caniuse though, orientationchange is still supported on all mobile browsers and has not yet been removed since its deprecation... so maybe it could work 🤔
orientationchange also isn't implemented on desktop browsers, so that could potentially work as feature detection as well (more accurately than user-agent querying as in).

@agilgur5
Copy link
Owner

agilgur5 commented Feb 9, 2022

This would also need some tests before it could be merged

@agilgur5 agilgur5 added the problem: stale Issue author has not responded label Mar 6, 2022
@nettum
Copy link

nettum commented May 28, 2024

Ok so I was thinking changing the on and off methods to work differently for mobile, i.e. detect the orientationchange event instead of resize, but apparently that's been deprecated, as was Screen.onorietationchange. And the replacement API, ScreenOrientation, isn't supported by Safari yet... oof.

According to caniuse though, orientationchange is still supported on all mobile browsers and has not yet been removed since its deprecation... so maybe it could work 🤔 orientationchange also isn't implemented on desktop browsers, so that could potentially work as feature detection as well (more accurately than user-agent querying as in).

ScreenOrientation seems to be supported by all browsers (except IE) as of March 2023. 🎉
image

@agilgur5
Copy link
Owner

as of March 2023

That's pretty recent though, so we'd still need a fallback for unsupported browsers 😕

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
problem: stale Issue author has not responded
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Canvas clears itself on iOS 15 due to Safari URL bar window resizes
3 participants