Skip to content

Blazor's MouseEventArgs coordinates for SVGs are wrong! #15440

Closed
@Joebeazelman

Description

@Joebeazelman

The coordinates obtained from MouseEventArgs, namely clientX and clientY, during a mousedown event is wrong. It seems there's a constant offset applied to the coordinates. I suspect there's some kind of miscalculation occurring in Blazor. I haven't tested this on other elements types other than SVG.

At first, I thought it might have something to do with relative coordinates of the SVG child elements, but after adjusting for it, the coordinates are the same. When I implemented it in JavaScript, JavaScript returned the correct coordinates. Whatever MouseEventArgs is doing to the coordinates, it is wrong:

@page "/counter"
@using System.Diagnostics
@using System.Drawing


<h1>Blazor version</h1>


<div>
    <svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" @onmousedown="OnMouseDown">
         <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red"/>

         @foreach (var center in centers)
         {
             <circle cx="@center.X" cy="@center.Y" r="10" stroke="black" stroke-width="0" fill="red"/>
         }
         Sorry, your browser does not support inline SVG.
    </svg>
</div>

@code{

  List<PointF> centers = new List<PointF>();

  public void OnMouseDown(MouseEventArgs e)
  {
      Debug.WriteLine(e.ClientX + " " + e.ClientY);
      centers.Add(new PointF((float) e.ClientX, (float) e.ClientY));
      StateHasChanged();
  }

}

Almost identical code implemented in pure JS without Blazor running (SvgPoint, translation of points makes no difference):

@page "/fetchdata"

<h1>Counter</h1>


<div>
    <svg xmlns="http://www.w3.org/2000/svg" id="template" height="100%" width="100%">
        <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red"/>
        
        Sorry, your browser does not support inline SVG.
    </svg>
</div>

<script>
var svg = document.getElementById("template"),
     NS = svg.getAttribute("xmlns"),
     local = svg.getElementById("local"),
     coords = document.getElementById("coords");
 
 // add a circle to the SVG
 svg.addEventListener(
     "mousedown", DOMToSvgCoordinate,
     false
 );
 
 // translate page to SVG co-ordinates
 function svgPoint(element, x, y) {
     var pt = svg.createSVGPoint();
     pt.x = x;
     pt.y = y;
     return pt.matrixTransform(element.getScreenCTM().inverse());
 }
 
 function DOMToSvgCoordinate(e) {
     var 
         x = e.clientX, 
         y = e.clientY,
         svgP = svgPoint(svg, x, y);
  
    var circle = document.createElementNS(NS, "circle");
    circle.setAttributeNS(null, "cx", Math.round(svgP.x));
    circle.setAttributeNS(null, "cy", Math.round(svgP.y));
    circle.setAttributeNS(null, "r", 10);
    circle.setAttributeNS(null, "stroke", "green");
    circle.setAttributeNS(null, "stroke-width", 3);
    circle.setAttributeNS(null, "fill", "yellow" );
    svg.appendChild(circle);
        
    console.log(svgP);
 }
</script>

Metadata

Metadata

Assignees

No one assigned

    Labels

    ✔️ Resolution: DuplicateResolved as a duplicate of another issueStatus: Resolvedarea-blazorIncludes: Blazor, Razor ComponentsenhancementThis issue represents an ask for new feature or an enhancement to an existing onefeature-svg

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions