Skip to content

UIMouseEventArgs should include OffsetX and OffsetY #8241

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

Closed
petergolde opened this issue Mar 6, 2019 · 12 comments
Closed

UIMouseEventArgs should include OffsetX and OffsetY #8241

petergolde opened this issue Mar 6, 2019 · 12 comments
Assignees
Labels
area-blazor Includes: Blazor, Razor Components Done This issue has been fixed enhancement This issue represents an ask for new feature or an enhancement to an existing one

Comments

@petergolde
Copy link

I'm using Razor Components (server-side Blazor) to handle mouse events on a canvas element, although the issue could arise with any HTML element. I would like to know where on the canvas element the mouse event occurred (obviously a key piece of data!)

Currently, UIMouseEventArgs includes only ScreenX/Y and ClientX/Y. Neither of these directly give the location of the mouse event within the element. Typically, JavaScript code will call getBoundingClientRect() on the given element, and subtract those values from ClientX/Y to get the mouse location with the element.

Doing that using server-side Blazor presents two problems. First, it requires another round-trip to the client to make that Javascript call. This is a performance problem. Second, because that Javascript call is asynchronous, the bounding client rect might have changed since the event happened. For example, the web page might have scrolled or there might be an animation occurring. In that case, the adjusted mouse coordinates still won't be correct.

In order to remedy this, I think that UIMouseEventArgs should include two new fields: OffsetX and OffsetY, which indicate the position within that element that the mouse event occurred. Most modern browsers already include those properties on mouse events; for those that do not, the client size Blazor code should provide the trivial emulation.

@Eilon Eilon added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Mar 6, 2019
@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Mar 6, 2019
@mkArtakMSFT
Copy link
Contributor

Thanks for contacting us, @petergolde.
@danroth27 assigning to you to collect the actual need from community regarding similar asks.

@mkArtakMSFT mkArtakMSFT added enhancement This issue represents an ask for new feature or an enhancement to an existing one Needs: Spec Indicates that a spec defining user experience is required labels Mar 6, 2019
@danroth27 danroth27 added this to the Backlog milestone Mar 11, 2019
@mkArtakMSFT mkArtakMSFT removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels May 9, 2019
@Bartmax
Copy link

Bartmax commented Jul 12, 2019

👍 I need this to implement material design ripple without js interop.

@VR-Architect
Copy link

I need this too please. Also consider adding a reference to the actual element that was clicked too!

@VR-Architect
Copy link

VR-Architect commented Jul 17, 2019

Here is the code I used to get the offset:

    Vector2 mouseOffset = new Vector2 { top = 0, left = 0 };
    void mouseDown(UIMouseEventArgs args)
    {
        mouseOffset.left = args.ClientX - MyElement.left;
        mouseOffset.top = args.ClientY - MyElement.top;
    }
   void mouseMove(UIMouseEventArgs args)
    {
        if (isMouseDown)
        {
            MyElement.left = args.ClientX - mouseOffset.left;
            MyElement].top = args.ClientY - mouseOffset.top;
        }
    }
    public class Vector2
    {
        public long left { get; set; }
        public long top { get; set; }
    }

Full code here #12259

@Zigby
Copy link

Zigby commented Oct 28, 2019

I need this too.
Are there any plans to support OffsetX and OffsetY as properties of the MouseEventArgs?

@tleylan
Copy link

tleylan commented Oct 28, 2019

While the OffsetX and Y values would be useful it seems to me that the PageX and PageY are values we need. Generally speaking once a page is rendered the Page positions won't change often while the Client positions change if the page scrolls.

@mkArtakMSFT mkArtakMSFT removed the Needs: Spec Indicates that a spec defining user experience is required label Jan 23, 2020
@gmnenad
Copy link

gmnenad commented Mar 27, 2020

This is definitely needed.

We usually need location relative to element where we put 'onmouse' event , to determine at what part of that element user actually clicked.

Currently we either need to call JSinterop on every click ( element.getBoundingClientRect() or similar), or we need to try and track whenever that BoundingClientRect would change, which is hard ... it can change on resizes or scrolls, neither of which can be caught at element event ( onscroll of element will not catch if parent element is scrolled, and yet its own BoundingClientRect will change )

So it boils down to calling element.getBoundingClientRect() on every 'onmouse' event, which is huge latency hit for server Blazor apps.

*** SUGGESTION ***
Include RectangleF BoundingClientRect in MouseEventArgs

That not only remove above need for additional jsInterop call and its latency, but returning rectangle instead of just top corner location allows for deciding where relatively on element we clicked ( for example, bottom right quadrant, or rightmost edge ) independent of resizing/moving of element.

@doug62
Copy link

doug62 commented Apr 10, 2020

+1 - Without knowing where a click occurs within an element - why bother with ClientX/Y - ScreenX/Y? Locations are worthless at this point. And ElementReference should have a clientrect so we can take it from there.

@gmnenad
Copy link

gmnenad commented Apr 11, 2020

That is good, but it would be much better if BoundingClientRect is included , instead of OffsetX/Y. Two reasons:

  1. just OffsetX/Y do not allow to determine position of click on resizable item - and BoundingClientRect does
  2. if OffsetX/Y are obtained on JS side by calling getBoundingClientRect, returning BoundingClientRect instead is no additional performance hit

@doug62
Copy link

doug62 commented Apr 11, 2020

I "have to" work around it by:

public class BoundingClientRect
{
    public double X { get; set; }
    public double Y { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
    public double Top { get; set; }
    public double Right { get; set; }
    public double Bottom { get; set; }
    public double Left { get; set; }
}

private async Task onImageClick(MouseEventArgs e)
{
    var result = await JSRuntime.InvokeAsync<BoundingClientRect>("MyDOMGetBoundingClientRect", MyElementReference);

    var x = (int) (e.ClientX - result.Left);
    var y = (int) (e.ClientY - result.Top);

// your code here
}

and

<script> MyDOMGetBoundingClientRect = (element, parm) => { return element.getBoundingClientRect(); }; </script>

@gmnenad
Copy link

gmnenad commented Apr 11, 2020

Yes, I use similar, it is actually possible to just use RectangleF as return type, without declaring your BoundingClientRect, although both approaches are dependent on browser having Left/Top fields (for example, Safari does not have X/Y fields)

But, that is different bug issue, and this #8241 was about avoiding that additional InvokeAsync call after OnClick - since that doubles (already big) latency between user clicking and you doing something afterwards.

And my suggestion/question to @captainsafia was about possibility to include entire BoundingRectangle in MouseEventArgs, instead of just including OffsetX/Y - since just OffsetX/Y can not help us to determine relative position of click on element , if element is resizable. For example, if we have resizable/responsive image and we want to see if user clicked shape at center of that image.

@captainsafia
Copy link
Member

I'll go ahead and mark this as done since #20478 was merged.

And my suggestion/question to @captainsafia was about possibility to include entire BoundingRectangle in MouseEventArgs, instead of just including OffsetX/Y - since just OffsetX/Y can not help us to determine relative position of click on element , if element is resizable. For example, if we have resizable/responsive image and we want to see if user clicked shape at center of that image.

Can you open an another issue for this?

@captainsafia captainsafia added Done This issue has been fixed and removed Working labels Apr 14, 2020
@ghost ghost locked as resolved and limited conversation to collaborators May 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components Done This issue has been fixed enhancement This issue represents an ask for new feature or an enhancement to an existing one
Projects
None yet
Development

No branches or pull requests