How to do an animated dashed svg line? - javascript

I've tried to do an animated dashed line in HTML (SVG) / CSS / JS.
This is my first svg animation... and clearly... I don't understand anything.
First of all, this is my dashed line :
<svg id="bf7de8ba-cf75-48ab-a36c-06f8d86635d5" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 690.814 824.302">
<defs>
<style>
.a00cb6af-c716-4d00-9962-797e598003da,
.a6fde9f6-9a2f-4715-ac34-678948a4d015,
.b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
fill:none;
stroke-miterlimit:10;
stroke-width:6px;
}
.a6fde9f6-9a2f-4715-ac34-678948a4d015 {
stroke:url(#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0);
}
.b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
stroke-dasharray:30.322 50.536;
stroke:url(#a958eb71-8928-4250-a898-e2a9df336375);
}
.a00cb6af-c716-4d00-9962-797e598003da {
stroke:url(#a8cb66bd-35fa-45ad-b9b6-1af210f764d2);
}
</style>
<linearGradient id="bef7cd12-3404-46dc-ac0f-c9d91ddd83d0" x1="60.835" y1="123.864" x2="751.668" y2="123.864" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ec6608"/>
<stop offset="0.494" stop-color="#c33089"/>
<stop offset="1" stop-color="#662483"/>
</linearGradient>
<linearGradient id="a958eb71-8928-4250-a898-e2a9df336375" x1="60.835" y1="541.828" x2="751.668" y2="541.828" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
<linearGradient id="a8cb66bd-35fa-45ad-b9b6-1af210f764d2" x1="60.835" y1="932.54" x2="751.668" y2="932.54" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
</defs>
<path class="a6fde9f6-9a2f-4715-ac34-678948a4d015" d="M748.213,116.426c.215,4.461.381,9.478.436,14.992" transform="translate(-60.835 -116.281)"/>
<path id="pathRecrut" class="b963f74d-80cb-4571-80bd-9cf5cd28cce2" d="M745.947,181.853c-3.573,34.83-7.4,65.457-20.713,85.466-36.276,54.511-150.309,41.2-247.4,29.872-73.484-8.575-74.824-17.343-139.4-21.446-87.16-5.538-141.016-8.96-191.49,24.51-48.083,31.886-87.4,93.472-82.723,159.319.847,11.934,4.189,59.01,39.83,91.915,35.144,32.448,81.33,32.315,131.744,32.171,53.366-.154,56.932-10.359,130.213-18.383,52.244-5.721,100.335-10.606,160.085,1.532,36.964,7.508,74.081,20.657,109.532,43.659,26.491,17.189,49.773,32.776,59.745,62.809,1.48,4.457,13.436,42.337-6.894,72.766-14.348,21.475-39.623,31.524-81.957,36.766-67.779,8.391-105.681-4.654-182.3-16.086-41.6-6.206-132.521-17.593-227.49-.766-22.971,4.071-60.931,12.4-91.149,42.894-7.9,7.968-23.347,23.951-29.872,49.787a99.225,99.225,0,0,0-1.1,42.916" transform="translate(-60.835 -116.281)"/>
<path class="a00cb6af-c716-4d00-9962-797e598003da" d="M81.983,925.674a117,117,0,0,0,6.74,13.39" transform="translate(-60.835 -116.281)"/>
</svg>
see on codepen : https://codepen.io/Unrillaz/pen/gNmgjW
I've made it with Illustrator (adobe).
So I've tried to animate this line an I've followed this tutorial fron CSS-TRICKS : https://css-tricks.com/scroll-drawing/
AND .... TADA ! What's I have :
// Get a reference to the <path>
var path = document.querySelector('#pathRecrut');
// Get length of path... ~577px in this case
var pathLength = path.getTotalLength();
// Make very long dashes (the length of the path itself)
path.style.strokeDasharray = pathLength + ' ' + pathLength;
// Offset the dashes so the it appears hidden entirely
path.style.strokeDashoffset = pathLength;
// Jake Archibald says so
// https://jakearchibald.com/2013/animated-line-drawing-svg/
path.getBoundingClientRect();
// When the page scrolls...
window.addEventListener("scroll", function(e) {
// What % down is it?
// https://stackoverflow.com/questions/2387136/cross-browser-method-to-determine-vertical-scroll-percentage-in-javascript/2387222#2387222
// Had to try three or four differnet methods here. Kind of a cross-browser nightmare.
var scrollPercentage = (document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
// Length to offset the dashes
var drawLength = pathLength * scrollPercentage;
// Draw in reverse
path.style.strokeDashoffset = pathLength - drawLength;
// When complete, remove the dash array, otherwise shape isn't quite sharp
// Accounts for fuzzy math
if (scrollPercentage >= 0.99) {
path.style.strokeDasharray = "none";
} else {
path.style.strokeDasharray = pathLength + ' ' + pathLength;
}
});
<svg id="bf7de8ba-cf75-48ab-a36c-06f8d86635d5" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 690.814 824.302">
<defs>
<style>
.a00cb6af-c716-4d00-9962-797e598003da,
.a6fde9f6-9a2f-4715-ac34-678948a4d015,
.b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
fill:none;
stroke-miterlimit:10;
stroke-width:6px;
}
.a6fde9f6-9a2f-4715-ac34-678948a4d015 {
stroke:url(#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0);
}
.b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
stroke-dasharray:30.322 50.536;
stroke:url(#a958eb71-8928-4250-a898-e2a9df336375);
}
.a00cb6af-c716-4d00-9962-797e598003da {
stroke:url(#a8cb66bd-35fa-45ad-b9b6-1af210f764d2);
}
</style>
<linearGradient id="bef7cd12-3404-46dc-ac0f-c9d91ddd83d0" x1="60.835" y1="123.864" x2="751.668" y2="123.864" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ec6608"/>
<stop offset="0.494" stop-color="#c33089"/>
<stop offset="1" stop-color="#662483"/>
</linearGradient>
<linearGradient id="a958eb71-8928-4250-a898-e2a9df336375" x1="60.835" y1="541.828" x2="751.668" y2="541.828" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
<linearGradient id="a8cb66bd-35fa-45ad-b9b6-1af210f764d2" x1="60.835" y1="932.54" x2="751.668" y2="932.54" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
</defs>
<path class="a6fde9f6-9a2f-4715-ac34-678948a4d015" d="M748.213,116.426c.215,4.461.381,9.478.436,14.992" transform="translate(-60.835 -116.281)"/>
<path id="pathRecrut" class="b963f74d-80cb-4571-80bd-9cf5cd28cce2" d="M745.947,181.853c-3.573,34.83-7.4,65.457-20.713,85.466-36.276,54.511-150.309,41.2-247.4,29.872-73.484-8.575-74.824-17.343-139.4-21.446-87.16-5.538-141.016-8.96-191.49,24.51-48.083,31.886-87.4,93.472-82.723,159.319.847,11.934,4.189,59.01,39.83,91.915,35.144,32.448,81.33,32.315,131.744,32.171,53.366-.154,56.932-10.359,130.213-18.383,52.244-5.721,100.335-10.606,160.085,1.532,36.964,7.508,74.081,20.657,109.532,43.659,26.491,17.189,49.773,32.776,59.745,62.809,1.48,4.457,13.436,42.337-6.894,72.766-14.348,21.475-39.623,31.524-81.957,36.766-67.779,8.391-105.681-4.654-182.3-16.086-41.6-6.206-132.521-17.593-227.49-.766-22.971,4.071-60.931,12.4-91.149,42.894-7.9,7.968-23.347,23.951-29.872,49.787a99.225,99.225,0,0,0-1.1,42.916" transform="translate(-60.835 -116.281)"/>
<path class="a00cb6af-c716-4d00-9962-797e598003da" d="M81.983,925.674a117,117,0,0,0,6.74,13.39" transform="translate(-60.835 -116.281)"/>
</svg>
see on codepen : https://codepen.io/Unrillaz/pen/ZdeezN
I don't understand why this line is solid when I animate it.
I want the same animation. A line which is filling itself when you scroll down but I want to keep it dashed. Do you think it's possible ?

The standard "line drawing" technique uses a changing dash length to simulate the drawing effect. So obviously, if your line already has a dash pattern, that technique won't work. Not directly at least.
The best solution to this is to apply a <mask> to the dashed line. The mask consists of a line that covers your original one (the dashed one). We then use the standard line drawing dash technique to animate the version of the line in the mask. Thus slowly unmasking/revealing the original dashed line.
// Get a reference to the <path>
var path = document.querySelector('#pathRecrut');
// Get length of path... ~577px in this case
var pathLength = path.getTotalLength();
// Make very long dashes (the length of the path itself)
path.style.strokeDasharray = pathLength + ' ' + pathLength;
// Offset the dashes so the it appears hidden entirely
path.style.strokeDashoffset = pathLength;
// When the page scrolls...
window.addEventListener("scroll", function(e) {
// What % down is it?
// https://stackoverflow.com/questions/2387136/cross-browser-method-to-determine-vertical-scroll-percentage-in-javascript/2387222#2387222
// Had to try three or four differnet methods here. Kind of a cross-browser nightmare.
var scrollPercentage = (document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
// Length to offset the dashes
var drawLength = pathLength * scrollPercentage;
// Draw in reverse
path.style.strokeDashoffset = pathLength - drawLength;
});
<svg id="bf7de8ba-cf75-48ab-a36c-06f8d86635d5" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 690.814 824.302">
<defs>
<style>
.a00cb6af-c716-4d00-9962-797e598003da,
.a6fde9f6-9a2f-4715-ac34-678948a4d015,
.b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
fill:none;
stroke-miterlimit:10;
stroke-width:6px;
}
.a6fde9f6-9a2f-4715-ac34-678948a4d015 {
stroke:url(#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0);
}
.b963f74d-80cb-4571-80bd-9cf5cd28cce2 {
stroke-dasharray:30.322 50.536;
stroke:url(#a958eb71-8928-4250-a898-e2a9df336375);
}
.a00cb6af-c716-4d00-9962-797e598003da {
stroke:url(#a8cb66bd-35fa-45ad-b9b6-1af210f764d2);
}
</style>
<linearGradient id="bef7cd12-3404-46dc-ac0f-c9d91ddd83d0" x1="60.835" y1="123.864" x2="751.668" y2="123.864" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ec6608"/>
<stop offset="0.494" stop-color="#c33089"/>
<stop offset="1" stop-color="#662483"/>
</linearGradient>
<linearGradient id="a958eb71-8928-4250-a898-e2a9df336375" x1="60.835" y1="541.828" x2="751.668" y2="541.828" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
<linearGradient id="a8cb66bd-35fa-45ad-b9b6-1af210f764d2" x1="60.835" y1="932.54" x2="751.668" y2="932.54" xlink:href="#bef7cd12-3404-46dc-ac0f-c9d91ddd83d0"/>
<mask id="linemask">
<path id="pathRecrut" fill="none" stroke="white" stroke-width="10" d="M745.947,181.853c-3.573,34.83-7.4,65.457-20.713,85.466-36.276,54.511-150.309,41.2-247.4,29.872-73.484-8.575-74.824-17.343-139.4-21.446-87.16-5.538-141.016-8.96-191.49,24.51-48.083,31.886-87.4,93.472-82.723,159.319.847,11.934,4.189,59.01,39.83,91.915,35.144,32.448,81.33,32.315,131.744,32.171,53.366-.154,56.932-10.359,130.213-18.383,52.244-5.721,100.335-10.606,160.085,1.532,36.964,7.508,74.081,20.657,109.532,43.659,26.491,17.189,49.773,32.776,59.745,62.809,1.48,4.457,13.436,42.337-6.894,72.766-14.348,21.475-39.623,31.524-81.957,36.766-67.779,8.391-105.681-4.654-182.3-16.086-41.6-6.206-132.521-17.593-227.49-.766-22.971,4.071-60.931,12.4-91.149,42.894-7.9,7.968-23.347,23.951-29.872,49.787a99.225,99.225,0,0,0-1.1,42.916"/>
</mask>
</defs>
<path class="a6fde9f6-9a2f-4715-ac34-678948a4d015" d="M748.213,116.426c.215,4.461.381,9.478.436,14.992" transform="translate(-60.835 -116.281)"/>
<path class="b963f74d-80cb-4571-80bd-9cf5cd28cce2" d="M745.947,181.853c-3.573,34.83-7.4,65.457-20.713,85.466-36.276,54.511-150.309,41.2-247.4,29.872-73.484-8.575-74.824-17.343-139.4-21.446-87.16-5.538-141.016-8.96-191.49,24.51-48.083,31.886-87.4,93.472-82.723,159.319.847,11.934,4.189,59.01,39.83,91.915,35.144,32.448,81.33,32.315,131.744,32.171,53.366-.154,56.932-10.359,130.213-18.383,52.244-5.721,100.335-10.606,160.085,1.532,36.964,7.508,74.081,20.657,109.532,43.659,26.491,17.189,49.773,32.776,59.745,62.809,1.48,4.457,13.436,42.337-6.894,72.766-14.348,21.475-39.623,31.524-81.957,36.766-67.779,8.391-105.681-4.654-182.3-16.086-41.6-6.206-132.521-17.593-227.49-.766-22.971,4.071-60.931,12.4-91.149,42.894-7.9,7.968-23.347,23.951-29.872,49.787a99.225,99.225,0,0,0-1.1,42.916" transform="translate(-60.835 -116.281)" mask="url(#linemask)"/>
<path class="a00cb6af-c716-4d00-9962-797e598003da" d="M81.983,925.674a117,117,0,0,0,6.74,13.39" transform="translate(-60.835 -116.281)"/>
</svg>

Related

Animation is too choppy when animating inline SVG with javascript according to the window's scrollbar position

I am trying to use JavaScript to retrieve inline SVG elements and set their transform attributes in order to translate them in response to scrolling down the screen. I am using window.requestAnimationFrame() in order to do so.
The animation is very choppy so far and I haven't found a solution to remedy this yet. Any suggestions??
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="margin: 0px">
<svg viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="">
<g id="AbstractBackground">
<rect id="backgroundRect" width="1440" height="1024" fill="#BDD8DE"/>
<rect id="greenCircleGrad" x="-338" y="-444" width="1440" height="1440" fill="url(#paint0_radial_2005_534273)"/>
<path id="wave1" d="M516 228.015C212 228.015 74 34.0154 -170 36.0154C-414 38.0154 -634 228.015 -634 228.015V988.015H1692V200.015C1692 200.015 1459 36.0154 1208 36.0154C957 36.0153 820 228.015 516 228.015Z" fill="#60AB9E"/>
<rect id="turquoiseCircleGrad" x="508" y="-208" width="1440" height="1440" fill="url(#paint1_radial_2005_534273)"/>
<path id="wave2" d="M872 553.015C568 553.015 430 359.015 186 361.015C-58 363.015 -278 553.015 -278 553.015V1313.02H2048V525.015C2048 525.015 1815 361.015 1564 361.015C1313 361.015 1176 553.015 872 553.015Z" fill="#77ABBB"/>
<rect id="blueCircleGrad" x="-128" y="-42" width="1440" height="1440" fill="url(#paint2_radial_2005_534273)"/>
<path id="wave3" d="M376 853.015C72 853.015 -66 659.015 -310 661.015C-554 663.015 -774 853.015 -774 853.015V1613.02H1552V825.015C1552 825.015 1319 661.015 1068 661.015C817 661.015 680 853.015 376 853.015Z" fill="#C6DAD4"/>
<rect id="blackCircleGrad" x="207" y="221" width="1753" height="1753" fill="url(#paint3_radial_2005_534273)"/>
<defs>
<radialGradient id="paint0_radial_2005_534273" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(382 276) rotate(90) scale(720)">
<stop stop-color="#7B3A5D" stop-opacity="0.67"/>
<stop stop-color="#6DA060" stop-opacity="0.83"/>
<stop offset="0.442708" stop-color="#6DA360" stop-opacity="0.71"/>
<stop offset="1" stop-color="#6CA95D" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint1_radial_2005_534273" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(1228 512) rotate(90) scale(720)">
<stop stop-color="#71EFE3"/>
<stop stop-color="#71EFE3"/>
<stop offset="1" stop-color="#71EFE3" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint2_radial_2005_534273" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(592 678) rotate(90) scale(720)">
<stop stop-color="#8A78B1"/>
<stop stop-color="#58B4C8"/>
<stop offset="1" stop-color="#67C0D4" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint3_radial_2005_534273" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(1083.5 1097.5) rotate(90) scale(876.5)">
<stop stop-color="#8A78B1" stop-opacity="0.73"/>
<stop stop-color="#20665E" stop-opacity="0.53"/>
<stop offset="0.713542" stop-color="#2F9262" stop-opacity="0"/>
</radialGradient>
</defs>
</svg>
</body>
<script>
// IDs of SVG elements in the SVG background that animate when scrolling down
const SLO_SCROLL_TRANSFORM_IDS = ["turquoiseCircleGrad","wave1"];
const MED_SCROLL_TRANSFORM_IDS = ["blueCircleGrad","wave2"];
const FST_SCROLL_TRANSFORM_IDS = ["blackCircleGrad","wave3"];
const [SLO_SCROLL_DIST, MED_SCROLL_DIST, FST_SCROLL_DIST] = [50, 100, 200];
/**
* applies css translate transformation to an svg element
* #param id svg element id to apply transformation to
* #param distance vertical distance to translate svg element
*/
function translateSvgVertically(id, distance) {
document.querySelector("svg #"+id).setAttribute('transform',"translate(0,"+distance+")");
}
let h = document.documentElement;
let b = document.body;
/**
* returns how much of the page has been scrolled through as a decimal
* #returns {number} returns a decimcal [0,1]
*/
function getScrollFraction() {
return (h['scrollTop']||b['scrollTop']) / ((h['scrollHeight']||b['scrollHeight']) - h.clientHeight);
}
let lastKnownScrollFraction = 0;
let ticking = false;
document.addEventListener("scroll", (e) => {
lastKnownScrollFraction = getScrollFraction();
if (!ticking) {
window.requestAnimationFrame(function() {
SLO_SCROLL_TRANSFORM_IDS.forEach((id) => translateSvgVertically(id, SLO_SCROLL_DIST*lastKnownScrollFraction));
MED_SCROLL_TRANSFORM_IDS.forEach((id) => translateSvgVertically(id, MED_SCROLL_DIST*lastKnownScrollFraction));
FST_SCROLL_TRANSFORM_IDS.forEach((id) => translateSvgVertically(id, FST_SCROLL_DIST*lastKnownScrollFraction));
ticking = false;
});
ticking = true;
}
});
</script>
</html>

how can i make a svg ball roll to the last click

I am trying to make a game like online bowling, and I cannot get the ball to launch correctly in js. when I click on it the ball goes the wrong way or off the screen. I have been trying to fix this for a while.
var xup
var yup
var x = 50;
var y = 95
document.onmouseup = function(e){
xup = -(e.pageX/screen.width)
yup = -(e.pageY/screen.height)
let d = setInterval(function(){
x += xup
y += yup
document.getElementById("player").innerHTML = '<circle id="ball" cx="'+x+'%" cy="'+y+'%" r="1%" fill="url(#ball)" />'
if(y<=20){
d=null
}
},10)
}
<svg style='position: absolute;left: 0;top: 1%;' width='100%' height='100%'>
<defs>
<radialGradient id="ball" cx="50%" cy="25%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:#ff00ff;stop-opacity:1" />
<stop offset="100%" style="stop-color:#800080;stop-opacity:1" />
</radialGradient>
</defs>
<g id="player">
<circle id="ball" cx="50%" cy="95%" r="1%" fill="url(#ball)" />
</g>
</svg>

SVG - Obtaining ordered list of IDs that appear under mouse/touch hove/click/tap in an SVG

I am trying to extract all layer/group ID names and metadata from the top layer as well as all layers underneath it.
Desired result: Get a list of IDs and Group IDs from an SVG.
In example SVG would see, if hovering over the center of the image, something like this:
Poly 1
Star
Group Begin: Bright Shapes
Group Begin: Gradient Shapes
Gradient Poly Small
Gradient Poly Large
Gradient Star
End Group: Gradient Shapes
Pink Ellipse
Green Square
End Group: Bright Shapes
Ellipse 2
I've also looked at CSS pointer-events.. but that seems limited to extracting from 1 layer.
Modified from: Determine which element the mouse pointer is on top of in Javascript
http://jsfiddle.net/coq4eg0d/1/
setInterval(function(){
var element = $(':hover');
if(element.length)
{
var domElement = element[element.length - 1];
var tagName = domElement.tagName;
var id = domElement.id ? ' id="' + domElement.id + '"' : "";
document.getElementById('test').innerHTML =
"hover: <" + tagName.toLowerCase() + id + ">";
}
}, 100);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="test"></div>
<svg version="1.1" id="Shapes" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 368 373" style="enable-background:new 0 0 368 373;" xml:space="preserve">
<style type="text/css">
.st0{stroke:#FFFFFF;stroke-miterlimit:10;}
.st1{fill:#4BB749;stroke:#1F451F;stroke-miterlimit:10;}
.st2{fill:#CB3694;stroke:#FFFFFF;stroke-miterlimit:10;}
.st3{fill:url(#Gradient_Star_1_);stroke:#FFFFFF;stroke-miterlimit:10;}
.st4{fill:url(#Gradient_Poly_Large_1_);stroke:#FFFFFF;stroke-miterlimit:10;}
.st5{fill:url(#Gradient_Poly_Small_1_);stroke:#FFFFFF;stroke-miterlimit:10;}
</style>
<ellipse id="Ellipse_2" class="st0" cx="261" cy="212" rx="94" ry="79"/>
<g id="Bright_Shapes">
<rect id="Green_Square" x="98" y="161.22" class="st1" width="184" height="174.5"/>
<ellipse id="Pink_Ellipse" class="st2" cx="115.59" cy="268.59" rx="94" ry="79"/>
<g id="Gradient_Shapes">
<radialGradient id="Gradient_Star_1_" cx="115.5932" cy="189.5899" r="147.9309" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#1C75BC"/>
</radialGradient>
<polygon id="Gradient_Star" class="st3" points="109.37,335.15 68.3,238.41 -34.67,217.41 44.63,148.46 32.79,44.03 122.87,98.15
218.53,54.61 194.9,157.01 265.86,234.53 161.17,243.7 "/>
<radialGradient id="Gradient_Poly_Large_1_" cx="167" cy="171" r="88.1134" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#1C75BC"/>
</radialGradient>
<polygon id="Gradient_Poly_Large" class="st4" points="234,233 146.81,260.02 79.81,198.02 100,109 187.19,81.98 254.19,143.98
"/>
<radialGradient id="Gradient_Poly_Small_1_" cx="209.5932" cy="248.4668" r="30.3834" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#1C75BC"/>
</radialGradient>
<polygon id="Gradient_Poly_Small" class="st5" points="236.59,265.88 208.02,280.55 181.02,263.14 182.59,231.06 211.17,216.38
238.17,233.79 "/>
</g>
</g>
<g id="Pointed_Dark_Shapes">
<polygon id="Star" class="st0" points="249,229 142.84,198.45 57.49,268.59 53.74,158.19 -39.34,98.69 64.5,61 92.32,-45.91
160.25,41.21 270.53,34.63 208.67,126.16 "/>
<polygon id="Poly1" class="st0" points="220,251 124.55,266.33 63.55,191.33 98,101 193.45,85.67 254.45,160.67 "/>
</g>
</svg>
One way to find all elements at a location is to call elementFromPoint() to find the topmost element, and then use the fact that..
Elements with pointer-events set to none will be ignored, and the element below it will be returned.
So, once you've found an element, set its pointer-events: none and then call elementFromPoint() again to find the next element. Repeat until you reach the main SVG element:
function hitTest(e) {
const x = e.clientX,
y = e.clientY,
elms = [];
let elm;
while(true) {
elm = document.elementFromPoint(x, y);
if(!svg.contains(elm)) {
break;
}
elms.push(elm);
//Hide the element from the next round of `elementFromPoint()`:
elm.style.pointerEvents = 'none';
}
output.textContent = elms.map(printElement).join(' ');
//Cleanup:
elms.forEach(elm => elm.style.pointerEvents = '');
}
http://jsfiddle.net/r9k1bgnu/

svg gradient fill animation percentage jquery

I'm trying to get some svg animation with jquery, for each class "check" i need summs percentage offset for gradient, and when this class is remove need reduce percentage offset gradient. This all need animation down up when class added, and up down when class removed.
So i got, gradient and get offset to 5% percentage. Trying to get array but stuck. Think about get all elements with class "check" and try to summs for each class.
var firstStop = document.getElementById('F1gst1');
percentage = '5%'; firstStop.setAttribute('offset',percentage);
$(".analysis-li").click(function(){
$(this).toggleClass("check");
if($(this).hasClass('check')){
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="analysis-li"></li>
<li class="analysis-li"></li>
<li class="analysis-li"></li>
<li class="list analysis-li"></li>
<li class="analysis-li"></li>
<li class="list analysis-li"></li>
<li class="analysis-li" ></li>
<svg class="thermometr" id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44.3 333.8">
<linearGradient y2="0%" x2="0%" y1="100%" x1="0%" id="F1g"><stop stop-color="#00FF00" offset="0%" id="F1gst1"/><stop stop-color="#FFFFFF" offset="0%" id="F1gst2"/></linearGradient>
<path fill="url(#F1g)" class="st0" d="M30.5 297.5V4.6c0-2.5-2.1-4.6-4.6-4.6-2.5 0-4.6 2.1-4.6 4.6v292.9c-7.9 2-13.8 9.2-13.8 17.8 0 10.2 8.2 18.4 18.4 18.4s18.4-8.2 18.4-18.4c0-8.5-5.9-15.7-13.8-17.8"/><path fill="url(#F1g)" class="st0" d="M9 290.2h7.5v.5H9zM9 284.3h7.5v.6H9zM9 278.4h7.5v.5H9zM9 272.5h7.5v.6H9zM0 266.6h16.5v.6H0zM9 260.7h7.5v.5H9zM9 254.8h7.5v.6H9zM9 248.9h7.5v.5H9zM9 243h7.5v.6H9zM0 237.1h16.5v.6H0zM9 231.3h7.5v.5H9zM9 225.4h7.5v.6H9zM9 219.5h7.5v.6H9zM9 213.6h7.5v.6H9zM0 207.7h16.5v.6H0zM9 201.8h7.5v.6H9zM9 195.9h7.5v.6H9zM9 190h7.5v.6H9zM9 184.1h7.5v.5H9zM0 178.2h16.5v.6H0zM9 172.3h7.5v.6H9zM9 166.4h7.5v.5H9zM9 160.5h7.5v.6H9zM9 154.7h7.5v.6H9zM0 148.8h16.5v.6H0zM9 142.9h7.5v.6H9zM9 137h7.5v.5H9zM9 131.1h7.5v.5H9zM9 125.2h7.5v.6H9zM0 119.3h16.5v.5H0zM9 113.4h7.5v.6H9zM9 107.5h7.5v.6H9zM9 101.6h7.5v.5H9zM9 95.7h7.5v.6H9zM0 89.8h16.5v.6H0zM9 83.9h7.5v.6H9zM9 78.1h7.5v.6H9zM9 72.2h7.5v.6H9zM9 66.3h7.5v.6H9zM0 60.4h16.5v.6H0zM9 54.8h7.5v.6H9zM9 48.9h7.5v.6H9zM9 43h7.5v.5H9zM9 37.1h7.5v.6H9zM0 31.2h16.5v.5H0zM9 26h7.5v.6H9zM9 20.1h7.5v.5H9zM9 14.2h7.5v.6H9zM9 8.3h7.5v.6H9zM0 2.4h16.5V3H0z"/>
</svg>
This is how I would do it. In order to animate the gradient I'm using requestAnimationFrame. I'm animating the second stop offset between 10% and 100% but you can choose the values you want.
Please read the comments in the code.
// the second stop
let laststop = document.getElementById('F1gst2');
// a variable used to toggle the animation
let n = 0;
// the target value of the offset attribute
let target;
// the actual value of the offset attribute
let val = 10;
//the request animation frame id
let rid = null;
$(".analysis-li").click(function(){
n++;
// set the target value
if(n%2 == 1){
target = 100;
}else{target = 10}
// if there is an animation stop it
if(rid){cancelAnimationFrame(rid); rid="null"}
// call the frame function
frame()
});
function frame(){
rid = requestAnimationFrame(frame);
//the distance between the value and the target value
dist = target - val;
//increase the value
val += dist/10;
// set the offset value
laststop.setAttributeNS(null,"offset",`${val}%`)
}
svg{border:1px solid; width:30px}
path{stroke:black;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="analysis-li">click here</p>
<svg class="thermometr" id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44.3 333.8" >
<linearGradient y2="0%" x2="0%" y1="100%" x1="0%" id="F1g">
<stop stop-color="#00FF00" offset="0%" id="F1gst1"/>
<stop stop-color="#FFFFFF" offset="10%" id="F1gst2"/>
</linearGradient>
<path fill="url(#F1g)" class="st0" d="M30.5 297.5V4.6c0-2.5-2.1-4.6-4.6-4.6-2.5 0-4.6 2.1-4.6 4.6v292.9c-7.9 2-13.8 9.2-13.8 17.8 0 10.2 8.2 18.4 18.4 18.4s18.4-8.2 18.4-18.4c0-8.5-5.9-15.7-13.8-17.8"/>
<path fill="url(#F1g)" class="st0" d="M9 290.2h7.5v.5H9zM9 284.3h7.5v.6H9zM9 278.4h7.5v.5H9zM9 272.5h7.5v.6H9zM0 266.6h16.5v.6H0zM9 260.7h7.5v.5H9zM9 254.8h7.5v.6H9zM9 248.9h7.5v.5H9zM9 243h7.5v.6H9zM0 237.1h16.5v.6H0zM9 231.3h7.5v.5H9zM9 225.4h7.5v.6H9zM9 219.5h7.5v.6H9zM9 213.6h7.5v.6H9zM0 207.7h16.5v.6H0zM9 201.8h7.5v.6H9zM9 195.9h7.5v.6H9zM9 190h7.5v.6H9zM9 184.1h7.5v.5H9zM0 178.2h16.5v.6H0zM9 172.3h7.5v.6H9zM9 166.4h7.5v.5H9zM9 160.5h7.5v.6H9zM9 154.7h7.5v.6H9zM0 148.8h16.5v.6H0zM9 142.9h7.5v.6H9zM9 137h7.5v.5H9zM9 131.1h7.5v.5H9zM9 125.2h7.5v.6H9zM0 119.3h16.5v.5H0zM9 113.4h7.5v.6H9zM9 107.5h7.5v.6H9zM9 101.6h7.5v.5H9zM9 95.7h7.5v.6H9zM0 89.8h16.5v.6H0zM9 83.9h7.5v.6H9zM9 78.1h7.5v.6H9zM9 72.2h7.5v.6H9zM9 66.3h7.5v.6H9zM0 60.4h16.5v.6H0zM9 54.8h7.5v.6H9zM9 48.9h7.5v.6H9zM9 43h7.5v.5H9zM9 37.1h7.5v.6H9zM0 31.2h16.5v.5H0zM9 26h7.5v.6H9zM9 20.1h7.5v.5H9zM9 14.2h7.5v.6H9zM9 8.3h7.5v.6H9zM0 2.4h16.5V3H0z"/>
</svg>
SVG created programmicaly, only one shape is translated by incoming value:
let path = (y, d, extra) => `<path d="${d}" transform="translate(0,${y})" ${extra||''}></path>`
let multi = (count, html) => Array(count).fill(0).map((e, i) => html(i)).join('');
let toggle = el => el.classList.toggle('on') |
rect.setAttribute('y', 14.6*(7-document.querySelectorAll("path.on").length)+8)
scale.innerHTML = multi(10, i => path(i*10, 'M60,10h10M65,12h5M65,14h5M65,16h5M65,18h5'));
checks.innerHTML = multi(7, i => path(i*12, 'M10,10v8h8v-8z', 'class="on" onclick="toggle(this)"') +
path(i*12, 'M12,14l2.2,2l2.2,-4'))
g#scale path {
stroke: white;
stroke-width: 0.7;
}
#checks {
position: absolute;
top: 20px;
left: 20px;
}
#checks path {
fill: none;
pointer-events: all;
stroke: #f5b53a;
cursor:pointer;
stroke-linejoin:round;
}
#checks path.on + path {
opacity:1;
}
#checks path:nth-child(2n) {
opacity: 0;
pointer-events: none;
transition: 0.5s;
stroke: white;
}
<svg viewbox="0 0 135 135" height="90vh" style="background-color:purple">
<defs><mask id="termometer">
<path d="M80,10v100" stroke="white" stroke-width="5" stroke-linecap="round"></path>
<circle r="10" cy="120" cx="80" fill="white"></circle>
<g id="scale"></g>
</mask></defs>
<rect width="130" height="130" mask="url(#termometer)" fill="white"></rect>
<rect id="rect" style="transition:1s" y="8" width="130" height="130"
mask="url(#termometer)" fill="#f5b53a"></rect>
<g id="checks"></g>
</svg>

SVG LinearGradient - How to fade from bottom to top?

New to working with SVG. I have a working demo that has a linear gradient fade from left to right on the x axis, however I'm trying to get the same affect going from bottom to top on the y axis. Tried several different ways but can't get it to work the same.
https://codepen.io/joshuaeelee/pen/bqYmEG
HTML
<div class="share">
<ul>
<li>
<svg class="svg" style="width:100%;height:100%;position:fixed;top:0;bottom:0;left:0;">
<defs>
<linearGradient id="gradient-0">
<stop offset="0.8" stop-color="#fff"/>
<stop offset="1" stop-color="#000"/>
</linearGradient>
<mask id="gradient-mask-0" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<rect class="js-rect" x="-2" y="0" width="2" height="1" fill="url(#gradient-0)" />
</mask>
</defs>
<image class="js-images" x="0" y="0" width="100%" height="100%" xlink:href="http://68.media.tumblr.com/ef71091b57992c63cd6b6371160694b7/tumblr_o9c283SMGZ1st5lhmo1_1280.jpg" / mask="url(#gradient-mask-0)" preserveAspectRatio="xMidYMid slice">
</svg>
</li>
</ul>
JS - Using TweenMax to change attribute on Rect
const tl = new TimelineMax()
let firstRect = document.querySelector('.js-rect')
tl.to(firstRect, 5, {
attr: {
x: 0
}
})
You'd need to specify x2 and y2 values on the linearGradient element e.g.
<linearGradient id="gradient-0" x2="0%" y2="100%">
The default values are x2="100%" and y2="0%" which produce a horizontal gradient.
I guess another option would be to use a gradientTransform to rotate the gradient but the solution I've illustrated is simpler given your use case.

Categories

Resources