Using an SVG as a css background image on input range thumb - javascript

I am trying to use a custom background SVG for a range slider thumb in React using styled components. At the moment I am having trouble getting the SVG I have created to show. I have tested with other SVG's online and it works. Here is where I have got to thus far. It is in React with Typescript using styled-components
My compomnent styles:
const sliderThumbStyles = (props: any) => `
width: 40px;
height: 40px;
border: 0;
background: url("data:image/svg+xml, SVG to go in here");
border-radius: 20px;
border: 5px solid white;
cursor: pointer;
margin-top: -18px
`;
const SliderWrapper = styled.div`
.value {
flex: 1;
font-size: 2rem;
}
.slider {
-webkit-appearance: none;
appearance: none;
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
${(props) => sliderThumbStyles(props)}
}
&::-moz-range-thumb {
${(props) => sliderThumbStyles(props)}
}
&::-webkit-slider-runnable-track {
background: black;
height: 3px;
outline: none;
}
&::-moz-slider-track {
background: black;
height: 3px;
outline: none;
}
}
`;
And here is my SVG file that is in ./src/assets/images/slider/slider-thumb.svg
<svg width="63" height="63" viewBox="0 0 63 63" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="5.05025" y="31.2134" width="37" height="37" rx="18.5" transform="rotate(-45 5.05025 31.2134)" fill="#FF9675" stroke="white" stroke-width="7"/>
<path d="M31.3357 40.8633L31.3357 22.0019" stroke="#1D1D1D" stroke-width="2" stroke-miterlimit="10"/>
<path d="M38.67 26.334C32.3829 26.334 31.335 18.999 31.335 18.999C31.335 18.999 30.2871 26.334 24 26.334" stroke="#1D1D1D" stroke-width="2" stroke-miterlimit="10" stroke-linejoin="bevel"/>
<path d="M38.67 35.5283C32.3829 35.5283 31.335 42.8633 31.335 42.8633C31.335 42.8633 30.2871 35.5283 24 35.5283" stroke="#1D1D1D" stroke-width="2" stroke-miterlimit="10" stroke-linejoin="bevel"/>
</svg>
When I try and import the SVg and include it in the css property inside sliderThumbStyles method it doesn't work. I have tried dropping the SVG markup in directly too and this doesn't work. As I said, it works when I dropped in a random SVG from the web so I think my SVG markup is wrong or I am importing it incorrecty. Can anyone point me to as to where I am going wrong?
Thanks

I manage to use your svg as a thumbnail, but I had to
convert the double quotes to single quotes
remove all line breaks
encode the # with %23
ajust the width and heigth inside your svg tag to match the css
.slider {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 10px;
background: #d3d3d3;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 40px;
height: 40px;
border: 0;
background: url("data:image/svg+xml,<svg width='40' height='40' viewBox='0 0 63 63' fill='none' xmlns='http://www.w3.org/2000/svg'><rect x='5.05025' y='31.2134' width='37' height='37' rx='18.5' transform='rotate(-45 5.05025 31.2134)' fill='%23FF9675' stroke='white' stroke-width='7'/><path d='M31.3357 40.8633L31.3357 22.0019' stroke='%231D1D1D' stroke-width='2' stroke-miterlimit='10'/><path d='M38.67 26.334C32.3829 26.334 31.335 18.999 31.335 18.999C31.335 18.999 30.2871 26.334 24 26.334' stroke='%231D1D1D' stroke-width='2' stroke-miterlimit='10' stroke-linejoin='bevel'/><path d='M38.67 35.5283C32.3829 35.5283 31.335 42.8633 31.335 42.8633C31.335 42.8633 30.2871 35.5283 24 35.5283' stroke='%231D1D1D' stroke-width='2' stroke-miterlimit='10' stroke-linejoin='bevel'/></svg>");
cursor: pointer;
}
<input type="range" min="1" max="100" value="50" class="slider">

Related

I have a There is a problem with implementing the model window in the react

I am currently implementing a modal window. If I click the icon on the navigation bar, the background is blurred and the modal window appears. I changed the value of passedMake to false when I clicked X to close the modal window. But even if I click X, the modal window doesn't close. When I checked with console, the value of passedMake changes to false when I click X, but then value comes out true twice and the modal window doesn't close. The question is why the true value is printed twice after false value is checked when X is clicked. I don't know which part is the problem. I will attach a picture of the value in the console. I erased the unnecessary parts as much as I can to make the code easier to understand. I'd appreciate it if you let me know thanks!
NavigationBar:
this is navigation bar file. I pass the value to parent component if Icon is clicked
import React, { useState } from 'react'
import styled from 'styled-components';
const NavigationBarWrap1 = styled.div`
position: fixed;
flex-direction: column;
box-sizing: border-box;
display: flex;
flex-shrink: 0;
.NavigationBarSection1Wrap2 {
opacity: 1;
display: block;
color: rgb(38,38,38);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 18px;
direction: ltr;
}
.IconWrap3 {
position: relative;
display: block;
}
.IconWrap4 {
text-decoration: none;
color: rgb(0,55,107);
box-sizing: border-box;
display: inline;
background-color: transparent;
cursor: pointer;
}
.IconWrap5 {
border-bottom-left-radius: 24px;
padding-right: 12px;
align-items: center;
padding-top: 12px;
width: 100%;
}
.IconWrap6 {
position: relative;
flex: 0 0 auto;
justify-content: flex-start;
flex-direction: column;
}
.IconWrap7 {
box-sizing: border-box;
height: 24px;
width: 24px;
}
`
function NavigationBar({toParentIsMake,}) {
//state declare
const[make,setMake] = useState(false);
const setTrueMake = () => {
setMake(true)
}
const forMake = (e) => {
setTrueMake();
}
//pass value to parent
toParentIsMake(make);
return (
<NavigationBarWrap1 search={search} profile={profile} alarm={alarm} seeMore={seeMore}>
<div className='NavigationBarWrap2'>
<div className='IconWrap3'>
<div className='IconWrap4'>
<div onClick={(e)=>{forMake();}} className='IconWrap5'>
<div>
<div className='IconWrap6'>
<div className='IconWrap7'>
{make===true?
<>
<svg aria-label="새로운 게시물" class="_ab6-" color="#262626" fill="#262626" height="24" role="img" viewBox="0 0 24 24" width="24"><path d="m12.003 5.545-.117.006-.112.02a1 1 0 0 0-.764.857l-.007.117V11H6.544l-.116.007a1 1 0 0 0-.877.876L5.545 12l.007.117a1 1 0 0 0 .877.876l.116.007h4.457l.001 4.454.007.116a1 1 0 0 0 .876.877l.117.007.117-.007a1 1 0 0 0 .876-.877l.007-.116V13h4.452l.116-.007a1 1 0 0 0 .877-.876l.007-.117-.007-.117a1 1 0 0 0-.877-.876L17.455 11h-4.453l.001-4.455-.007-.117a1 1 0 0 0-.876-.877ZM8.552.999h6.896c2.754 0 4.285.579 5.664 1.912 1.255 1.297 1.838 2.758 1.885 5.302L23 8.55v6.898c0 2.755-.578 4.286-1.912 5.664-1.298 1.255-2.759 1.838-5.302 1.885l-.338.003H8.552c-2.754 0-4.285-.579-5.664-1.912-1.255-1.297-1.839-2.758-1.885-5.302L1 15.45V8.551c0-2.754.579-4.286 1.912-5.664C4.21 1.633 5.67 1.05 8.214 1.002L8.552 1Z"></path></svg>
</>:
<>
<svg aria-label="새로운 게시물" class="_ab6-" color="#262626" fill="#262626" height="24" role="img" viewBox="0 0 24 24" width="24"><path d="M2 12v3.45c0 2.849.698 4.005 1.606 4.944.94.909 2.098 1.608 4.946 1.608h6.896c2.848 0 4.006-.7 4.946-1.608C21.302 19.455 22 18.3 22 15.45V8.552c0-2.849-.698-4.006-1.606-4.945C19.454 2.7 18.296 2 15.448 2H8.552c-2.848 0-4.006.699-4.946 1.607C2.698 4.547 2 5.703 2 8.552Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path><line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="6.545" x2="17.455" y1="12.001" y2="12.001"></line><line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" x1="12.003" x2="12.003" y1="6.545" y2="17.455"></line></svg>
</>}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</NavigationBarWrap1>
)
}
export default NavigationBar;
HomePage.jsx:
and this is homepage file I'm trying to implement modal window. When Icon of navigation bar is clickd, background color becomes blur and modal window appears.
import React, { useEffect } from 'react'
import styled from 'styled-components';
import NavigationBar from '../components/NavigationBar';
import { useState } from 'react';
function HomePage() {
//receive value from chid
const[passedMake,setPassedMake] = useState(false);
const toParentIsMake = (isMakeClick) => {
setPassedMake(isMakeClick)
}
console.log('passedMake' , passedMake)
//if click X, close modal
const noModal = (e) => {
setPassedMake(false)
}
return (
<>
<HomepageWrap>
<NavigationBar toParentIsMake={toParentIsMake} passedMake={passedMake}/>
</HomepageWrap>
<Modal passedMake={passedMake}>
<div onClick={(e)=>{noModal();}} className='X'>
<div className='X2'>
<div className='X3'>
<svg aria-label="닫기" class="x1n2onr6 x1lliihq" color="#ffffff" fill="#ffffff" height="18" role="img" viewBox="0 0 24 24" width="18"><title>닫기</title><polyline fill="none" points="20.643 3.357 12 12 3.353 20.647" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="3"></polyline><line fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" x1="20.649" x2="3.354" y1="20.649" y2="3.354"></line></svg>
</div>
</div>
</div>
</Modal>
</>
)
}
export default HomePage;
const HomepageWrap = styled.div`
height: 100%;
box-sizing: border-box;
display: flex;
flex-shrink: 0;
align-items: stretch;
flex-direction: row;
overflow-y: visible;
align-content: stretch;
border-bottom-left-radius: 0;
background-color: rgb(250,250,250);
border-bottom-right-radius: 0;
position: static;
justify-content: space-between;
overflow-x: visible;
align-self: auto;
flex-grow: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
`
const Modal = styled.div`
display: ${props=>props.passedMake===true?'block':'none'};
position: fixed;
background-color: rgba(0,0,0,0.65);
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 500343;
.X {
top: 10px;
right: 10px;
position: absolute;
cursor: pointer;
}
.X2 {
padding: 8px;
justify-content: center;
box-sizing: border-box;
display: flex;
align-items: center;
}
.X3 {
justify-content: center;
display: flex;
flex-direction: column;
}
`
I'm not quite sure what the exact issue is because your code is pretty confusing, but if I were to guess the issue is probably that lone call to toParentShowMake(make) in NavigationBar.
It seems to me that that call is supposed to pass an event to HomePage, which then updates its state to match that of the NavigationBar; that's not how you're supposed to do it.
You're duplicating the state that controls whether or not the modal should be shown, and that is just asking for problems.
Instead, you should keep the state that controls the modal in HomePage:
function HomePage () {
const [ showModal, setShowModal ] = useState(false)
const show = () => setShowModal(true)
const hide = () => setShowModal(false)
return (
<>
<HomepageWrap>
<NavigationBar onShowModal={show} />
</HomepageWrap>
<Modal show={showModal}>
<div onClick={hide} className='X'>
{/* ... */}
</div>
</Modal>
</>
)
}
Then in NavigationBar, accept a callback that will update that state:
function NavigationBar({ onShowModal }) {
return (
<NavigationBarWrap1>
<div onClick={onShowModal} className='IconWrap5'>
{/* ... */}
</div>
</NavigationBarWrap1>
)
}
This way, there's only one place that controls the Modal, the HomePage in which it lives.

On click add class to hide other elements using vanilla JavaScript

At the moment when the user clicks one of the SVGs the class "clicked" is added to that particular SVG. What I would like to happen is that when an SVG is clicked on the page, the other SVG elements are hidden (opacity: 0 or something) and not clickable.
My JS knowledge is a bit limited. I was thinking a class would need to be added to the SVGs when the others were inactive as I was thinking about transitioning them out when a click happens, however would appreciate any suggestions.
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Interactive SVG</title>
<link rel="stylesheet" href="static/css/styles.css" />
</head>
<body>
<div class="container" id="container">
<svg version="1.0" class="svg svg-a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect class="rect rect-a" width="100" height="100" />
</svg>
<svg version="1.0" class="svg svg-b" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect class="rect rect-b" width="100" height="100" />
</svg>
<svg version="1.0" class="svg svg-c" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect class="rect rect-c" width="100" height="100" />
</svg>
</div>
<script src="https://cdn.jsdelivr.net/npm/animejs#3.0.1/lib/anime.min.js"></script>
<script src="static/js/script.js"></script>
</body>
</html>
body {
margin: 0;
padding: 0;
}
.container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100vh;
background: #222;
position: relative;
}
svg {
display: flex;
width: 100px;
height: 100px;
transition: 0.7s ease-out;
}
.rect {
cursor: pointer;
fill: #eee;
transform-origin: 50% 50%;
transition: 0.5s;
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
box-shadow: 20px 20px 20px 0;
position: absolute;
}
.rect-a {
fill: cornflowerblue;
z-index: 390;
}
.rect-b {
fill: pink;
box-shadow: 20px 20px 20px 0;
}
.rect-c {
fill: azure;
box-shadow: 20px 20px 20px 0;
}
.clicked {
fill: cornflowerblue;
transform: scale(1.2);
transform-origin: 50% 50%;
transition: 0.5s;
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}
.clicked svg {
fill: red;
transform: translateY(500px);
}
button {
position: absolute;
z-index: 1000;
color: red;
top: -5px;
right: -5px;
border-radius: 100px;
z-index: 900;
}
// First we get all the path elements and put them in an array
let paths = document.getElementsByClassName('svg');
// Now we can loop over the array and add an eventlistener to each path in the array and it listens to the 'click' event and then runs function toggleClass()
for (let i = 0; i < paths.length; i++) {
paths[i].addEventListener('click', toggleClass);
}
// In the function toggleClass we can toggle the 'clicked' class.
function toggleClass() {
this.classList.toggle('clicked');
}
https://codepen.io/chrismorrison/pen/ZEWdJyV
Updated CodePen w/ rough implementation of what I believe you are looking for.
Below are the changes I made:
JS
// In the function toggleClass we can toggle the 'clicked' class.
function toggleClass(e) {
const clickedClassName = 'clicked';
// If "disabled", don't respond to the click event.
if(this.classList.contains('disabled')) {
e.preventDefault();
}
// The element is "enabled". Has it been clicked
// already? If so, we need to restore it along with
// all the other SVGs back to their original state.
// If not, then hide all other SVGs and add the "clicked"
// class to the element that was clicked
else if(!this.classList.contains(clickedClassName)) {
this.classList.add(clickedClassName);
for(let p of paths) {
if(this !== p) {
toggleDisabled(p)
}
}
} else {
this.classList.remove(clickedClassName);
for(let p of paths) {
if(this !== p) {
toggleDisabled(p)
}
}
}
}
function toggleDisabled(p) {
p.classList.contains('disabled') ? p.classList.remove('disabled') : p.classList.add('disabled')
}
CSS
.disabled {
opacity: 0;
}

lazy line painter as a pre-loader

I have an animated SVG using lazy line painter that I would like to use as a pre-loader. How can I review the page content (with a transition or a simple fade-in) after the line animation is completed?
So the concept is this: on landing LOAD SVG animation when COMPLETE transition into page content.
<!-- Include lazylinepainter -->
<script src="https://cdn.jsdelivr.net/npm/ lazy-line-painter#1.9.4/lib/lazy-line-painter-1.9.4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/d3js/5.15.0/d3.min.js"></script>
<script type="text/javascript">
(function(){
document.onreadystatechange = () => {
if (document.readyState === 'complete') {
let el = document.querySelector('#markin2');
let myAnimation = new LazyLinePainter(el, {"ease":"easeLinear","strokeWidth":2.2,"strokeOpacity":1,"strokeColor":"#fff"});
myAnimation.paint();
}
}
})();
</script>
<svg version="1.1" id="markin2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="314.094px" height="314.765px" viewBox="0 0 314.094 314.765" enable-background="new 0 0 314.094 314.765" xml:space="preserve" data-llp-composed="true" class="lazy-line-painter">
<circle fill="none" stroke-miterlimit="10" cx="157.828" cy="157.404" r="150.813" data-llp-id="markin2-0" data-llp-duration="2920" data-llp-delay="0" fill-opacity="1" data-llp-stroke-join="" data-llp-stroke-cap=""/>
<path id="#markin2" class=".markin2" fill="none" values="#000" stroke-miterlimit="10" d="M18.482,132.273
c1.019-4.147,1.774-8.38,3.099-12.427c7.988-24.405,24.611-39.774,49.798-44.317c26.582-4.795,47.878,5.064,64.031,26.525
c2.094,2.782,2.112,4.714-0.499,7.183c-3.496,3.306-6.592,7.035-10.095,10.837c-2.364-3.506-4.425-7.039-6.94-10.211
C104.843,93.427,81.91,88.297,62.884,97.426c-18.967,9.102-29.097,30.539-24.289,51.399c4.649,20.172,22.977,34.573,43.973,34.571
c13.572-0.002,24.751-5.104,33.906-15.18c22.505-24.771,44.815-49.735,67.885-73.971c17.361-18.239,39.164-24.295,63.441-17.369
c24.221,6.91,39.282,23.516,45.102,48.006c3.184,13.398,1.887,26.967-2.008,39.987c-1.322,4.422-5.715,7.985-8.899,11.78
c-10.94,13.035-24.349,21.988-41.47,24.67c-19.018,2.979-35.86-2.006-50.829-13.86c-1.162-0.92-2.304-1.863-4.361-3.533
c0,2.48-0.004,4.178,0,5.873c0.045,22.324,0.009,44.646,0.213,66.967c0.037,3.956-0.771,7.102-3.877,9.674
c-1.653,1.37-3.243,2.961-4.409,4.748c-2.552,3.912-5.974,4.865-10.668,3.637c0-6.688,0.01-13.473-0.003-20.258
c-0.041-22.488,0.024-44.979-0.227-67.465c-0.056-4.814,1.073-8.443,4.622-11.914c6.039-5.908,11.509-12.398,17.593-19.056
c4.06,8.205,9.36,14.85,16.678,19.736c15.507,10.355,35.698,10.172,51.128-0.49c15.202-10.506,22.338-29.406,18.086-47.903
c-3.979-17.298-19.188-31.573-37.106-33.975c-15.415-2.066-29.11,2.093-39.841,13.781c-21.17,23.057-42.371,46.092-63.192,69.461
c-14.497,16.271-31.743,25.988-53.992,25.404c-30.517-0.799-56.945-24.744-60.94-55.143c-0.123-0.934-0.602-1.821-0.915-2.73
C18.482,140.272,18.482,136.272,18.482,132.273z" data-llp-id="markin2-1" data-llp-duration="2920" data-llp-delay="0" fill-opacity="1" data-llp-stroke-join="" data-llp-stroke-cap=""/>
</svg>
CSS
body, html {
background: #000;
position: absolute;
width: 100%;
height: 100%;
top:0;
left:0;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
}
#markin2 {
width: 40vw;
height: 40vh;
position: relative;
overflow: visible;
}
.markin2 {
animation: stroke_fill 4s linear forwards, changeColor 2s, forwards;
stroke-dasharray: 1538.2169189453125px;
stroke-dashoffset: 0;
}
#keyframes stroke_fill {
0% {
fill: white;
}
50% {
fill: white;
stroke-dashoffset: 0;
}
100% {
fill: black;
stroke-dashoffset: 0;
}
}
#keyframes changeColor {
from{ fill: rgba(0,0,0,0);}
to{ fill: rgba(0,0,0,1)}
}
Here is the SVG animation example:
https://codepen.io/cpawl/pen/zYvEqYq
The Lazy Line Painter library has some custom events built in to which you can listen. Such as the complete event whenever you animation has been completed. Whenever that event is called, hide the SVG.
In the example below I've added this event listener but also wrapped your animation in a Promise. This way you can wait for it to finish and then do something. And also another Promise which listens for the load event on the document. So that this is an actual page loader and the SVG would not disappear before the page would be loaded.
In your HTML first load the SVG and then the JS you see below here. Inside the then callback function either delete your SVG, or set a class to the body which hides the class. Anyway you see fit.
body,
html {
background: #000;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
}
#markin2 {
width: 20vw;
height: 20vh;
position: relative;
overflow: visible;
}
.markin2 {
animation: stroke_fill 4s linear forwards, changeColor 2s, forwards;
stroke-dasharray: 1538.2169189453125px;
stroke-dashoffset: 0;
}
#keyframes stroke_fill {
0% {
fill: white;
}
50% {
fill: white;
stroke-dashoffset: 0;
}
100% {
fill: black;
stroke-dashoffset: 0;
}
}
#keyframes changeColor {
from {
fill: rgba(0, 0, 0, 0);
}
to {
fill: rgba(0, 0, 0, 1);
}
}
.hsvg {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
width: 100%;
height: 100%;
background: #000000;
z-index: 999;
transition: 2000ms ease-in-out;
transition-property: opacity, visibility;
}
body.is-loaded .hsvg {
opacity: 0;
visibility: hidden;
}
.main-content {
color: #fff;
}
<script src="https://cdn.jsdelivr.net/npm/lazy-line-painter#1.9.6/lib/lazy-line-painter-1.9.6.min.js"></script>
<!-- Include lazylinepainter -->
<div class="hsvg">
<svg version="1.1" id="markin2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="314.094px" height="314.765px" viewBox="0 0 314.094 314.765" enable-background="new 0 0 314.094 314.765" xml:space="preserve"
data-llp-composed="true" class="lazy-line-painter">
<circle fill="none" stroke-miterlimit="10" cx="157.828" cy="157.404" r="150.813" data-llp-id="markin2-0" data-llp-duration="2920" data-llp-delay="0" fill-opacity="1" data-llp-stroke-join="" data-llp-stroke-cap=""/>
<path id="#markin2" class=".markin2" fill="none" values="#000" stroke-miterlimit="10" d="M18.482,132.273
c1.019-4.147,1.774-8.38,3.099-12.427c7.988-24.405,24.611-39.774,49.798-44.317c26.582-4.795,47.878,5.064,64.031,26.525
c2.094,2.782,2.112,4.714-0.499,7.183c-3.496,3.306-6.592,7.035-10.095,10.837c-2.364-3.506-4.425-7.039-6.94-10.211
C104.843,93.427,81.91,88.297,62.884,97.426c-18.967,9.102-29.097,30.539-24.289,51.399c4.649,20.172,22.977,34.573,43.973,34.571
c13.572-0.002,24.751-5.104,33.906-15.18c22.505-24.771,44.815-49.735,67.885-73.971c17.361-18.239,39.164-24.295,63.441-17.369
c24.221,6.91,39.282,23.516,45.102,48.006c3.184,13.398,1.887,26.967-2.008,39.987c-1.322,4.422-5.715,7.985-8.899,11.78
c-10.94,13.035-24.349,21.988-41.47,24.67c-19.018,2.979-35.86-2.006-50.829-13.86c-1.162-0.92-2.304-1.863-4.361-3.533
c0,2.48-0.004,4.178,0,5.873c0.045,22.324,0.009,44.646,0.213,66.967c0.037,3.956-0.771,7.102-3.877,9.674
c-1.653,1.37-3.243,2.961-4.409,4.748c-2.552,3.912-5.974,4.865-10.668,3.637c0-6.688,0.01-13.473-0.003-20.258
c-0.041-22.488,0.024-44.979-0.227-67.465c-0.056-4.814,1.073-8.443,4.622-11.914c6.039-5.908,11.509-12.398,17.593-19.056
c4.06,8.205,9.36,14.85,16.678,19.736c15.507,10.355,35.698,10.172,51.128-0.49c15.202-10.506,22.338-29.406,18.086-47.903
c-3.979-17.298-19.188-31.573-37.106-33.975c-15.415-2.066-29.11,2.093-39.841,13.781c-21.17,23.057-42.371,46.092-63.192,69.461
c-14.497,16.271-31.743,25.988-53.992,25.404c-30.517-0.799-56.945-24.744-60.94-55.143c-0.123-0.934-0.602-1.821-0.915-2.73
C18.482,140.272,18.482,136.272,18.482,132.273z" data-llp-id="markin2-1" data-llp-duration="2920" data-llp-delay="0" fill-opacity="1" data-llp-stroke-join="" data-llp-stroke-cap=""/>
</svg>
</div>
<script>
const pageLoad = new Promise(resolve => {
window.addEventListener('load', resolve);
});
const animationLoad = new Promise(resolve => {
let el = document.querySelector('#markin2');
let myAnimation = new LazyLinePainter(el, {
"ease": "easeLinear",
"strokeWidth": 2.2,
"strokeOpacity": 1,
"strokeColor": "#fff"
});
myAnimation.paint();
myAnimation.on('complete', resolve);
});
Promise.all([pageLoad, animationLoad]).then(function() {
document.body.classList.add('is-loaded');
console.log('Load event fired and animation done');
});
</script>
<div class="main-content">
<h1>IS THIS THING ON?</h1>
</div>

seconds in a circle corner (like a clock)

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>

How to programmatically build curves in svg path?

I'm trying to build a line chart using an SVG, but I'm having a hard time making the path have nice curves. As much as internet told me, the best way to accomplish this is using Q and T, but I don't really get the intended result.
Here are two of the versions I have built, first one doesn't have curves, but the second one overflows the svg container for some reason.
*, *:after, *:before {
box-sizing: border-box;
position: relative;
font-family: 'Montserrat', sans-serif;
}
svg {
width: 30vmin; height: 30vmin;
fill: none;
position: relative;
z-index: 3;
border: 2px solid red;
}
path {
stroke-width: 3px;
// stroke-dasharray: 4;
}
button {
left: 0; top: 0;
position: absolute;
}
html, body {
overflow: hidden;
width: 100%; height: 100%;
display: flex;
align-items: center;
justify-content: space-around;
margin: 0; padding: 0;
background-color: #333ddd;
}
<svg viewBox="0 0 100 100" preserveAspectRatio="none"><path d="M0,16.372727272727275 Q7.6923076923076925,29.09090909090908 15.384615384615385,29.09090909090908 23.076923076923077,2.7363636363636346 30.76923076923077,42.73636363636363 38.46153846153846,69.0909090909091 46.15384615384615,56.37272727272727 53.84615384615385,56.37272727272727 61.53846153846154,82.73636363636363 69.23076923076923,95.45454545454545 76.92307692307692,82.73636363636363 84.61538461538461,82.73636363636363 92.3076923076923,42.73636363636363 T100,42.73636363636363" fill="none" stroke="white" vector-effect="non-scaling-stroke"></path></svg>
<svg viewBox="0 0 100 100" preserveAspectRatio="none"><path d="M0,16.372727272727275 Q 7.6923076923076925,29.09090909090908 15.384615384615385,29.09090909090908 T 23.076923076923077,2.7363636363636346 30.76923076923077,42.73636363636363 38.46153846153846,69.0909090909091 46.15384615384615,56.37272727272727 53.84615384615385,56.37272727272727 61.53846153846154,82.73636363636363 69.23076923076923,95.45454545454545 76.92307692307692,82.73636363636363 84.61538461538461,82.73636363636363 92.3076923076923,42.73636363636363 100,42.73636363636363" fill="none" stroke="white" vector-effect="non-scaling-stroke"></path></svg>
<svg viewBox="0 0 100 100" preserveAspectRatio="none"><path d="M0,16.372727272727275 7.6923076923076925,29.09090909090908 15.384615384615385,29.09090909090908 23.076923076923077,2.7363636363636346 30.76923076923077,42.73636363636363 38.46153846153846,69.0909090909091 46.15384615384615,56.37272727272727 53.84615384615385,56.37272727272727 61.53846153846154,82.73636363636363 69.23076923076923,95.45454545454545 76.92307692307692,82.73636363636363 84.61538461538461,82.73636363636363 92.3076923076923,42.73636363636363 100,42.73636363636363" fill="none" stroke="white" vector-effect="non-scaling-stroke"></path></svg>
Any ideas what am I doing wrong or how to approach this better?

Categories

Resources