.container
svg
path
.element
View Compiled
:root {
--size: 75;
}
* {
box-sizing: border-box;
}
body {
display: -webkit-box;
display: flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
min-height: 100vh;
background: #ddd;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
}
@media (prefers-color-scheme: dark) {
body {
background: #222;
}
}
.container {
position: relative;
height: calc(var(--size) * 1vmin);
width: calc(var(--size) * 1vmin);
border: 2px solid #222;
}
@media (prefers-color-scheme: dark) {
.container {
border: 2px solid #ddd;
}
}
.element {
height: 40px;
width: 40px;
background: rgba(128,191,255,0.5);
border: 2px #80bfff solid;
position: absolute;
top: 0%;
left: 0%;
offset-path: path(var(--path));
-webkit-animation: travel 2s infinite alternate linear;
animation: travel 2s infinite alternate linear;
}
svg {
position: absolute;
height: calc(var(--size) * 1vmin);
opacity: 0.5;
width: calc(var(--size) * 1vmin);
}
svg path {
fill: none;
stroke-width: 4px;
stroke: #222;
}
@media (prefers-color-scheme: dark) {
svg path {
stroke: #ddd;
}
}
@-webkit-keyframes travel {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
@keyframes travel {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
const { d3 } = window
const POINTS = [
[0, 0],
[5, -5],
[10, 0],
[15, 5],
[20, 0]
]
const CONTAINER = document.querySelector('.container')
const PADDING = 40
const assignPath = () => {
const { height: size } = CONTAINER.getBoundingClientRect()
// Create an X scale
const xScale = d3.scaleLinear().domain([0, 20]).range([PADDING, size - PADDING])
// Create a Y scale
const yScale = d3.scaleLinear().domain([-5, 5]).range([PADDING, size - PADDING])
// Map the POINTS using our scales
const SCALED_POINTS = POINTS.map(POINT => [xScale(POINT[0]), yScale(POINT[1])])
// Generate a path string with our points
const LINE = d3.line().curve(d3.curveBasis)(SCALED_POINTS)
// Assign attributes and path values
d3.select('svg')
.attr('viewBox', `0 0 ${size} ${size}`)
d3.select('path')
.attr('d', `${LINE}`)
// Assign path to animated element
document.querySelector('.element').style.setProperty('--path', `"${LINE}"`)
}
assignPath()
window.addEventListener('resize', assignPath)
View Compiled
This Pen doesn't use any external CSS resources.