Creating a Circular SVG Temperature Dragger in Angular? - javascript

This is a static demo of the circular thumb dragger I'm trying to create in Angular. It uses the stroke-dashoffset="-260" setting to position the thumb /dragger close to the end of the circular path behind the thumb, and as can be seen the -260 negative offset works as expected.
<body style="width: 200px; height: 200px;">
<svg
(mousedown)="onMouseDown($event)"
#svgRoot
id="svgclick"
version="1.1"
viewBox="0 0 79.375 79.375"
xmlns="http://www.w3.org/2000/svg"
>
<path
transform="rotate(90)"
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="10.583"
/>
<path
#thumb
transform="rotate(90)"
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke="#F66"
stroke-width="18"
pathlength="270"
stroke-dasharray="0 270"
stroke-dashoffset="-260"
id="thumb"
/>
</svg>
</body>
When I use the same code in this Angular Stackblitz the stroke-dashoffset="-260" does not work the same way.
This is a live dragger demo. If you try to drag the thumb, the drag "Accelerates" and pushes the thumb further and further out. Note that the value corresponding to the offset calculation and the number of degrees that the click or drag represents is logged.
https://stackblitz.com/edit/angular-ptzvsm?file=src%2Fmain.ts
Any ideas on why it's doing this?

The issue with the circular thumb dragger in the provided Angular Stackblitz is caused by an incorrect calculation for the stroke-dashoffset value. To fix this, you can use the stroke-dasharray value to determine the length of the circular path and update the stroke-dashoffset based on the distance the thumb has moved around the circle

Related

Positioning an SVG Circle on top of a circular path using keypoints?

In this question the author of the question is able to position an SVG circle on top of a path like this:
<div style="width:400px">
<svg viewBox="0 -10 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="M20,60a35,35 0 1,1 60,0" stroke="#D3D7DB" stroke-width="4" fill="none" stroke-linecap="round"></path>
<path d="M20,60a35,35 0 1,1 60,0" stroke="#008000" stroke-width="6" pathLength="100" fill="none" stroke-linecap="round" stroke-dasharray="50 85"></path>
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</circle>
</svg>
</div>
I've noticed that if I change the first keyPoints value it moves the circle. This is a stackblitz containing the same markup in case anyone wants to play with it.
I'd like to apply this approach to a different path.
<path
#thumb
transform="rotate(90)"
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke="#F66"
stroke-width="18"
pathlength="270"
stroke-dasharray="0 270"
stroke-dashoffset="-260"
id="thumb"
/>
And I assumed it would just be a matter of copying in the circle markup:
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.5;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="M20,60a35,35 0 1,1 60,0"
></animateMotion>
</circle>
And then changing the path attribute value from M20,60a35,35 0 1,1 60,0 to m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6, however this ends up placing the circle on top of the SVG path and almost out of focus.
<body>
<svg
#svgRoot
id="svgclick"
version="1.1"
viewBox="0 0 79.375 79.375"
xmlns="http://www.w3.org/2000/svg"
>
<path
transform="rotate(90)"
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="10.583"
/>
<path
#thumb
transform="rotate(90)"
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke="#F66"
stroke-width="18"
pathlength="270"
stroke-dasharray="0 270"
stroke-dashoffset="-260"
id="thumb"
/>
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="infinite"
repeatCount="infinite"
keyPoints="0.1;0.5"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
></animateMotion>
</circle>
</svg>
</body>
Thoughts?
The transform attribute is quite simply not applied to the motion path. Wrap the paths and the circle in a <g transform="rotate(90)">, remove the attributes from the individual paths, and all vectors will be positioned collectively.
Applying that transform attribute to the <circle> element will not work. That would only rotate the circle in place around its center. The motion path would be applied in the un-rotated coordinate system.
You should take the time to understand how the <animateMotion> works. It animates the circle, moving it from the first value of keyPoints to the second during the duration of the animation. The attribute dur has the value infinite, which is simply invalid. Instead, the initial value indefinite is used. Since there is also no end value, interpolation of values is turned off, you see no motion, and the first value is used at all times. That is what you intended, but I would think it preferable to stay with a valid combination of values and set both values of keyPoints to the same.
Currently, your stroke-dasharray="0 270" draws a zero-length dash (visible as a circle because of stroke-linecap="round") and a gap of the path length. I suspect you intended to draw a partial path instead from the start of the path to the dot position. For that use: stroke-dasharray="270 270".
Also, stroke-dashoffset="-260" and keyPoints="0.1;0.1" do not match. While the keyPoints go from 0...1, the dashoffset has to move from 270...0. So the correct value for the offset is 270 * (1 - 0.1) = 243.
<body>
<svg
#svgRoot
id="svgclick"
version="1.1"
viewBox="0 0 79.375 79.375"
xmlns="http://www.w3.org/2000/svg"
>
<g transform="rotate(90)" >
<path
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="10.583"
/>
<path
#thumb
d="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
stroke="#F66"
stroke-width="18"
pathlength="270"
stroke-dasharray="270 270"
stroke-dashoffset="243"
id="thumb"
/>
<circle
cx="0"
cy="0"
r="6"
stroke-width="6"
fill="#FFFFFF"
stroke="#008000"
>
<animateMotion
begin="0s"
dur="0s"
repeatCount="infinite"
keyPoints="0.1;0.1"
fill="freeze"
keyTimes="0;1"
calcMode="linear"
path="m64.961-15.355a34.984 34.412 0 0 1-49.474 1e-6 34.984 34.412 0 0 1-1e-6 -48.666 34.984 34.412 0 0 1 49.474-2e-6"
></animateMotion>
</circle>
</g>
</svg>
</body>
Your new <path> is placed: x: 64.961 y:-15.355 (first 2 values after m)
That't why you path is almost off-canvas.
Since your path is already relative, you only need to change these 2 values to change the x/y offset in your viewBox.
You can also rotate the path d directly using svg path editor.
svg{
border: 1px solid red;
width:20em;
overflow:visible
}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="circlePath" d="M25.67 79.86a34.98 34.41 90 0 1 0-49.47a34.98 34.41 90 0 1 48.67 0a34.98 34.41 90 0 1 0 49.47" fill="none" stroke-linecap="round" pathLength="100" />
</defs>
<use href="#circlePath" stroke="#D3D7DB" stroke-width="4" />
<use href="#circlePath" stroke="#008000" stroke-width="6" stroke-dasharray="50 100" />
<circle cx="0" cy="0" r="6" stroke-width="6" fill="#FFFFFF" stroke="#008000">
<animateMotion fill="freeze" begin="0s" dur="0s" repeatCount="0" keyPoints="0.5;0.5" keyTimes="0;1" calcMode="linear">
<mpath xlink:href="#circlePath" />
</animateMotion>
</circle>
</svg>
You could also define your horseshoe path as a reusable element within <def> an reference it via <use> and <mpath>.

scalling problem in shapes and controllers of svg

I want to scale in component and shape javascript but it's not working with following svg .. can you guide me how to solve this issue???
<g text-anchor="middle" font-family="sans-serif" font-size="14" stroke="#000000" fill="#FFFFFF" type="svg-ext-proceng-pumpjet" id="SHE_6769b48c-0bde4e24">
<path d="M342,232A20,20 0 0 1 322,252A20,20 0 0 1 302,232A20,20 0 0 1 322,212A20,20 0 0 1 342,232" id="SHE_80a3b7ab-a1794e09"></path>
<path d="M302,232L322,212L342,232M310.8,223.2C316.87,230.58 316.87,241.22 310.8,248.6M333.2,223.2C327.13,230.58 327.13,241.22 333.2,248.6" id="SHE_41f771e5-37da4534"></path>
</g>

Different sizes of SVG icons

I don't know why those two svg icons don't have exactly the same size when I'm checking it in the browser.
The first one is:
<svg viewBox="0 0 60 60">
<path
d='M10.3333333,16.7141667 L14.88,25.8333333 L51.6666667,25.8333333 L51.6666667,46.5 L10.3333333,46.5 L10.3333333,16.7141667 Z M56.8333333,10.3333333 L46.5,10.3333333 L51.6666667,20.6666667 L43.9166667,20.6666667 L38.75,10.3333333 L33.5833333,10.3333333 L38.75,20.6666667 L31,20.6666667 L25.8333333,10.3333333 L20.6666667,10.3333333 L25.8333333,20.6666667 L18.0833333,20.6666667 L12.9166667,10.3333333 L10.3333333,10.3333333 C7.49166667,10.3333333 5.1925,12.6583333 5.1925,15.5 L5.16666667,46.5 C5.16666667,49.3416667 7.49166667,51.6666667 10.3333333,51.6666667 L51.6666667,51.6666667 C54.5083333,51.6666667 56.8333333,49.3416667 56.8333333,46.5 L56.8333333,10.3333333 Z'
/>
</svg>
The second one:
<svg viewBox="0 0 60 60">
<path
d='M21,2 L3,2 C1.9,2 1,2.9 1,4 L1,16 C1,17.1 1.9,18 3,18 L10,18 L10,20 L8,20 L8,22 L16,22 L16,20 L14,20 L14,18 L21,18 C22.1,18 23,17.1 23,16 L23,4 C23,2.9 22.1,2 21,2 Z M21,16 L3,16 L3,4 L21,4 L21,16 Z'
/>
</svg>
The thing is that I need to have exactly the same viewBox (here 0 0 60 60)for both but when I'm setting it like this the second icon is much smaller then the first one. I'd like to have them looking the same (size) while having hte same viewBox. What am I missing here?
You can put the width and height atribute but still will not solve the issue
<svg viewBox="0 0 60 60" width="60" height="60">
<path d="M10.3333333,16.7141667 L14.88,25.8333333 L51.6666667,25.8333333 L51.6666667,46.5 L10.3333333,46.5 L10.3333333,16.7141667 Z M56.8333333,10.3333333 L46.5,10.3333333 L51.6666667,20.6666667 L43.9166667,20.6666667 L38.75,10.3333333 L33.5833333,10.3333333 L38.75,20.6666667 L31,20.6666667 L25.8333333,10.3333333 L20.6666667,10.3333333 L25.8333333,20.6666667 L18.0833333,20.6666667 L12.9166667,10.3333333 L10.3333333,10.3333333 C7.49166667,10.3333333 5.1925,12.6583333 5.1925,15.5 L5.16666667,46.5 C5.16666667,49.3416667 7.49166667,51.6666667 10.3333333,51.6666667 L51.6666667,51.6666667 C54.5083333,51.6666667 56.8333333,49.3416667 56.8333333,46.5 L56.8333333,10.3333333 Z"></path>
</svg>
and
<svg viewBox="0 0 60 60" width="60" height="60">
<path d="M21,2 L3,2 C1.9,2 1,2.9 1,4 L1,16 C1,17.1 1.9,18 3,18 L10,18 L10,20 L8,20 L8,22 L16,22 L16,20 L14,20 L14,18 L21,18 C22.1,18 23,17.1 23,16 L23,4 C23,2.9 22.1,2 21,2 Z M21,16 L3,16 L3,4 L21,4 L21,16 Z"></path>
</svg>
You can open the svg in ilustrator and fit the path to 60x60px
The second SVG has much more whitespace, and the paths only cover the top-left of the viewbox.
Added borders to show:
<svg viewBox="0 0 60 60" style="border:solid 1px red">
<path
d='M10.3333333,16.7141667 L14.88,25.8333333 L51.6666667,25.8333333 L51.6666667,46.5 L10.3333333,46.5 L10.3333333,16.7141667 Z M56.8333333,10.3333333 L46.5,10.3333333 L51.6666667,20.6666667 L43.9166667,20.6666667 L38.75,10.3333333 L33.5833333,10.3333333 L38.75,20.6666667 L31,20.6666667 L25.8333333,10.3333333 L20.6666667,10.3333333 L25.8333333,20.6666667 L18.0833333,20.6666667 L12.9166667,10.3333333 L10.3333333,10.3333333 C7.49166667,10.3333333 5.1925,12.6583333 5.1925,15.5 L5.16666667,46.5 C5.16666667,49.3416667 7.49166667,51.6666667 10.3333333,51.6666667 L51.6666667,51.6666667 C54.5083333,51.6666667 56.8333333,49.3416667 56.8333333,46.5 L56.8333333,10.3333333 Z'
/>
</svg>
<svg viewBox="0 0 60 60" style="border:solid 1px red">
<path
d='M21,2 L3,2 C1.9,2 1,2.9 1,4 L1,16 C1,17.1 1.9,18 3,18 L10,18 L10,20 L8,20 L8,22 L16,22 L16,20 L14,20 L14,18 L21,18 C22.1,18 23,17.1 23,16 L23,4 C23,2.9 22.1,2 21,2 Z M21,16 L3,16 L3,4 L21,4 L21,16 Z'
/>
</svg>
You can either:
Reduce the viewbox down to its ~ 25x25 viewbox and style the height/width using HTML/CSS instead
edit the SVG and have it fill a 60x60 viewbox

Javascript SVG place arrow on bezier [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have a cubic bezier. And I don't know how to put an arrow in the middle of it. Example below:
I want it to be like this, but with bezier. How can I do this.
Note: I've tried textPaths, markers. But nothing helped.
You have two options:
Position the marker(s), yourself, at the correct place
Split the line into two paths. One up to the first marker, and one for the rest of the path. Then assign an end marker on each path.
#1 Solution
I thank #Paul LeBeau, who found a solution and below the implementation:
We make two patches: a straight line and a curve at the end of which
there will also be markers.
<path id="line_Path" d="m20.8 22.9c0 0 47.7-0.3 68.9-0.1" />
<path id="curve_Path" d="m89.5 22.9c0 0 7.3 0 7.3 6.5 0 24 0 65.4 0 65.4 0
0-2.5 7.6 7.1 7.6 29.6 0 77.5 0 77.5 0l0 0"/>
For accurate positioning of the marker, the following attributes are
used: refX="10", refY="5"
<svg width="200" height="120" viewBox="0 0 200 120" preserveAspectRatio="xMinYMin meet" border="1">
<defs>
<marker id="MarkerArrow" viewBox="0 0 10 10" refX="10" refY="5" markerUnits="userSpaceOnUse" orient="auto" markerWidth="10" markerHeight="10">
<polyline points="0,0 10,5 0,10 3,5" fill="red"/>
</marker>
</defs>
<style>
#line_Path, #curve_Path {
fill:none;
stroke:red;
stroke-width:2;
marker-end:url(#MarkerArrow);
}
</style>
<path id="line_Path" d="m20.8 22.9c0 0 47.7-0.3 68.9-0.1" />
<path id="curve_Path" d="m89.5 22.9c0 0 7.3 0 7.3 6.5 0 24 0 65.4 0 65.4 0 0-2.5 7.6 7.1 7.6 29.6 0 77.5 0 77.5 0l0 0"/>
</svg>
#2 Solution
You can draw an arrow as an independent object
<polyline id="MarkerArrow" points="0,0 10,5 0,10 3,5" fill="red"/>
And place it on the curve the required number of times with the help
of the command
<use xlink:href="#MarkerArrow" x="80" y="18"/>
<svg width="200" height="120" viewBox="0 0 200 120" preserveAspectRatio="xMinYMin meet" border="1">
<defs>
<polyline id="MarkerArrow" points="0,0 10,5 0,10 3,5" fill="red"/>
</defs>
<path d="m20.8 22.9c0 0 47.7-0.3 68.9-0.1 5.4 0 6.8 2.9 6.9 6.8 0.4 22.6-0.8 45.9 0 66.6 0.2 4.2 2.6 6.5 6.6 6.6C129.1 103.1 180 102.2 180 102.2l0.7 0.5" style=" fill:none; stroke:red; stroke-width:2; "/>
<use xlink:href="#MarkerArrow" x="80" y="18"/>
<use xlink:href="#MarkerArrow" x="178" y="97"/>
</svg>

SVG custom circles shape

I don't have experience with SVG and I have a problem with creating my custom shape. I want to create below shape.
Share of slices and belongings lines should be genarated dynamically.
All slices are the same. For example: If we have 4 slices each slices would have 25% value, if there are 10 slices we would have 10 slices with 10%.
<!DOCTYPE html>
<html>
<body>
<svg width="800" height="800">
<circle cx="400" cy="400" r="300" stroke="black" stroke-width="2" fill="red" />
<circle cx="400" cy="400" r="80" stroke="black" stroke-width="2" fill="blue" />
<path d="M 400 400 H 480 320" stroke="black" stroke-width="2" fill="none" />Sorry, your browser does not support inline SVG.
</svg>
</body>
</html>
Please, help me out.
You will need multiple elements to this SVG.
Two for the center circle
Four for the outer circle
First, you need 4 areas for the 4 sections in the outside circle. This can be done like so:
<svg width="50%" viewbox="0 0 100 100">
<path d="M50,50 L0,50 A50,50 0 0,1 50,0" fill="red"></path>
<path d="M50,50 L100,50 A50,50 0 0,1 0,50" fill="blue"></path>
<path d="M50,50 L100,50 A50,50 0 0,1 50,100" fill="green"></path>
<path d="M50,50 L50,0 A50,50 0 0,1 100,50" fill="yellow"></path>
</svg>
For the inside area, you will need two segments with text inside.
text {
fill: white;
font-size: 16px;
}
<svg width="50%" viewbo0x="0 0 100 100">
<path d="M0,50 A50,50 0 0,1 100,50z" fill="purple"></path>
<path d="M0,50 A-50,-50 0 1,0 100,50z" fill="green"></path>
<text x="18" y="40">Some text</text>
<text x="15" y="70">Bottom text</text>
</svg>
Join them together and hey presto, you should have your shape.
text {
font-size: 2.5em;
fill: white;
}
<svg width="50%" viewbox="0 0 1000 1000">
<path d="M500,500 L0,500 A500,500 0 0,1 500,0" fill="red"></path>
<path d="M500,500 L1000,500 A500,500 0 0,1 0,500" fill="blue"></path>
<path d="M500,500 L1000,500 A500,500 0 0,1 500,1000" fill="green"></path>
<path d="M500,500 L500,0 A500,500 0 0,1 1000,500" fill="yellow"></path>
<path d="M350,500 A100,100 0 0,1 650,500z" fill="purple" x="45" y="45"></path>
<path d="M350,500 A-100,-100 0 1,0 650,500z" fill="pink"></path>
<text x="420" y="450">Some text</text>
<text x="410" y="550">Bottom text</text>
</svg>
SVG Documentation (MDN)

Categories

Resources