<div class="box">
<svg viewBox="0 0 236 200">
<g class="path" fill="none" stroke="#fff" stroke-miterlimit="10" stroke-width="1">
<path d="M0,0 C40,240 200,240 240,0" fill="none" stroke="#ffffff" stroke-dasharray="5 3"/>
</g>
</svg>
<div class="offset-path"></div>
</div>
<aside>
<div class="item">
<input type="checkbox" id="path-play-state"/>
<label for="path-play-state">Animate offset-distance</label>
</div>
<div class="item">
<label for="anchorX">anchorX</label>
<input type="range" id="anchorX" value="50" min="0" max="100"/>
<output id="outputX">50%</output>
</div>
<div class="item">
<label for="anchorY">anchorY</label>
<input type="range" id="anchorY" value="50" min="0" max="100"/>
<output id="outputY">50%</output>
</div>
</aside>
@import url('https://fonts.googleapis.com/css?family=Gochi+Hand');
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--offset: 0%;
--anchorX: 50%;
--anchorY: 50%;
}
body {
margin: 0;
padding: 0;
background-color: #291642;
font-family: 'Gochi Hand', sans-serif;
color: #fff;
font-size: 130%;
letter-spacing: 0.1rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
min-height: 100vh;
}
.box {
width: 240px;
height: 240px;
border: 1px dashed #f36;
margin-bottom: 2vh;
position: relative;
}
.offset-path {
width: 5vh;
height: 5vh;
border: 1px solid hsla(343,100%,58%,.3);
border-right: 5px solid hsl(343,100%,58%);
background: hsla(343,100%,58%,.3);
position: absolute;
offset-path: path('M0,0 C40,240 200,240 240,0');
offset-distance: var(--offset);
offset-anchor: var(--anchorX) var(--anchorY);
&.play {
animation: ani 4000ms linear alternate infinite;
}
&::after {
content: '';
position: absolute;
background: radial-gradient(circle at var(--anchorX) var(--anchorY), #fff 6px, transparent 3px) no-repeat;
width: 100%;
left: 0;
bottom: 0;
top: 0;
}
}
svg {
position: absolute;
opacity: .3;
}
@keyframes ani {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
aside {
display: flex;
align-items: center;
.item {
margin: 0 2vh;
display: flex;
align-items: center;
}
label {
display: flex;
align-items: center;
}
}
View Compiled
const toggle = document.querySelector('#path-play-state')
const aniEle = document.querySelector('.offset-path')
const anchorX = document.getElementById('anchorX')
const anchorY = document.getElementById('anchorY')
const outputx = document.getElementById('outputX')
const outputy = document.getElementById('outputY')
toggle.addEventListener('click', (e) => {
console.log(e.target.checked)
if (e.target.checked) {
aniEle.classList.add('play')
} else {
aniEle.classList.remove('play')
}
})
anchorX.addEventListener('input', (e) => {
console.log(e.currentTarget.value)
aniEle.style.setProperty('--anchorX', `${e.currentTarget.value}%`);
outputx.textContent = `${e.currentTarget.value}%`;
})
anchorY.addEventListener('input', (e) => {
console.log(e.currentTarget.value)
aniEle.style.setProperty('--anchorY', `${e.currentTarget.value}%`);
outputy.textContent = `${e.currentTarget.value}%`;
})
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.