Skip to content

Instantly share code, notes, and snippets.

@rjygraham
Created July 14, 2022 22:20
Show Gist options
  • Save rjygraham/b8cf72d628931422f983719cf704f6b8 to your computer and use it in GitHub Desktop.
Save rjygraham/b8cf72d628931422f983719cf704f6b8 to your computer and use it in GitHub Desktop.
SVG animated glowing line
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
background-color: black;
}
</style>
</head>
<body>
<div style="position:absolute; top:0; right:0; width:100%; height:auto;" id="route">
<svg viewBox="0 0 334 1426" id="svgRoute" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
@keyframes flicker {
0% {
opacity: 1;
}
3% {
opacity: 0.4;
}
6% {
opacity: 1;
}
7% {
opacity: 0.4;
}
8% {
opacity: 1;
}
9% {
opacity: 0.4;
}
10% {
opacity: 1;
}
89% {
opacity: 1;
}
90% {
opacity: 0.4;
}
100% {
opacity: 0.4;
}
}
@keyframes glow-flicker {
0% {
opacity: .25;
}
15% {
opacity: .75;
}
30% {
opacity: 0;
}
50% {
opacity: 1;
}
70% {
opacity: 0;
}
85% {
opacity: .75;
}
100% {
opacity: 0;
}
}
#line-glow, #dot-glow {
animation: glow-flicker .75s infinite ease-in-out;
}
#line, #dot {
animation: flicker .75s infinite ease-in-out;
}
</style>
<defs>
<filter id="glow" width="200%" height="200%" x="-50%" y="-50%" filterUnits="objectBoundingBox">
<feOffset in="SourceAlpha" result="shadowOffsetOuter1" />
<feGaussianBlur in="shadowOffsetOuter1" result="shadowBlurOuter1" stdDeviation="5" />
<feColorMatrix in="shadowBlurOuter1" result="shadowMatrixOuter1" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0" />
<feOffset in="SourceAlpha" result="shadowOffsetOuter2" />
<feGaussianBlur in="shadowOffsetOuter2" result="shadowBlurOuter2" stdDeviation="7" />
<feColorMatrix in="shadowBlurOuter2" result="shadowMatrixOuter2" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.9 0" />
<feOffset in="SourceAlpha" result="shadowOffsetOuter3" />
<feGaussianBlur in="shadowOffsetOuter3" result="shadowBlurOuter3" stdDeviation="10" />
<feColorMatrix in="shadowBlurOuter3" result="shadowMatrixOuter3" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.8 0" />
<feOffset in="SourceAlpha" result="shadowOffsetOuter4" />
<feGaussianBlur in="shadowOffsetOuter4" result="shadowBlurOuter4" stdDeviation="1" />
<feColorMatrix in="shadowBlurOuter4" result="shadowMatrixOuter4" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.69678442 0" />
<feOffset in="SourceAlpha" result="shadowOffsetOuter5" />
<feGaussianBlur in="shadowOffsetOuter5" result="shadowBlurOuter5" stdDeviation="8" />
<feColorMatrix in="shadowBlurOuter5" result="shadowMatrixOuter5" values="0 0 0 0 0.314369351 0 0 0 0 0.8883757 0 0 0 0 0.759899616 0 0 0 0.649371603 0" />
<feMerge>
<feMergeNode in="shadowMatrixOuter1" />
<feMergeNode in="shadowMatrixOuter2" />
<feMergeNode in="shadowMatrixOuter3" />
<feMergeNode in="shadowMatrixOuter4" />
<feMergeNode in="shadowMatrixOuter5" />
</feMerge>
</filter>
<circle id="dot-template" r=".2" cy="-5" cx="0" />
<path id="path"
d="M170 19s18 32 18 57c0 48-40 51-40 72 0 22 43 31 43 44 0 10-9.4 10-10 23-.7 14 2.3 16 2.2 28-.17 12-14 24-21 32-6.5 7.2-17 15-20 23-2.4 6.8-3.5 23 12 29 16 5.7 32 10 37 24 5.2 13-7.4 26-17 33-9.2 6.6-30 20-26 30 3.5 9.9 27 6.2 27 24 0 18 8.8 13 8.8 24-11 24 16 50 13 71-.46 17-15 23-8.2 42-32 37 1.3 83 26 106 28 20-33 5.7-33 39 2.4 51-28 113-34 139-4.1 18-3.5 41 18 41 8.1-.2 14-6.5 15-14 .37-6.3-6.1-14-16-12-11 1.8-16 11-19 24-1.3 6.6-2.1 17-2.3 28-.43 29 14 36 19 39 2.6 1.8 19 8.8 19 17 10 18-41 7.8-35 28 .61 10 37 22 36 35 8.4 94-128 42-89 130 8.8 36-63 33-60 68-2.1 25 35 32 38 44" />
</defs>
<g id="schedule-location" fill="none" fill-rule="evenodd">
<g id="line">
<use id="line-glow" stroke="#000" filter="url(#glow)" xlink:href="#path" />
<use stroke="#FFF" stroke-width="0.2" xlink:href="#path" />
</g>
</g>
<g id="dot">
<use id="dot-glow" stroke="#000" filter="url(#glow)" xlink:href="#dot-template" />
<use stroke="#FFF" stroke-width="0.2" xlink:href="#dot-template" />
</g>
</svg>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js"
integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
<script>
$(document).ready(function () {
$(window).scroll(function () {
drawLine(path);
positionDot(dot, path);
});
var maxScrollTop = $(document).height() - $(window).height();
var path = document.getElementById('path');
var pathLength = path.getTotalLength();
var dot = document.getElementById("dot");
//path.setAttribute('class', 'pathVisible');
dot.setAttribute('class', 'dotVisible');
// Init positions.
drawLine(path);
positionDot(dot, path);
// Draw the line
function drawLine(path) {
var percentDone = $(window).scrollTop() / maxScrollTop;
var length = percentDone * pathLength;
path.style.strokeDasharray = [length, pathLength].join(' ');
}
// Draw the dot.
function positionDot(dot, path) {
// What percentage down the page are we?
var scrollPercentage = (document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
// Get the position of a point at <scrollPercentage> along the path.
var pt = path.getPointAtLength(scrollPercentage * pathLength);
var scrollY = window.scrollY || window.pageYOffset;
var maxScrollY = document.documentElement.scrollHeight - window.innerHeight;
// Calculate distance along the path the car should be for the current scroll amount
var dist = pathLength * scrollY / maxScrollY;
var pos = path.getPointAtLength(dist);
// Position the red dot at this point
dot.setAttribute("transform", "translate(" + pt.x + "," + (pt.y + 5) + ")");
};
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment