Svg polygon rounding - javascript

I am working on an application that is using svg move/rotate/zoom functionalities. I'm programming the back-end in Laravel and the front-end is using html/css/javascript. I've seen on the web that is possible for a polyline to have some sort of cubic-bezier to it.
Now my question is: is it possible for a polygon svg element to have the same cubic-bezier to it as the polyline like in this example?
The structure of the svg looks like is:
<svg>
<g data-type="track">
<polygon class="track" points="2588,851 2537,1157 1796,916 1117,723 0,382 40,80 816,314 1885,638 1887,634"></polygon>
<polygon class="track" points="114,19 73,0 17,497 46,485"></polygon>
</g>
</svg>
Is it possible to give the polygon element a cubic bezier so that it can create a fluid polygon instead of the square no-rounded polygon?

I think some of the responses here have been a little confusing.
(is it) possible for a polygon svg element to have the same cubic-bezier to it as the polyline
The short answer is no. <polygon> (and <polyline>) elements are always rendered as a sequence of straight line segments between the coordinates you provide. There is no way to automatically make the joins have a radius - like an HTML border-radius. If that is what you are asking.
If the line has a bigger stroke width, you can choose to round the outside corner of the line joins.
.track {
fill: none;
stroke: black;
stroke-width: 20;
}
.round {
stroke-linejoin: round;
}
<svg width="300" height="300">
<polygon class="track" points="20,20 290,20 290,130 20,130"></polygon>
<polygon class="track round" points="20,170 290,170 290,280 20,280"></polygon>
</svg>
If you want to include bezier curve segments in your "line", you will have to use the <path> element instead. As was used in the example you linked to.

I suggest to put one duplicated figure above another one with just smaller stroke-width. Profit! :)
<svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<polygon points="50,30 55,50 70,50 60,60 65,75 50,65 35,75 40,60 30,50 45,50" stroke-linejoin="round" stroke-width="50" stroke="red"/>
<polygon points="50,30 55,50 70,50 60,60 65,75 50,65 35,75 40,60 30,50 45,50" stroke-linejoin="round" stroke-width="30" stroke="#fff"/>
</svg>

A polygon does not use cubic Bézier curves, a path does. The example linked does not use any polygons, but a path which includes such curves.
The difference between a polyline and a polygon is simply that the latter is closed, so you can simply create a path and close it (implicitly or explicitly).
Beyond that, I'm not sure what your actual issue is.

Related

how to create d3 radial with dynamic radios

I created a radial with two tiers of options. I did in a way that isn't really dynamic and isn't really responsive to screen size. I now need it to be both of those things. Here is what it looks like when on the screen size I designed it for.
I created a working demo on sandbox that has the dimensions set how I need to use it on. This is what it looks like.
Here is link WORKING DEMO
any help is appreciated. Also keep in mind the outer tiers can have less or more options. it would be great if the blue toggle button would always align at the bottom of the radial like under the En of Energy Loss
I would consider using an SVG ViewBox in order to maintain consistency. What this basically does is create a consistent scalable SVG, mapping the size and coordinates of its container into a consistent range inside the SVG.
For example:
<div height="400px" width="400px">
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="100%" height="100%" stroke="red" fill-opacity="0"/>
<circle r="4" cx="10" cy="10"/>
</svg>
</div>
So it basicalley creates a mapping from the 400x400 dimensions of the div, into the 100x100 of the svg, so the circle positioned at (10, 10) inside the svg will actually be in coordinates (40, 40) of the div

How to create a svg line with a filter

I would like to create lines with the following effect :
The above was created with the following :
<svg id="svg_wrp" width="500" height="500">
<defs>
<filter id="crayon">
<feTurbulence
type="fractalNoise"
baseFrequency="1.001"
numOctaves="10"
result="noise">
</feTurbulence>
<feDisplacementMap
xChannelSelector="R"
yChannelSelector="G"
scale="50"
in="SourceGraphic"
result="newSource">
</feDisplacementMap>
<feGaussianBlur stdDeviation="1.1"/>
</filter>
</defs>
<polyline
points="200,100 100,200"
stroke="#000"
stroke-width="10"
fill="none"
filter=url(#crayon) ></polyline>
</svg>
Above in Fiddle
This method does not work for much of what I want to do.
The effect changes depending on the length and direction of the line.
The only way I can think of doing this is by replacing all the lines with polygons. Then it would be a straight forward use of filters. But then I would have to create a complex polygon with all the calculations for each corner and curve.
So before I do that I would like to know if there is a way to achieve the above with svg polylines or some other method.
Edit: Michael Mullany's answer solved the vertical and horizontal only line issue, but I still have problems with the effect differing on some lines, see below for an example. Notice effect is reduced in top left. Is there a way to have a consistent effect on all lines?
Default filter dimensions don't work on horizontal and vertical lines because they have a zero area bounding box. You need to change your filter units to:
<filter id="crayon" filterUnits="userSpaceOnUse" x="0" y="0" width="500" height="500">
Otherwise this filter is fine.
Update: there are some values for baseFrequency that cause anomalies/moire-like artifacts - apparently 1.001 is one of them for this case. If you tweak that baseFrequency down to 0.98, the problem disappears.

Changing the colour of regions on an SVG circle tiled world map when hovered

I am attempting to make a world map made from an svg comprising many circles. I based this from a codepen I found here: https://codepen.io/mvaneijgen/pen/NRzENO
E.g.
<svg viewBox="0 0 845.2 458">
<circle class="st0" cx="826.1" cy="110.3" r="1.9"/>
<circle class="st0" cx="819.3" cy="110.3" r="1.9"/>
<circle class="st0" cx="819.3" cy="117.1" r="1.9"/>
<circle class="st0" cx="812.6" cy="90" r="1.9"/>
The map is great. I have been dividing it up into coloured continent regions using classes. These change colour when hovered over. All good so far. Most of my functionality is there.
The issue is that you have to be hovering directly on a circle to make the colour change happen. I am using a javascript mouseover event to change the colour.
Is there any way of increasing the area of effect around the circle elements? Maybe putting an invisible square either behind or in front? I am still getting to grips with front-end stuff and any pointers here would be great.
That’s the right idea: transparent rects behind each circle. (Or transparent continent-shaped paths based on geo data, depending on what you’re going for.)
The trick is to use the SVG CSS property pointer-events. Setting it to fill or all should do the trick.

SVG animate path to rotate around its center

I want to animate an image for The Center for Humane Technology for use on a html landing page. The image looks like this and contains 28 gears positioned in a heart shape. I would like to have each gear to rotate continuously around its center, either clockwise or counter-clockwise.
I have read the other SO posts that deal with similar issues, but the solutions do not work for me. When I add e.g. an animateTransform to the shape of a gear, specifying its center coordinates, then it rotates in a wide circle around its center, not staying into position. I am confused.
I have the orginal artwork (created by nivedita) from EPS to SVG, which resulted in rather large paths. This is the resulting SVG image.
First I was planning to use AnimateJS for the animation, but inline SVG animation markup may also do the trick (maybe better).
Reading other SO submissions, I tried rotating gear1 by calculating its center from these coordinates:
X: 42.623
Y: 309.810
Width: 60.796
Height: 60.774
Resulting in following transform:
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" id="gears-of-the-heart" width="333.92" height="526.28">
<g id="canvas" transform="matrix(1.25 0 0 -1.25 0 526.27)">
<g id="heart">
<path d="M58.42 265.7a6.41 6.41 ..." id="gear1" fill="#1e2227">
<animateTransform attributeType="xml" attributeName="transform" type="rotate"
from="0 73.111 340.197" to="360 73.111 340.197" additive="sum" dur="3s" repeatDur="indefinite"/>
</path>
<!-- The other 27 gears here -->
</g>
<!-- More SVG elements (unrelated) -->
</g>
</svg>
Its not working. Is this because of the transform on the parent canvas group?
Two questions:
What am I doing wrong?
Is there an easier way to animate this, so I don't have to calculate center for all gears (I know I could use javascript for coordinates calc)?

Get pixel coordinates of a path

A typical path element under svg will be like
<svg width="960" height="960">
<g transform="translate(480,480)">
<path style="fill:none; stroke:#000"
d="M69.963,-353.136
L66.190,-341.705
C62.417,-330.274,54.870,-307.412,46.957,-284.620
C39.043,-261.828,30.762,-239.107,28.338,-191.600
C25.915,-144.093,29.348,-71.801,1.420,-46.863
C-26.507,-21.924,-85.794,-44.340,-128.969,-48.510
C-172.144,-52.680,-199.207,-38.604,-234.999,-29.311
C-270.791,-20.018,-315.311,-15.509,-337.572,-13.255
L-359.832,-10.100">
</path></g></svg>
Now I need to get the coordinates of the pixels in the Bézier curve. I understand I can calculate the coordinates by the definition of Bézier curve. But are there any other more convenient ways (like some ready-made routines)?

Categories

Resources