James
James

Reputation: 2018

How to get/inject onclick handle in Javascript for Blazor

The main goal of this requirement is to get the Pixel Coordinates of a Click event on a scaled Image.

I have the following img tag on a Blazor component:

<img id="cameraFrame" src="@($"data:image/png;base64,{@ViewModel.DisplayFrameImageBytes}")"
     @onclick="CameraFrameClick"/>

My CameraFrameClick requires the Pixel level coordinates, if you just use args.OffsetX/Y in the C# then you get the pixel clicked on the image, but if the image is scaled this does not relate to the image pixel, but the display pixel on screen.

I want to capture the @onclick="CameraFrameClick" to some JS variable, so I can call this myself on a custom JS click event on the image.

For instance:

<script>
  #cameraFrame.onclick = function(args) {
     var bounds=this.getBoundingClientRect(); <<-- This is really what I need to use before going back to server.
     // Calculate PixelX and PixelY using args and bounds.
     var pixelX, pixelY;
     **cameraFrame.InvokeBlazorOnClick(pixelX, pixelY);**
  }

Is there a suggested way to accomplish this? It seems like there are many occasions where you may need to do some JS operation first before calling the handler of the function.

Note, this is Server Side blazor.

Upvotes: 1

Views: 1122

Answers (1)

James
James

Reputation: 2018

I've not found a proper solution for invoking JS code before returning to a C# Blazor invocation, but I have found a way to achieve Pixel Click coordinates in Blazor if this is useful for anyone.

https://mudblazor.com/ has extension methods for ElementReference that allows you to get the bounding client rect I was trying to get in JS.

So you can create your img tag with a Ref:

<img id="cameraFrame" @ref=CameraFrameElement src="@($"data:image/png;base64,{@ViewModel.DisplayFrameImageBytes}")"
     @onclick="CameraFrameClick"/>

Then on your event handler use the extension method to get the bounding rects. Note that you still need to be able to access the original image to get the width/height, assuming you still have this data in scope this will work.

ElementReference CameraFrameElement; <--- Binds to the img element using @ref
public async Task CameraFrameClick(MouseEventArgs args)
{
    var bounds = await CameraFrameElement.MudGetBoundingClientRectAsync(); <-- Extension method from MudBlazor
    <--- Calculate Pixel level coordinates, assuming you still have the image and its size.
    var pixelX = (args.OffsetX / bounds.Width) * ViewModel.LatestFrame.FrameCoordinates.FrameSize.Width;
    var pixelY = (args.OffsetY / bounds.Height) * ViewModel.LatestFrame.FrameCoordinates.FrameSize.Height;

    <---- Use the pixel level coordinates.
    await ViewModel.GoToImagePositionCmd
        .Execute(new PointF((float)pixelX, (float)pixelY))
        .ToTask();
}

Upvotes: 1

Related Questions