问题
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 ?
回答1:
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>
来源:https://stackoverflow.com/questions/56704940/how-to-do-an-animated-dashed-svg-line