I have an element bordered with an Svg:
.element-bordered-with-svg {
border-image-source: url('images/border.svg');
[....]
}
Inside the border.svg there is a Css animation (defined in the <style> tag), like so:
<svg class="svg-frame-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 337 198">
<style>
.svg-frame-1:hover > path {
animation-play-state: running;
}
path {
stroke:#BEA757;
fill-opacity:0;
stroke-width:1;
stroke-dasharray: 1948;
stroke-dashoffset:1948;
animation-name: dash1;
animation-duration: 2s;
animation-fill-mode: forwards;
animation-delay: 2s;
animation-play-state: paused;
}
@keyframes dash1 {
0% { stroke-dashoffset:1948;}
100%{stroke-dashoffset:0;}
}
</style>
[...]
</svg>
I would like to start the animation only when I hover the .element-bordered-with-svg element.
Of course, because it is not inlined, the <svg> knows nothing about the elements of the main DOM and vice versa.
Is there a possible solution, perhaps in Javascript, to this problem?
EDITED: following the advice of @Danny '365CSI' Engelman in the comments I've tried with this solution (see the snippet):
function docReady(fn) {
// see if DOM is already available
if (
document.readyState === 'complete' ||
document.readyState === 'interactive'
) {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1');
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
function transformInDataUri(id) {
var svgText = new XMLSerializer().serializeToString(
document.getElementById(id),
);
var raw = svgText;
var encoded = raw.replace(/\s+/g, ' ');
// According to Taylor Hunt, lowercase gzips better ... my tiny test confirms this
encoded = replaceAll(encoded, '%', '%25');
encoded = replaceAll(encoded, '> <', '><'); // normalise spaces elements
encoded = replaceAll(encoded, '; }', ';}'); // normalise spaces css
encoded = replaceAll(encoded, '<', '%3c');
encoded = replaceAll(encoded, '>', '%3e');
encoded = replaceAll(encoded, '"', "'");
encoded = replaceAll(encoded, '#', '%23'); // needed for ie and firefox
encoded = replaceAll(encoded, '{', '%7b');
encoded = replaceAll(encoded, '}', '%7d');
encoded = replaceAll(encoded, '|', '%7c');
encoded = replaceAll(encoded, '^', '%5e');
encoded = replaceAll(encoded, '`', '%60');
encoded = replaceAll(encoded, '@', '%40');
var uri = 'url("data:image/svg+xml;charset=UTF-8,' + encoded + '")';
return uri;
}
docReady(function () {
var svgAsBorderSelector = 'svg-as-border';
var svg = document.getElementById(svgAsBorderSelector);
var svgAnimatedSelectors = '.path-1, .path-2, .path-3';
var svgElementsToAnimate = svg.querySelectorAll(svgAnimatedSelectors);
let divToBorderWithAnimatedSvg = document.querySelector('.frame-1');
divToBorderWithAnimatedSvg.style.borderImageSource = transformInDataUri(
svgAsBorderSelector,
);
divToBorderWithAnimatedSvg.addEventListener('mouseenter', (e) => {
for (var i = 0, max = svgElementsToAnimate.length; i < max; i++) {
svgElementsToAnimate[i].style.animationPlayState = 'running';
}
divToBorderWithAnimatedSvg.style.borderImageSource = transformInDataUri(
svgAsBorderSelector,
);
});
divToBorderWithAnimatedSvg.addEventListener('mouseleave', (e) => {
for (var i = 0, max = svgElementsToAnimate.length; i < max; i++) {
svgElementsToAnimate[i].style.animationPlayState = 'paused';
}
divToBorderWithAnimatedSvg.style.borderImageSource = transformInDataUri(
svgAsBorderSelector,
);
});
});
.frame-1 {
border: 22px solid;
border-image-slice: 41;
border-image-width: 32px;
border-image-outset: 0;
border-image-repeat: stretch;
}
.blockquote-container blockquote, .blockquote-container blockquote p {
color: #a17c4a;
}
.blockquote-container blockquote {
padding: .5em;
}
<div class="blockquote-container">
<blockquote class="frame-1">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec placerat ex enim, nec tempus nisl commodo a. Nullam eu odio ut neque interdum mollis quis ac velit. Etiam pulvinar aliquam auctor.</p>
</blockquote>
</div>
<svg style="display:none" id='svg-as-border' class='svg-frame-1' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 337 198'>
<g fill='none' fill-rule='evenodd'>
<style>
.path-1 {
stroke: #BEA757;
fill-opacity: 0;
stroke-width: 1;
stroke-dasharray: 1948;
stroke-dashoffset: 1948;
animation-name: dash1, fill;
animation-duration: 2s, 1s;
animation-fill-mode: forwards;
animation-delay: 0s, 0s;
animation-play-state: paused, paused;
}
.path-2 {
stroke: #BEA757;
fill-opacity: 0;
stroke-width: 1;
stroke-dasharray: 1878;
stroke-dashoffset: 1878;
animation-name: dash2, fill;
animation-duration: 4s, 1s;
animation-fill-mode: forwards;
animation-delay: 0s, 2.5s;
animation-play-state: paused, paused;
}
.path-3 {
stroke: #BEA757;
fill-opacity: 0;
stroke-width: 1;
stroke-dasharray: 2306;
stroke-dashoffset: 2306;
animation-name: dash3, fill;
animation-duration: 3s, 1s;
animation-fill-mode: forwards;
animation-delay: 1s, 2.5s;
animation-play-state: paused, paused;
}
@keyframes dash1 {
0% {
stroke-dashoffset: 1948;
}
100% {
stroke-dashoffset: 0;
}
}
@keyframes dash2 {
0% {
stroke-dashoffset: 1878;
}
100% {
stroke-dashoffset: 0;
}
}
@keyframes dash3 {
0% {
stroke-dashoffset: 2306;
}
100% {
stroke-dashoffset: 0;
}
}
@keyframes fill {
80% {
fill-opacity: 0;
}
100% {
fill-opacity: 1;
}
}
</style>
<path class='path-1' fill='#BEA757'
d='M22.68,176.6 L315.68,176.6 L315.68,22.6 L22.68,22.6 L22.68,176.6 Z M331.596839,180.6 L332.68,180.6 L332.68,193.6 L319.68,193.6 L319.68,180.6 L331.596839,180.6 Z M18.68,191.363552 L18.68,193.6 L5.68,193.6 L5.68,180.6 L18.68,180.6 L18.68,191.363552 Z M9.65296139,18.6 L5.68,18.6 L5.68,5.6 L18.68,5.6 L18.68,18.6 L9.65296139,18.6 Z M319.68,12.191199 L319.68,5.6 L332.68,5.6 L332.68,18.6 L319.68,18.6 L319.68,12.191199 Z M331.333807,22.158844 L336.68,22.158844 L336.68,0.6 L315.049474,0.6 L315.049474,17.9061919 L22.3105259,17.9061919 L22.3105259,0.6 L0.68,0.6 L0.68,22.158844 L18.0579387,22.158844 L18.0579387,176.041156 L0.68,176.041156 L0.68,197.6 L22.3105259,197.6 L22.3105259,180.293808 L315.049474,180.293808 L315.049474,197.6 L336.68,197.6 L336.68,176.041156 L319.304352,176.041156 L319.304352,22.158844 L331.333807,22.158844 L331.333807,22.158844 Z' />
<path class='path-2' fill='#BEA757'
d='M31.4211018,184.6 L305.940979,184.6 C309.012635,176.424701 315.497242,169.940127 323.68,166.857774 L323.68,31.3422262 C315.497242,28.2598727 309.012635,21.7752988 305.940979,13.6 L31.4211018,13.6 C28.3473648,21.7752988 21.8648391,28.2598727 13.68,31.3422262 L13.68,166.857774 C21.8648391,169.940127 28.3473648,176.424701 31.4211018,184.6 Z M308.786627,188.6 L28.5712948,188.6 L28.1017136,187.123075 C25.5460281,179.085951 19.2108369,172.755681 11.1552331,170.191258 L9.68,169.721045 L9.68,28.4789548 L11.1552331,28.0087416 C19.2108369,25.4443192 25.5460281,19.1140486 28.1017136,11.076925 L28.5712948,9.6 L308.786627,9.6 L309.256209,11.076925 C311.811894,19.1140486 318.147085,25.4443192 326.202897,28.0087416 L327.68,28.4789548 L327.68,169.721045 L326.202897,170.191258 C318.147085,172.755681 311.811894,179.085951 309.256209,187.123075 L308.786627,188.6 L308.786627,188.6 Z' />
<path class='path-3' fill='#BEA757'
d='M48.6867136,193.6 L289.675574,193.6 C289.920957,188.260365 291.095884,183.076434 293.177482,178.162392 C295.452474,172.791616 298.711078,167.968921 302.857637,163.827174 C307.006274,159.685428 311.837202,156.434312 317.218786,154.163099 C322.138925,152.08496 327.33148,150.911984 332.68,150.667008 L332.68,48.5329917 C327.33148,48.2880163 322.138925,47.1150404 317.218786,45.0369009 C311.837202,42.7656875 307.006274,39.5124961 302.857637,35.3728257 C298.711078,31.2310791 295.452474,26.4083838 293.177482,21.0355316 C291.095884,16.1235655 289.920957,10.9396351 289.675574,5.6 L48.6867136,5.6 C48.4411226,10.9396351 47.2641155,16.1235655 45.1827263,21.0355316 C42.9075259,26.4083838 39.6510012,31.2310791 35.5023634,35.3728257 C31.3537256,39.5124961 26.523006,42.7656875 21.1432937,45.0369009 C16.2210752,47.1150404 11.0285195,48.2880163 5.68,48.5329917 L5.68,150.667008 C11.0285195,150.911984 16.2210752,152.08496 21.1432937,154.163099 C26.523006,156.434312 31.3537256,159.685428 35.5023634,163.827174 C39.6510012,167.968921 42.9075259,172.791616 45.1827263,178.162392 C47.2641155,183.076434 48.4411226,188.260365 48.6867136,193.6 Z M293.56286,197.6 L43.799639,197.6 L43.799639,195.474715 C43.799639,172.883411 25.4095267,154.505209 2.80639774,154.505209 L0.68,154.505209 L0.68,43.6947908 L2.80639774,43.6947908 C25.4095267,43.6947908 43.799639,25.3165892 43.799639,2.72528529 L43.799639,0.6 L293.56286,0.6 L293.56286,2.72528529 C293.56286,25.3165892 311.950682,43.6947908 334.553602,43.6947908 L336.68,43.6947908 L336.68,154.505209 L334.553602,154.505209 C311.950682,154.505209 293.56286,172.883411 293.56286,195.474715 L293.56286,197.6 L293.56286,197.6 Z' />
<path class='path-4' fill='#BEA757'
d='M294,184.6 L294,188.6 L43,188.6 L43,184.6 L294,184.6 Z M13.68,42.5 L13.68,153.5 L9.68,153.5 L9.68,42.5 L13.68,42.5 Z M327.68,42.5 L327.68,153.5 L323.68,153.5 L323.68,42.5 L327.68,42.5 Z M294,9.6 L294,13.6 L43,13.6 L43,9.6 L294,9.6 Z M31.4211018,184.6 L305.940979,184.6 C309.012635,176.424701 315.497242,169.940127 323.68,166.857774 L323.68,31.3422262 C315.497242,28.2598727 309.012635,21.7752988 305.940979,13.6 L31.4211018,13.6 C28.3473648,21.7752988 21.8648391,28.2598727 13.68,31.3422262 L13.68,166.857774 C21.8648391,169.940127 28.3473648,176.424701 31.4211018,184.6 Z M28.5712948,188.6 L28.1017136,187.123075 C25.5460281,179.085951 19.2108369,172.755681 11.1552331,170.191258 L9.68,169.721045 L9.68,28.4789548 L11.1552331,28.0087416 C19.2108369,25.4443192 25.5460281,19.1140486 28.1017136,11.076925 L28.5712948,9.6 L308.786627,9.6 L309.256209,11.076925 C311.811894,19.1140486 318.147085,25.4443192 326.202897,28.0087416 L327.68,28.4789548 L327.68,169.721045 L326.202897,170.191258 C318.147085,172.755681 311.811894,179.085951 309.256209,187.123075 L308.786627,188.6 L28.5712948,188.6 Z' />
</g>
</svg>-
put the Svg on page with the animations set to "paused"
-
in Javascript, I've set a
mouseenterevent in wich the animations of the Svg in page are set to "running", the Svg is transformed in data uri and assigned to the Cssborder-imageproperty as Url value -
Similarly, in Js I've set a
mouseleaveevent in wich the animations of the Svg in page are set to "paused", the Svg is transformed in data uri and assigned to the Cssborder-imageproperty as Url value
The result is that when you "mouseenter" the blockquote, the animation starts but when you "mouseleave" the blockquote the animation visually reset to 0 and when you "mouseenter" again you can see that in the meantime the animation is over.
Why?
from Start Css animation on hover in a Svg used as border-source
No comments:
Post a Comment