Closed
Description
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>