Finding point of svg polygon - javascript

I have an SVG object, a polygon with 3 points. I want to use javascript to rotate the polygon and add text near the point. How can I find the coordinates of the point?
<svg width="165" height="165" style="border: 1px solid black; ">
<path d="M5 0 Q 80 70 160 0" stroke="black" fill="transparent"/>
<path d="M5 165 Q 80 90 160 165" stroke="black" fill="transparent"/>
<polygon points="77.5,20 87.5,20 82.5,75"
style="fill:transparent;stroke:black;stroke-width:1" transform="rotate(90 82.5 20) " />
</svg>
I want to rotate the polygon to somewhere between 0 and -180 degrees from the original 90 position and add a label at the tip so the user knows how far it's been rotated.

To rotate the polygon you can use CSS transform property e.g.
.svg-el {
transform: rotate(90deg);
}
To animate any path or points in the polygon you manipulate it with JS, you can use a library like animejs http://animejs.com/documentation/#motionPath

Related

I want to make it appear as if text is always the same distance away from circle

My problem is that when i am rotating this svg i counter rotate the text to keep it horizontal. however this makes it look like it is further from the circle when the degree is for example 0 or 180 when its high above or below. but when its 90 its right next to it. i believe this is actually correct since the center of the text is the same distance away. is there a way to fix this?
<svg
height="200"
viewBox="0 0 100 100"
fill="none"
transform="rotate(45, -16, -16)"
>
<circle
cx="30"
cy="30"
r="5"
fill="#FFFFFF"
stroke="#3D3D3D"
stroke-width="1.5"
/>
<g transform="rotate(90, 20, 20)">
<path
d="M15.6528 7.06945L15.4939 7.36025L15.602 7.67352L17.8504 14.1941L2.3372 6.25279L18.9596 1.01652L15.6528 7.06945Z"
fill="white"
stroke="#3D3D3D"
stroke-width="1.5"
/>
</g>
<text
x="30"
y="70"
text-anchor="middle"
font-size="14px"
fill="#3D3D3D"
pointer-events="none"
font-weight={500}
transform="rotate(-45, 30, 70)"
>
some text here
</text>
</svg>
Remember to set your transform-origin, because they help solv this: if you want the text at a fixed distance, put it in a <g> with the circle's center as transform-origin, and a rotation transform, and then give the text element a rotation by the same angle in the opposite direction so that it stays upright.

SVG make a clip-path to scale and relocate as its container scales

I have this svg:
<svg viewBox="0 0 280 280" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<clipPath id="clipPath">
<path d="M 10 10 q 49 41 100 0 c -14 46 -14 40 50 50 c -24 -1 -50 -6 -40 40 c -14 -44 -53 -73 -99 -51 Z"/>
</clipPath>
</defs>
<rect x="5" y="5" width="190" height="90" fill="#770000" clip-path="url(#clipPath)"/>
</svg>
I can't use CSS styles here, just SVG. And I need to scale and relocate the clipPath as the rect scales or moves.
I tried adding this to the clipPath definition <clipPath id="clipPath" width="190" height="90" x="5" y="5"> with no result. Tried adding these parameters to the path too. No result both times. Also tried reducing the dimensions of the rect the clipPath will truncate instead of readjusting, same thing if I change the X,Y position. Any hint on how to solve this?

How to set a dynamic height value to a wave in svg based on % value?

I want to design dynamic wave effect with help of svg. Suppose I have passed value 40%, wave should appear 40%. Based on the value, wave effect should increase or decrease.
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 1440 320">
<path fill="#FFF6E3" fill-opacity="1" d="M0,192L48,197.3C96,203,192,213,288,229.3C384,245,480,267,576,250.7C672,235,768,181,864,181.3C960,181,1056,235,1152,234.7C1248,235,1344,181,1392,154.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z">
</path>
</svg>
Depending on exactly what is meant by 40% etc increase, using transform scale on the y but leaving the x will result in the waves being higher.
For example, to get them 5 times higher (than the heights of the SVG given in the question) use transform: scale(1, 5)
svg {
transform: scale(1, 5);
}
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 1440 320">
<path fill="#FFF6E3" fill-opacity="1" d="M0,192L48,197.3C96,203,192,213,288,229.3C384,245,480,267,576,250.7C672,235,768,181,864,181.3C960,181,1056,235,1152,234.7C1248,235,1344,181,1392,154.7L1440,128L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z" ></path></svg>

Why do SVG lines/ paths on top of each other create a different stroke?

I am drawing some paths with the same stroke with some significant overlap (dynamically creating and updating a tree). On the overlapping regions, the stroke looks different (darker as well as thicker -see a) as on the non overlapping regions (- see b). The same effect is noticeable with different stroke colors, too.
Here is the code:
path.p2 {
fill: none;
stroke: black;
stroke-width: 1px;
}
<svg height="500" width="400">
<path class="p2" d="M210 10 V 100 H 300 "/>
<path class="p2" d="M210 10 V 120 H 300 "/>
<path class="p2" d="M210 10 V 140 H 300 "/>
<path class="p2" d="M210 10 V 160 H 300 "/>
</svg>
Is there a simple CSS, SVG or javascript fix how to draw these paths (without recalculation of the overlapping regions and creating a new path)?
As I've commented you may add shape-rendering: crispEdges to path.p2
MDN Quote:
crispEdges Indicates that the user agent shall attempt to emphasize the contrast between clean edges of artwork over rendering speed and geometric precision. To achieve crisp edges, the user agent might turn off anti-aliasing for all lines and curves or possibly just for straight lines which are close to vertical or horizontal. Also, the user agent might adjust line positions and line widths to align edges with device pixels.
svg {
outline:1px solid;
}
path.p2 {
fill: none;
stroke: black;
stroke-width: 1px;
shape-rendering: crispEdges;
}
<svg height="500" width="400">
<path class="p2" d="M210 10 V 100 H 300 "/>
<path class="p2" d="M210 10 V 120 H 300 "/>
<path class="p2" d="M210 10 V 140 H 300 "/>
<path class="p2" d="M210 10 V 160 H 300 "/>
</svg>

Analytics Project SVG Path

I am not able to figure out how to make path of a circle to go in the middle. I have an example on jsfiddle.
Basically, how do we make this black path go in the middle? This is the path (2nd in svg tag):
[![enter image description here][1]][1]
https://jsfiddle.net/6e1z6xkq/
<div align="center">
<div class="circleDraw">
<svg width="116" height="100">
<g transform="translate(58,58)">
<path d="M-44.430577700900734,37.281681361819274A58,58 0 1,1 44.43057770090073,37.28168136181928L35.23804438347299,29.568230045580812A46,46 0 1,0 -35.238044383472996,29.568230045580805Z" style="fill: rgb(100, 150, 100);">
</path>
<path d="M-90.430577700900734,97.281681361819274A58,58 0 0,1 -96.07604799105425,3.22779870395063L-96.54307254462923,7.939288627271193A46,46 0 0,0 -35.238044383472996,29.568230045580805Z" style="fill: rgb(255, 1, 1);" width="15px" height="20px">
</path>
</svg>
</div>
</div>
You want something like the below (although I would observe that your SVG source is verbose. You can get the same result from a single move and arc drawing command with a green stroke & appropriate stroke width. And there should be no need for a transform - this looks like a drawing tool export.)
<div align="center">
<div class="speedometer--points">
<svg width="116px" height="100px">
<g transform="translate(58,58)">
<path d="M-44.430577700900734,37.281681361819274A58,58 0 1,1 44.43057770090073,37.28168136181928 L35.23804438347299,29.568230045580812 A46,46 0 1,0 -35.238044383472996,29.568230045580805Z" fill="green">
</path>
<path d="M -45 35 l 45 -45" stroke="red" stroke-width="5">
</path>
</g>
</svg>
</div>
</div>
Positioning and animating a line within the svg
It was easiest to go into Illustrator to create a stroke path that matched your arc.
From there it is just a matter of animating the svg with the following css. For any point along the path you can set the stroke-dashoffset from 285 to 515 (for this example.
.speed{
stroke-dasharray: 260px;
stroke-dashoffset: 285;
}
To Animate The stroke with CSS
You can apply a transition of the stroke-dataoffset to the complete path (css-tricks has a good article on this), like so:
svg:hover .speed{
stroke-dashoffset: 515;
transition: 1s ease;
}
Positioning a circle in the middle of your svg
I apologize I misread the question initially. You will want to add a <circle></circle> svg tag with cx, cy, and r attributes. cx and cy are the positioning attributes and r is the radius. In this case cx and cy are set to zero and I've arbitrarily set the radius.
You can read more about basic svg shapes at MDN
Moving the red path to the middle
You can add transform: translate(x,y) to the appropriate path. 'x' and 'y' represent the x and y coordinates of the path. You can also add other attributes like rotate() and skew(). MDN has good explanations of this as well.
Also I noticed in your fiddle that you hadn't closed the <g> tag.
.speed {
stroke-dasharray: 260px;
stroke-dashoffset: 285;
transition: 1s ease;
}
svg:hover .speed {
stroke-dashoffset: 515;
transition: 1s ease;
}
<div align="center">
Hover over the first svg!
<div class="circleClass">
<svg width="116" height="100">
<g transform="translate(58,58)">
<path d="M-44.430577700900734, 37.281681361819274A58, 58 0 1,1 44.43057770090073,37.28168136181928L35.23804438347299,29.568230045580812A46,46 0 1,0 -35.238044383472996,29.568230045580805Z" style="fill: rgb(100, 150, 100);"/>
<path class="speed" d="M40.1,33.5l3.4-4.9c12.6-19,11.4-44.3-3.6-62.1C29.9-45.3,15.4-52,0-52c-12.2,0-24.1,4.3-33.4,12.2
c-20.4,17.1-24.4,46.8-10,68.5c0,0,2.3,4,3.3,5.1" stroke="red" fill="transparent" stroke-width="12"/>
</g>
</svg>
</div>
</div>
<div align="center">
<div class="circleClass">
<svg width="116" height="100">
<g transform="translate(58,58)">
<path d="M-44.430577700900734,37.281681361819274A58,58 0 1,1 44.43057770090073,37.28168136181928L35.23804438347299,29.568230045580812A46,46 0 1,0 -35.238044383472996,29.568230045580805Z" style="fill: rgb(100, 150, 100);">
</path>
<polygon points="2,2.50 0,-2.5 -40,30" style="fill:red;" />
</g>
</svg>
</div>
</div>
<div align="center">
<svg width="116" height="100">
<g transform="translate(58,58)">
<path d="M-44.430577700900734,37.281681361819274A58,58 0 1,1 44.43057770090073,37.28168136181928L35.23804438347299,29.568230045580812A46,46 0 1,0 -35.238044383472996,29.568230045580805Z" style="fill: rgb(100, 150, 100);">
</path>
<circle cx="0" cy="0" r="25"/>
</g>
</svg>
</div>
Your task is complicated a little due to the fact that your green arc is not a simple little path arc that goes from left to right (or vice versa). It is actually a closed shape that defines the outside of the green shape. So it goes from left to right around the outer radius, then a little straight bit to the inner radius, and another arc back to the start.
It is possible to fill a green shape like that, in a meter like way, using a mask or a clipping path. However it is much simpler to just convert your green meter shape to a simple path that goes from left to right in one direction, and has a thick width.
If we do that, your SVG becomes, something like:
<div align="center">
<div class="circleDraw">
<svg width="116" height="100">
<g transform="translate(58,58)">
<! the green path converted to a simple one directional stroke -->
<path d="M -39.8,33.4 A 52,52, 0, 1, 1, 39.8, 33.4"
style="fill: none; stroke-width: 12; stroke: rgb(100, 150, 100);">
</path>
</g>
</svg>
</div>
</div>
Now that we've done that, we can use a really easy method to produce your black meter line.
What we do is make an exact duplicate of the green line (except black this time of course). Then we apply a dash array to the line that makes it on for 50% of the length and off for 50% of the length.
The length of our arc is 236 units. So we set the dash array to:
stroke-dasharray: 118 118
<div align="center">
<div class="circleDraw">
<svg width="116" height="100">
<g transform="translate(58,58)" style="fill: none; stroke-width: 12;">
<! the green path -->
<path d="M -39.8,33.4 A 52,52, 0, 1, 1, 39.8, 33.4"
style="stroke: rgb(100, 150, 100);">
</path>
<!-- the black path -->
<path d="M -39.8,33.4 A 52,52, 0, 1, 1, 39.8, 33.4"
style="stroke: black; stroke-dasharray: 118 118;">
</path>
</g>
</svg>
</div>
</div>
If you need to change the meter to read something other than 50%, then you need to adjust the value of the stroke-dasharray. Just make sure the two values add up to (at least) 236.
This other question shows how to update the meter with Javascript if that's what you ultimately want to do.

Categories