Adding event to svg elements in Phaser3 - svg

I have one SVG image file, having some paths. Something like:
<svg>
<g>
<path id="land" class="land" d="M108.114,402.043l0.683,1.604l-1.204.(truncated)">
<path id="ice" class="ice" d="M288.114,402.541l0.683,1.604l-1.204...........">
<path id="water" class="water" d="M038.114,402.543l0.683,1.604l-1.204........">
</g>
</svg>
I need to know which path was clicked. When I load SVG image file in Phaser using load.svg(), the event is triggered for the entire image and not just for the area (or path).
So, how can I detect which path was clicked? Any help is appreciated.

Might be using the wrong terms, but the SVG loader paints the projected SVG to a static bitmap texture. This eliminates the existence of these pathed objects. Even if you split these paths into their own SVG and layer them, the hitboxes for textures is going to be rectangular, based on the size of the texture.
If you separate these paths into their own SVGs, a more computationally expensive hitbox exists, with pixel-perfect enabled for the hitbox setup Docs Phaser3 #makePixelPerfect. This will look at the projected texture and apply a hitboxArea over the pixels that each SVG renders.
A less expensive hitbox for each SVG would be to implement a custom hit test function when the input manager tests for pointer-events. Docs Phaser3 HitAreaCallback. This is going to be more difficult, and its difficulty depends on the shape of the hitbox you are going for, and how accurate you need this hitbox to be. Basic geometries and contains methods for hit tests can be found in Phaser.Geom namespace, if those don't match your use case you would need to write/find a function yourself.

Related

How can I place a geo-referenced SVG over an openlayers map (not as image)

How can I place a complex SVG image (with css-styles!) geo-referenced over an openlayers map so that the document's CSS styles are used with rendering the SVG.
A regular ImageLayer does a fine job of showing the georeferenced svg on the map as an image. But because it is an image, the CSS of the document has no effect on the rendered SVG
The SVG Layer example on the other hand places the SVG into the DOM and makes it react to the document's CSS and reacts when you change the CSS. But it always maps the SVG over the whole planet and seems to hide any layer I place under it.
To give you an idea of the use case: we have an externally generated SVG with several 'groups or layers' in it representing different aspects of infrastructure. This svg has to be put correctly over a map (like we can do with the imagelayer), but we want to be able to selectively show/hide the different 'groups or layers' that are within the SVG.
I guess in the end we would be needing something similar to ol/layer/Image/ImageLayer to happen in the SVG-layer example.
Any suggestions about how to approach this would be very welcome, but working code is also OK ;-)
In the example the image width is 360 degrees and the center is at [0, 0]. For a smaller extent you would need to use the appropriate width and adjust the center used in the transform https://codesandbox.io/s/lucid-poitras-i1qyb?file=/main.js Use an opacity setting to avoid completely hiding the base layer.

How to adjust the resizing of a SVG?

I need some help to figure out how I can adjust the resizing of an SVG graphic when displayed on my web page.
Here are joined 2 screenshots of the graphics, one shows the graphics on a desktop wide screen, and the other on a smartphone
My problem is the graphics are too small on the smartphone. How can I make it bigger? I didn't anything about the responsiveness of this graphics, just the plain SVG in my web page. So I guess something can be made but I don't know what exactly.
Here is the beginning of the SVG graphics:
<svg viewbox="0 0 1920 632" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
<title>graphics</title>
<g style="isolation:isolate">
<g data-name="before animation starts" id="0482fa28-2c72-43bc-8627-b57f09f318d3">
<path id="main-oval" class="main-oval" d="M1354.63,260.62C1338.38,142.2,1144.68,71,922,101.54c-109.4,15-205.35,51.8-272.82,99.38-69.92,49.26-109.23,110-101,170.29,16.31,118.42,210,189.59,432.62,159.07,110.79-15.17,207.86-52.73,275.44-101.15C1324.59,380.18,1362.8,320.12,1354.63,260.62Z" data-name="oval"></path>...
Thanks
Attribute names in SVG are case-sensitive. So viewbox should be viewBox.
It is possible that there are other things wring, but I can't tell without seeing the complete SVG file.
Because your SVG has a viewBox attribute without a width and height attribute it is by default responsive and will scale to fit it's parent container.
In the case of your mobile view, it is the parent container that is restricting the size rather than anything in your SVG. Try inspecting the width, margin and padding of the parent container to ensure it is 100% wide and your SVG will scale to suit.
If the SVG is still not quite legible after that you will need to modify the graphic using CSS media queries to scale and transform specific elements. That is beyond the scope of the question so I won't go into it here.

ImageMagick MVG vs. SVG -- graphic context

I am currently porting some app of me from ImageMagick MVG to SVG output. I made heavily use of the "push graphic-context" command of MVG and now wonder, what's the equivalent to this in SVG?
What "push graphic-context" does is in short (copied from some other source):
When a graphic context is pushed, options set after the context is pushed
(such as coordinate transformations, color settings, etc.) are saved to a
new graphic context. This allows related options to be saved on a graphic
context "stack" in order to support hierarchical nesting of options. When
"pop graphic-context" is used to pop the current graphic context, the
options in effect during the "push graphic-context" operation are restored.
Is the equivalent to use nested SVG documents, like the following example?
<svg>
...
<svg>
...
</svg>
...
</svg>
or should i use something else?
Thanks in advance!
You can use either <svg> or <g> elements for this, I'd recommend <g> elements unless you need a new viewport - in that case go for <svg>.

stroke-width doesn't scale; aspect ratio problem?

I have one or more path elements inside a g element that I am scaling to fit inside a grid rectangle. The transform is applied to the g element. My transform works in that all the points end up at the right places, but I discovered that I have to adjust the stroke-width of the path to get a readable line.
The problem is that if the scale involves a large shift in the aspect ratio, I end up with some segments of the path being heavier weight than others, depending on their orientation.
Here is a typical transform that my code computed:
scale(0.1875, -0.010397820616798718) translate(-1149000, -96174)
In this case I end up changing the stroke-width from 9px to about 48px. Segments close to the horizontal end up thin, those close to the vertical are thick.
Is there any easy way to end with all the segments with the same rendered width?
Have you looked at setting the vector-effect attribute to non-scaling-stroke?
<line vector-effect="non-scaling-stroke" stroke="black" stroke-width="5"
x1="32" y1="50" x2="32" y2="350"/>
http://www.w3.org/TR/SVGTiny12/painting.html#NonScalingStroke
UPDATE
The best solution I can think of is to manually transform the coordinates of your path.
vector-effect="non-scaling-vector" is not consistently supported. My versions of Firefox and Safari do not support it, but my Chrome browser does.
In the SVG standard there is no way of specifying a transformation for the stroke independantly. (A stroke-transform attribute would be nice - like the windows GDI+ drawing system, where a Pen object has it's own local transformation).
Until this changes, the best solution I can think of is to manually work out the coordinates of your path - that is the svg has no transform elements; the coordinates are already transformed.

Rollover overlays with SVG

i want to acheive the effect on this page using SVG. As you can see it uses a series of PNG transparent overlays when the user mouses over a polygonal hotspot drawn on a product.
What i want to achieve is the same thing with SVG, but without messing about with creating a load of PNGs, so that when the user mouses over an area the transparent shape (with link on it) appears over the top. The SVG shape would be built from a set of coordinates exactly as a polygonal hotspot would on an image map.
So i guess my first question is, can this be done with plain old SVG or do i need to use something like Raphael to achieve this? Never seen this effect before with SVG so if anyone has an example like that would be very useful.
Thanks in advance.
There are several ways to get this effect with plain old SVG. Probably the simplest is to use CSS within the SVG. For example:
<style>
.overlay:hover
{
opacity: 0.5;
}
</style>
<svg>
<a xlink:href="http://www.wherever/you/want/to/link/to.com">
<path class="overlay" d="Coordinates of your shape..." />
</a>
</svg>
I've written about various other methods at:
http://www.petercollingridge.co.uk/data-visualisation/mouseover-effects-svgs
Yes it can be done with SVG only, with or without javascript.
One way to get the effect would be to overlay a white semi-transparent path on top of the image that you want to whiten. Another way would be to use an SVG filter to process the image directly, similar to what I've done here or here to recolor a PNG (view page source and feel free to reuse that in any way you like).
You'll want to make use of the 'pointer-events' property most likely. Here's an example showing how to detect mouse-events on the fill and/or stroke of an svg shape, even if the shape is invisible.

Resources