I have a progress semicircle and try to work dynamically with vue 3. I want a help because I dont know why it doesnt work. I change the progress variable but nothing change. Need to calculate of stroke-dashoffset but the calculation is wrong?
<template>
<svg class="circle" viewBox="2 -2 28 36" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="gradient">
<stop class="stop1" offset="0%" />
<stop class="stop2" offset="100%" />
</linearGradient>
<circle class="circle-background" r="16" cx="16" cy="16" shape-rendering="geometricPrecision"></circle>
<circle class="circle-progress" style="stroke-dashoffset: 75;" r="16" cx="16" cy="16" shape-rendering="geometricPrecision"></circle>
</svg>
</template>
<script setup>
import { ref, computed } from 'vue'
const progress = ref(50);
const strokeDashoffset = computed(() => (100 - (100 - progress.value)));
const background = computed(() => {
const angle = 360 * progress.value;
return `
radial-gradient(white 50%, transparent 51%),
conic-gradient(transparent 0deg ${angle}deg, gainsboro ${angle}deg 360deg),
conic-gradient(orange 0deg, yellow 90deg, lightgreen 180deg, green)
`;
});
</script>
<style>
/* svg {
filter: drop-shadow(0 0 10px rgb(0 0 0 / 0.4));
} */
.circle {
width: 200px;
height: 200px;
transform: rotate(-225deg);
fill: none;
stroke: white;
stroke-dasharray: 75 100;
stroke-linecap: round;
}
.circle-background {
fill: none;
stroke: gainsboro;
stroke-width: 3px;
stroke-dasharray: 75 100;
stroke-linecap: round;
}
.circle-progress {
fill: none;
stroke-linecap: round;
stroke: url(#gradient);
stroke-dasharray: 75 100;
stroke-dashoffset: 20;
stroke-linecap: round;
stroke-width: 3px;
transition: stroke-dashoffset 1s ease-in-out;
}
.stop1 {
stop-color: #e66465;
}
.stop2 {
stop-color: #9198e5;
}
#progress-circle {
background: v-bind(background);
}
.circle-progress {
stroke-dashoffset: v-bind(strokeDashoffset);
}
</style>
I'm trying to create a circle that has small pins around (like seconds in a clock) to be like 60 of them (to count a minute)
here is a picture to describe what I mean
https://www.123rf.com/photo_91759207_stock-vector-close-up-of-digital-timer-showing-time-that-is-running-out-only-25-seconds-left-clock-on-vector-illu.html
I'm using React, javascript, css,
how can I make a loop that each pin would be stack to the circle 'corner' to fit his place ?
I'm having really hard time to find a way how to arrange them to look like it.
my final goal is to create a component that will receive a fill as prop that will represent the number of pins that needs to be in a different color, so I need a way to be able to control the background-color of each pin.
any advice would be awesome. thanks!
Do you mean something like the following? The code will create 60 "pins" for all tags with the class clock.
window.onload = function() {
var clocks = document.getElementsByClassName('clock'),
r = 0, i, j, d, clock;
for(j=0;j<clocks.length;j++) {
clock = clocks[j]
for(i=0;i<60;i++) {
d = document.createElement('div');
d.style.transform = "rotate("+ r +"deg)";
clock.appendChild(d);
r += 6;
}
}
}
.clock {
position:relative;
width:180px;
height:180px;
background:#eee;
}
.clock > div {
position:absolute;
margin-left:87px;
width:6px;
height:160px;
bottom:10px;
background: linear-gradient(to bottom, #491 16px, transparent 16px);
}
<div class="clock"></div>
Drawing the 'clock face' itself is easily done with SVG and stroke-dasharray.
Animating the clock can be done with an SVG mask, and some javascript to change the stroke-dashoffset.
An explanation of the maths for coming up with the values for the stroke-dasharray can be found in this answer.
const maskCircle = document.querySelector(".mask");
const clockText = document.querySelector(".clock-text");
const r = 50;
const c = 2 * r * Math.PI;
let secondsLeft = 60;
window.setInterval(function() {
if (secondsLeft > 0) {
secondsLeft--;
clockText.innerText = secondsLeft;
maskCircle.style.strokeDashoffset =
maskCircle.style.strokeDashoffset - c / 60 * -1;
} else {
clearInterval();
}
}, 1000);
body {
background: black;
}
.clock {
margin: 0 auto;
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
}
.clock-face {
stroke-width: 15;
stroke-linecap: butt;
fill: transparent;
stroke-dasharray: 2.236 3;
}
.grey {
stroke: #333;
}
.white {
stroke: white;
}
.mask {
stroke-dasharray: 314.15 314.15;
stroke-dashoffset: 0;
}
.clock-text {
width: 100%;
margin: 0 auto;
color: white;
text-align: center;
position: absolute;
top: 50%;
font-size: 6em;
transform: translateY(-50%);
}
<div class="clock">
<svg viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="mask">
<circle class="clock-face white mask" cx="50" cy="50" r="50" transform="rotate(-90.5 50 50)" />
</mask>
</defs>
<circle class="clock-face grey" cx="50" cy="50" r="50" />
<circle class="clock-face white" cx="50" cy="50" r="50" mask="url(#mask)" />
</svg>
<div class="clock-text">60</div>
</div>
Please help me on this.
I've this svg shown in this image Image
and its my code here:
var arcpoint = [-31, -66, -101, -136, -171, -206, -241, -276];
colors = ["red", "green", "blue", "orange", "yellow", "purple", "pink"];
for (var i = 0; i < colors.length; i++) {
document.querySelector("#" + colors[i]).style.strokeDashoffset = arcpoint[i];
}
svg {
height: 100px;
width: 100px;
}
circle {
stroke-width: 4px;
fill: transparent;
}
#gray {
stroke: gray;
}
#red {
stroke: red;
stroke-dasharray: 35.5, 284;
/* length of arc, circumference of circle */
}
#green {
stroke: green;
stroke-dasharray: 35.5, 284;
/* length of arc, circumference of circle */
}
#blue {
stroke: blue;
stroke-dasharray: 35.5, 284;
/* length of arc, circumference of circle */
}
#orange {
stroke: orange;
stroke-dasharray: 35.5, 284;
/* length of arc, circumference of circle */
}
#yellow {
stroke: yellow;
stroke-dasharray: 35.5, 284;
/* length of arc, circumference of circle */
}
#purple {
stroke: purple;
stroke-dasharray: 35.5, 284;
/* length of arc, circumference of circle */
}
#pink {
stroke: pink;
stroke-dasharray: 35.5, 284;
/* length of arc, circumference of circle */
}
<div id="orbit">
<svg viewBox='0 0 100 100'>
<circle cx='50' cy='50' r='45' id='gray'/>
<circle cx='50' cy='50' r='45' id='red'/>
<circle cx='50' cy='50' r='45' id='green'/>
<circle cx='50' cy='50' r='45' id='blue'/>
<circle cx='50' cy='50' r='45' id='orange'/>
<circle cx='50' cy='50' r='45' id='yellow'/>
<circle cx='50' cy='50' r='45' id='purple'/>
<circle cx='50' cy='50' r='45' id='pink'/>
</svg>
</div>
Now i want to rotate all arc's clockwise and anti-clockwise by clicking on a button.
Problem is, my mind is stuck on how to make function and loop to change colors and rotate clockwise and anti-clockwise.
Any help would be appreciated.
Thanks in advance!
You can easily use a css animation and then just add the class to your svg on a click function. Like this:
var arcpoint = [-31, -66, -101, -136, -171, -206, -241, -276];
colors = ["red", "green", "blue", "orange", "yellow", "purple", "pink"];
for (var i = 0; i < colors.length; i++) {
document.querySelector("#" + colors[i]).style.strokeDashoffset = arcpoint[i];
}
$('.left').click(function(){
$("#orbit svg").attr("class", "rotating-left");
});
$('.right').click(function(){
$("#orbit svg").attr("class", "rotating-right");
});
svg {
height: 100px;
width: 100px;
}
circle {
stroke-width: 4px;
fill: transparent;
}
#gray{
stroke: gray;
}
#red{
stroke: red;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#green{
stroke: green;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#blue{
stroke: blue;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#orange{
stroke: orange;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#yellow{
stroke: yellow;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#purple{
stroke: purple;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#pink{
stroke: pink;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
.rotating-right {
animation: rotating-right 2s linear infinite;
}
#keyframes rotating-right {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.rotating-left {
animation: rotating-left 2s linear infinite;
}
#keyframes rotating-left {
from {
transform: rotate(0deg);
}
to {
transform: rotate(-360deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="orbit" >
<svg viewBox='0 0 100 100' >
<circle cx='50' cy='50' r='45' id='gray'/>
<circle cx='50' cy='50' r='45' id='red'/>
<circle cx='50' cy='50' r='45' id='green'/>
<circle cx='50' cy='50' r='45' id='blue'/>
<circle cx='50' cy='50' r='45' id='orange'/>
<circle cx='50' cy='50' r='45' id='yellow'/>
<circle cx='50' cy='50' r='45' id='purple'/>
<circle cx='50' cy='50' r='45' id='pink'/>
</svg>
</div>
<button class="left">left</button>
<button class="right">right</button>
Notice I used $("#orbit svg").attr("class", "rotating-right"); as you can't use addClass on a svg with jQuery
Maybe you want something like this?
var colors = ["gray", "red", "green", "blue", "orange", "yellow", "purple", "pink"];
var rotateOffset = 0;
function setColours()
{
for (var i = 0; i < colors.length; i++) {
var arcIndex = (i + rotateOffset) % colors.length;
document.querySelector("#" + colors[i]).style.strokeDashoffset = (arcIndex ) * -35.3;
}
}
// Set initial colours
setColours();
// Button handlers
document.getElementById('left').addEventListener("click", function() {
rotateOffset += (colors.length - 1);
setColours();
});
document.getElementById('right').addEventListener("click", function() {
rotateOffset++
setColours();
});
svg {
height: 100px;
width: 100px;
}
circle {
stroke-width: 4px;
fill: transparent;
}
#gray{
stroke: gray;
}
#red{
stroke: red;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#green{
stroke: green;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#blue{
stroke: blue;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#orange{
stroke: orange;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#yellow{
stroke: yellow;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#purple{
stroke: purple;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
#pink{
stroke: pink;
stroke-dasharray: 35.5, 284; /* length of arc, circumference of circle */
}
<div id="orbit" >
<svg viewBox='0 0 100 100' >
<circle cx='50' cy='50' r='45' id='gray'/>
<circle cx='50' cy='50' r='45' id='red'/>
<circle cx='50' cy='50' r='45' id='green'/>
<circle cx='50' cy='50' r='45' id='blue'/>
<circle cx='50' cy='50' r='45' id='orange'/>
<circle cx='50' cy='50' r='45' id='yellow'/>
<circle cx='50' cy='50' r='45' id='purple'/>
<circle cx='50' cy='50' r='45' id='pink'/>
</svg>
</div>
<button id="left">left</button>
<button id="right">right</button>
I have multiple SVG circles and would like each to have unique text appear in a tooltip on hover.
I will be creating my SVG elements in Adobe Illustrator, so need a way to bind text for the tooltip to the id's of the SVGs.
Below I have tried to do this by creating an array with object "color: white" matching the name of the SVG circle id="#white" How can I bind this data to my tooltip?
var tooltipText = [
{"color":"white", "text":"About white"},
{"color":"black", "text":"About black"}
]
var tooltip = d3.select('.tooltip').text(function(d) {return tooltipText})
d3.select('#white')
.on("mouseover", function(){
return tooltip.style("visibility", "visible");
})
.on("mousemove", function(){
return tooltip
.style("top",(d3.event.pageY+10)+"px")
.style("left",(d3.event.pageX+10)+"px");
})
.on("mouseout", function(){
return tooltip.style("visibility", "hidden");
});
.container {
position: relative;
}
.tooltip {
font-family: Arial;
font-size: 10px;
padding: 10px;
width: 100px;
height: 150px;
border: 1px solid black;
position: absolute;
top: 0;
left: 200px;
visibility: hidden;
background: white;
}
#white {
fill: white;
stroke: black;
stroke-width: 2px
}
#black {
fill: black
}
circle:hover {
stroke: green; !important
fill: orange;
stroke-width: 2px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div class="container">
<svg>
<g id="selection">
<circle id="white" class="st0" cx="49.2" cy="49.2" r="48.7"/>
<circle id="black" class="st1" cx="128.4" cy="49.2" r="48.7"/>
</g>
</svg>
</div>
<div class="tooltip"></div>
First, we get the Id of the circle with this line inside your mousemove:
var thisId = d3.select(this).attr("id");
Then, we loop through your array and get the corresponding value:
var index;
for(var i = 0; i < tooltipText.length; i++){
if(tooltipText[i].color == thisId){
index= i
}
};
tooltip.html(tooltipText[index].text)
Here is your updated snippet:
var tooltipText = [
{"color":"white", "text":"About white"},
{"color":"black", "text":"About black"}
]
var tooltip = d3.select('.tooltip').text(function(d) {return tooltipText})
d3.selectAll("circle")
.on("mousemove", function(d){
var thisId = d3.select(this).attr("id");
var index;
for(var i = 0; i < tooltipText.length; i++){
if(tooltipText[i].color == thisId){ index= i}
};
tooltip.html(tooltipText[index].text)
.style("visibility", "visible")
.style("top",(d3.event.pageY+10)+"px")
.style("left",(d3.event.pageX+10)+"px");
})
.on("mouseout", function(){
return tooltip.style("visibility", "hidden");
});
.container {
position: relative;
}
.tooltip {
font-family: Arial;
font-size: 10px;
padding: 10px;
width: 100px;
height: 20px;
border: 1px solid black;
position: absolute;
top: 0;
left: 200px;
visibility: hidden;
background: white;
}
#white {
fill: white;
stroke: black;
stroke-width: 2px
}
#black {
fill: black
}
circle:hover {
stroke: green; !important
fill: orange;
stroke-width: 2px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div class="container">
<svg>
<g id="selection">
<circle id="white" class="st0" cx="49.2" cy="49.2" r="48.7"/>
<circle id="black" class="st1" cx="128.4" cy="49.2" r="48.7"/>
</g>
</svg>
</div>
<div class="tooltip"></div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1069" height="575" xml:space="preserve">
<desc>Created with Fabric.js 1.4.13</desc>
<defs></defs>
<rect x="-20" y="-20" rx="10" ry="10" width="40" height="40" style="stroke: black; stroke-width: 0.3; stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: DarkSalmon; fill-rule: nonzero; opacity: 1;"
transform="translate(461.15 451.15)" id="0"></rect>
<rect x="-20" y="-20" rx="10" ry="10" width="40" height="40" style="stroke: black; stroke-width: 0.3; stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: DarkSalmon; fill-rule: nonzero; opacity: 1;" transform="translate(429.15 310.15)"
id="1"></rect>
<rect x="-20" y="-20" rx="10" ry="10" width="40" height="40" style="stroke: black; stroke-width: 0.3; stroke-dasharray: ; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: DarkSalmon; fill-rule: nonzero; opacity: 1;" transform="translate(351.15 177.15)"
id="2"></rect>
this code has generated by fabricjs.1st added rect object is placed in first line in svg code.before genarate the svg code i change the positions of rect object by dragging.but the svg code has not changed acording to that.what i want to do is set the ID to every rect in svg code acording to displaying order.displaying order means top to bottom or bottom to top on screen.is it possible to do?thank you.
You can use this JS to give each 'rect' tag an id based on its location.
var SVG = document.getElementsByTagName('svg')[0];
var children = SVG.childNodes;
var ID = 0;
[].forEach.call(children, function (child) {
if(child.nodeType === 1 && child.tagName == "rect"){
child.setAttribute('id', ID);
ID++;
}
});
This will give the id 0 to the first 'rect' 1 to the next and so on.