Manipulating path element in HTML - javascript

I am creating a hexmap chart using svg element in d3js. The chart is working fine though I need to reduce the size of the hexagons and is unable to.
As per my knowledge, it is somewhat related to the path element of HTML
This is what my path element looks like:
<path d="M395.1641842489362,-477.03703703081476L431.0882010021053,-456.29629628799995L467.0122177552744,-477.03703703081476L467.0122177552744,
-518.5185185164444L431.0882010021053,-539.2592592592592L395.1641842489362,-518.5185185164444Z" class="border" fill="rgb(240, 75, 35)" stroke="#FFFFFF" stroke-width="3"></path>
Please let me know if you have any idea around it!

I don't see the whole picture but every element can be transformed. For example if you want to scale down your path, just add the property transform="scale(0.75)" to your tag. The number is a multiplier, so 0.75 means 25% smaller. 0.5 would mean half the size.

Related

How to use SVG with React and generate icons

Is there any place where I can upload an icon and get an SVG string vector?
Also, what are those tags in the code below?<g> <path> and viewBox, data-original, xmlns, d tags are?
Lately, Is the performance worth using SVG in place of regular icons?
<svg viewBox="0 0 512 512">
<g xmlns="http://www.w3.org/2000/svg" fill="currentColor">
<path d="M0 0h128v128H0zm0 0M192 0h128v128H192zm0 0M384 0h128v128H384zm0 0M0 192h128v128H0zm0 0"
data-original="#bfc9d1"
/>
</g>
</svg>
Here's a very good guide to using SVG with react. https://www.sanity.io/guides/import-svg-files-in-react
There are many online convertors you can use to create svg's
e.g https://www.pngtosvg.com/
The SVG <g> element is used to group SVG shapes together.
The SVG <path> element indicates that the vector to draw is a path. The could alternatively be a polyline or a shape e.g circle.
The <viewBox> attribute is a list of four values: min-x, min-y, width and height
The xmlns attribute is XML Namespace which is needed to use the correct DTD - Doctype Declaration
The <d> attribute defines the path that will be drawn.
From my experience SVG performs significantly faster when using inline SVG's.
The main blocking element for page loading is the numberous amount of files that load sequentially. Using inline svg loads all the images within the page file.
The major benefit of SVG's are the scalability of vector over raster when zooming or viewing at differant resolutions.

document.elementFromPoint returning different elements for same input

I am using document.elementFromPoint to figure out what svg shape is at a certain point. I was experimenting with elementFromPoint on this image when I noticed that I was getting different outputs for the same input.
Here is exactly what I did for reproducibility.
I cut and pasted the svg tag from the linked svg and inserted it into the body of an html file. The html file was set up using the single ! emmet shortcut in vscode. Nothing else was in the body. The only css was body{margin:0;}.
In chrome I went around calling elementFromPoint. Mostly at .25,50 but sometimes just a little to the right or a little to the left. Sometimes calling with the same arguments over and over again to see if it would change.
There was no scrolling done during this time. There wasn't even an option as there was no scroll bar present.
My question is why does this happen? Is there a pattern to it? Is there a way to prevent it?
Thanks.
While I can't tell you why this happens, or how to prevent it, the "pattern", or let's better say the reason for the inconsistent behavior can be narrowed down.
Let's look at the paths that are returned by your calls to elementFromPoint. There are two of them, and if you leave out the ids and classes, both look identical, even taking into consideration their parent elements:
<g transform="translate(-1.775,-1.575)">
<path d="M 1.9,551.3 V 1.7 H 1102 V 551.3 H 2.3" />
</g>
If you rewrite the path such that the transform is resolved, you get a path in (browser) viewport coordinates - for clarity, I have rewritten the V and H commands as L:
<path d="M 0.125,549.725 L 0.125,0.125 L 1100.125,0.125 L 1100.125,549.725 L 0.525,549.725" />
The SVG contains a stylesheet that describes the filling and stroking of these elements. This is the relevant excerpt:
.seabase {
fill: #C6ECFF;
stroke: none;
}
.mapborder {
fill: none;
stroke: #0978AB;
}
path, circle {
stroke-width: 0.25;
}
So what should be returned from document.elementFromPoint(0.25,50)? The topmost element to be found at the given coordinates, provided the pointer-events property allows the element to be the target of a hit-test.
pointer-events is not explicitely set for the elements, so the default value of visiblePainted applies. This means that an (at least partially) opaque fill or stroke both can be hit.
The bottom element of the two candidates, <path class="seabase"/>, has a visible fill, but no border. Point (0.25,50) is inside that fill.
The topmost element of the two candidates, <path class="mapborder"/>, has no fill but a visible border of width 0.25, extending half to the inside and half to the outside of the path outline. At the left side, there is a vertical subpath M 0.125,549.725 L 0.125,0.125. Not going into the details of corners, the stroke could be drawn equivalently as a filled path with a definition
M 0,549.725 L 0,0.125 L 0.25,0.125 L 0.25,549.725 Z
In other words, the point (0.25,50) is exactly on the outline of the stroke. The spec is quite clear about the consequences:
The zero-width geometric outline of a shape is included in the area to be painted.
The point should hit the mapborder element, as the point is part of its visible, painted stroke. If, as you describe, the browser sometimes returns the seabase element, it is in error.
I could go on and speculate about the reasons for this behavior, but that is moot, I think.
Can you prevent it? Only if you would be able to consistently avoid the exact outline of all paths, or if they have a stroke, the outline of that stroke. That's hardly practical, since you would have to find out if the browser missed something it should have hit, while you don't know what was missed.
Finally, there is a second interface that can be used. It is part of the SVG specification, while elementFromPoint is part of the CSSOM spec. Whether that makes a difference in the browser implementation, I cannot say.
document.querySelector('.seabase').isPointInFill(new DOMPoint(2.025,48.425));
document.querySelector('.mapborder').isPointInStroke(new DOMPoint(2.025,48.425));
Note that you need to provide an element to test against, that you get no information which element is on top, and that the coordinates are expressed in local userspace (before transform is applied).

Moving SVG objects using Javascript and CSS

I am currently working on a animated SVG, this includes elements being rotated, moving, etc.
I am facing the problem that I am unable to move certain elements that use a path to get its position.
My existing Javascript code moves some elements using the x attribute, this is working, but still leaves the elements that work with the paths.
Example SVG object:
<path id="XMLID_1418_" d="m1247.8 933c0 17.3-14 31.4-31.4 31.4-17.3 0-31.4-14-31.4-31.4h62.8z" class="st103"></path>
Margins, position or adding a x attribute doesnt move it, how can I do this?
You could wrap the element in a 'g' element and translate that object to move the whole path.
<g transform="translate(x,y)"></g>

SVG pattern not repeating

I'm playing around with SVGs and was working off of this example. However, in my
jsbin the pattern isn't repeating for my <rect> elements.
And when I change the height and width attributes (no I'm not changing the x , y attributes) the rect svg objects just disappear when I enter in large values.
I'm just dipping my toe into SVGs so my knowledge is quite limited. I figure it is something simple but am not seeing what I'm doing incorrectly when I compare to what I'm doing to the grid2.svg that I'm going off of.
You've written this...
<pattern id="OvalPattern2" patternUnits="objectBoundingBox" width="70" height="70" >
With objectBoundingBox units 1 is the size of the shape using it. So your pattern is 70 times the size of the object using it. I suspect you want .7 as the width/height.

What to do with SVG so it can be resized using Javascript?

Let's say I loaded SVG, displayed it in browser, and so far it is OK.
Now, I would like to resize it. All methods I found googling failed to give me the desired effect.
It is all variations of:
$svg.removeAttr('width')
.removeAttr('height')
//.attr('preserveAspectRatio','xMinYMin meet')
//.css('width',width+'px')
//.css('height',height+'px')
.css('width','100%')
.css('height','100%')
.attr('viewBox','0 0 '+width+' '+height)
;
Nothing. I get the view of desired size, but the image (SVG) is clipped to that view instead of being resized. Setting size via attributes does not change a thing. Like the size of that SVG is carved in stone.
Thanks to frenchie answer (see below) it appears JS tries hard to resize SVG and for basic SVG it just works. So the real question is -- what to do with SVG (real-world SVG, not just a rectangle) so Javascript would be able to resize it?
SVG I am testing: http://jsfiddle.net/D6599/
I created SVG with Inkscape, and this is how I load SVG in JS:
$.get(svg_url, function(data) {
// Get the SVG tag, ignore the rest
svg = $(data).find('svg')
.attr('id', 'SVG')
// Remove any invalid XML tags as per http://validator.w3.org
.removeAttr('xmlns:a')
[0];
on_load();
}, 'xml');
The code comes from How to change color of SVG image using CSS (jQuery SVG image replacement)?. What I have later on is svg element (I wrapped it using jQuery).
This is not the question how to load SVG, or what to do with cross-domain issue. SVG loads fine, it is the same domain as the script (my disk).
Your SVG markup should look like this:
<svg id="SomeID" height="20" width="20">......</svg>
So all you need to do is reset the css properties. Something like this should work:
$('#SomeID').css({'width':40, 'height' :40});
And if you can't change the id of the SVG markup then you can simply wrap it around a div like this:
<div id="SomeID"><svg>....</svg></div>
$('#SomeID').find('svg').css({'width': 40, 'height': 40});
Here's a jsFiddle:
function Start() {
$('#TheButton').click(ResizeSVG);
};
function ResizeSVG() {
$('#TheSVG').css({'width':40, 'height' :40});
}
$(Start);
Finally I found it. I hope it will change in future, but for now there is a crucial difference if you change attribute by editing actual SVG file, and changing SVG on-fly using Javascript.
In order JS could resize SVG you have to manually edit SVG file and change height and width attributes to following lines.
Before:
width="600px"
height="560px"
After:
viewBox="0 0 600 560"
width="100%"
height="100%"
Of course in your case the values will be different. Please note that you can change those attributes programmatically with Javascript but it does not work (at least not for me).
Now, you can load such file as usual and compute, let's say width/height ratio.
var vbox = $svg.attr('viewBox').split(' ');
var w_ratio = vbox[2]/vbox[3]; // width/height
Such fixed file is still readable by Inkscape, I don't know how about other programs.

Categories

Resources