SVG getScreenCTM does not account for CSS transforms in Firefox - javascript

I'm trying to calculate an svg's viewBox coordinates of a click event using
const { x, y } = new DOMPoint(event.clientX, event.clientY)
.matrixTransform(svg.getScreenCTM().inverse());
My svg lives inside a container that is CSS-transformed (translate). In Chrome everything is working fine, in Firefox the correct viewBox coords are calculated only if I remove the CSS-transform.
What can be done? Any help would be much appreciated.

The different behaviour you are seeing in Chrome is probably due to it being a little more advanced in its support of SVG 2 specification changes.
In the definition for getScreenCTM in the SVG 2 specification it says that among the transforms to be considered is included:
any transforms from the SVG viewport's coordinate space to the document's viewport, i.e. taking into account the positions of all of the CSS boxes from the outermost svg element's box to the initial containing block when the SVG document fragment is inline in an HTML document
This language is not in the SVG 1.1 specification.
This (the missing SVG2 behaviour) is a known bug in Firefox. You can view the bug report here.
As for a workaround, I don't think there is an easy answer. AFAIK there is no equivalent of getScreenCTM() for HTML elements. You could read the container element's transform property, parse it, then multiply it with the matrix you get from getScreenCTM(). But you probably also need to take account of the page offsets of the container and all its ancestors.

Related

SVG canvas size limitations

Problem
I was planning on using SVG as an infinite canvas on which I can move around using viewBox.
Turns out that when the viewbox reaches a specific sweetspot, the shapes start disappearing.
Example
Watch how the shapes always stay inside of the view box, until the viewbox passes the sweetspot:
Live reproduction
It's as if SVG has a limitation mismatch where the viewbox can keep running freely, but shapes can only render within specific bounds.
Research
Furthermore, the sweetspot is different between browsers:
On Chrome it's 33554399.
On Firefox it's 17895590.
The same happens on the other direction. Apply a minus sign to the above values and the shapes disappear on the other side of the canvas.
My best guess is that the browser implementation of SVG is internally constrained by something parallel to Number.MAX_VALUE (but is significantly lower).
However, I couldn't find any relevant documentation on the subject.
Question
Any way to fix or work around this? I'm hoping to keep my current implementation and not simulate the viewbox on my own.

Is there a difference between scaling elements in SVG and HTML?

This question looks similar but ultimately is different and didn't help. Moreover, the accepted answer was written in 2011 and seems outdated. That question has 400+ votes and the accepted answer has 500+ votes so understanding the differences between SVG and HTML is a common problem.
Canvas and its performance advantage is not under consideration because we only need to deal with <= 100 elements at a time, not thousands.
Assume the goal is to create an alternative to Adobe Spark, which is a simple design editor. (See image below.) The editor will let users add, move, and transform elements like text, image, and icons. Designs are output as PNGs.
SVG has worked so far, but there are issues like this and this with computing element positions and sizes.
In preliminary tests, HTML (e.g., div, span, img) looks promising, but before discarding the SVG code, it seems prudent to identify the key differences between HTML and SVG.
In particular:
It seems SVG’s primary difference is “magically” scaling designs from one size to another (e.g., normal resolution -> retina resolution).
But when we manually scale text and image elements with JavaScript, the preliminary tests show the HTML and SVG designs look equally as sharp.
Is there a difference between scaling designs with SVG automatically (by using the width, height, and viewbox attributes on the root SVG element) and scaling divs, spans, text, images, and HTML elements manually with JavaScript?

SVG - how to set text line-height

It seems line-height is the one CSS property absent from svg text. The best resource on SVG I have found is: Jenkov.com SVG Tutorials and there is no mention of it, neither could I find mention of it on MDN.
So if anyone can shed definitive light on this or share a technique. I am basically interested in the spacing between lines of text that wrap, not independent text elements.
Thanks
SVG 1.1 (officially) only supports single line text, hence no line-height setting.
I've just tried creating a block of text in Inkscape, and it's using a flowRoot element (containing a flowPara element with the actual text in it). Then the flowRoot element actually has line-height assigned to it (in %).
I don't know how wide-spread support for that way is, since it used to be part of SVG 1.2. You might also want to have a look here: Auto line-wrapping in SVG text

Getting the shape/outline of an HTML node in JavaScript

Is it possible to get the shape/outline of a DOM node in JavaScript? I would like to get some kind of representation of the shape or outline so that I can tell exactly which pixels the DOM node occupies. I can calculate the rectangle using width, height, and position, but this doesn't take into account the border-radius property, among others.
I know that I have access to all of the individual properties that will determine the rendered outline of a node (height, width, border-radius, etc), so I could, in JavaScript, reproduce the calculations the browser does. However, this would be pretty tedious and there would be a lot of edge cases.
and don't forget that different browsers may render slightly different.
That is if you are interested in the padding and margin as well.

Determine an element's custom CSS cursor hotspot coordinates from JavaScript

When I attempt to get the full CSS cursor definition of an HTML element in JavaScript, it omits the hotspot (target pixel) coordinates for some reason and is resulting in my cursor resetting its hotspot to the top-left pixel of the cursor image (i.e. not a good thing).
Problem demonstrated in this JSFiddle.
Update: It appears to only be this way in some browsers, specifically (in my tests) Mac Chrome and Safari.
Update 2: Looks like this is actually fixed in the latest nightly build of WebKit (8536.26.17, 537+), so I guess there's no real answer required besides it's a bug, and has already been fixed.
For example:
var elem = document.createElement("div");
elem.style.cursor = "url('path/to/cursor') 9 9, auto";
console.log( elem.style.cursor );
Outputs:
url(path/to/cursor), auto
Is there any way to get those coordinates from the style once they've been set?? I tried window.getComputedStyle() but it has the same result.
This seems like a pretty major oversight to me. Is that information just lost and no longer retrievable?
As far as I can tell from looking at the CSS 2.1 Specification, the X and Y coordinates are not included:
http://www.w3.org/TR/CSS21/ui.html#cursor-props
Also, the Mozilla Developer Network lists the X,Y coordinates as "experimental."
If something isn't in the specification then you can expect browsers to have different, and sometimes conflicting, implementations of the property.

Categories