I'm trying to reproduce this piece of code (animated button using SVG and CSS): https://codepen.io/jscottsmith/pen/azRObp/
To keep the code clean, I wanted to use xlink with that. My current code looks as follows:
@import "compass/css3";
body {background:violet}
@keyframes spin {
to { transform: rotate(360deg); }
}
.stroke-dotted {
opacity: 0;
stroke-dasharray: 4,5;
stroke-width: 1px;
transform-origin: 50% 50%;
animation: spin 4s infinite linear;
transition: opacity 1s ease,
stroke-width 1s ease;
}
.stroke-solid {
stroke-dashoffset: 0;
stroke-dashArray: 300;
stroke-width: 4px;
transition: stroke-dashoffset 1s ease,
opacity 1s ease;
}
.icon {
transform-origin: 50% 50%;
transition: transform 200ms ease-out;
}
#play:hover .stroke-dotted {
stroke-width: 4px;
opacity: 1;
}
#play:hover .stroke-solid {
opacity: 0;
stroke-dashoffset: 300;
}
#play:hover .icon {
transform: scale(1.05);
}
#PlayNow {
cursor: pointer;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
width:10em;
height:auto;
display:block;
}
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100" x="0px" y="0px" ><use xlink:href="#play" id="playTrailerButton" /></svg>
</a>
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="play" viewBox="0 0 100 100">
<path fill="none" stroke="white" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
C97.3,23.7,75.7,2.3,49.9,2.5"/>
<path fill="none" stroke="white" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
C97.3,23.7,75.7,2.3,49.9,2.5"/>
<path fill="white" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z"/>
</symbol>
</svg>
But the animation doesn't work.. Any ideas or hints - why? jsfiddle is here: https://jsfiddle.net/4ztwr3c9/6
CodePudding user response:
You have this:
#PlayNow {
cursor: pointer;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
width:10em;
height:auto;
display:block;
}
There is no element with the id #PlayNow
. The example below has #PlayNow
selector replaced by the original #play
and your changes have been added, and I removed the Compass as well which I guess you can add it back, just be mindful of each change and retest so it's easier to debug and backtrack.
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.stroke-dotted {
opacity: 0;
stroke-dasharray: 4, 5;
stroke-width: 1px;
transform-origin: 50% 50%;
animation: spin 4s infinite linear;
transition: opacity 1s ease, stroke-width 1s ease;
}
.stroke-solid {
stroke-dashoffset: 0;
stroke-dashArray: 300;
stroke-width: 4px;
transition: stroke-dashoffset 1s ease, opacity 1s ease;
}
.icon {
transform-origin: 50% 50%;
transition: transform 200ms ease-out;
}
#play:hover .stroke-dotted {
stroke-width: 4px;
opacity: 1;
}
#play:hover .stroke-solid {
opacity: 0;
stroke-dashoffset: 300;
}
#play:hover .icon {
transform: scale(1.05);
}
html {
height: 100%;
}
body {
height: 100%;
/*background-color: #30FF98;
background: radial-gradient(#71edb5, #30ff98);*/
}
#play {
cursor: pointer;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* Your Changes */
width:10em;
height:auto;
display:block;
}
body {background:violet}
<svg version="1.1" id="play" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" height="100px" width="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<path fill="none" stroke="white" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
C97.3,23.7,75.7,2.3,49.9,2.5"/>
<path fill="none" stroke="white" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
C97.3,23.7,75.7,2.3,49.9,2.5"/>
<path fill="white" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z"/>
</svg>
CodePudding user response:
You can change/override some properties of a <use>
element - provided these are not already set in your <symbol>
element (see first example).
Since you need to change the dash-array
values for different elements you can use css variables, that could be changed on hover.
body {
background: violet;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
:root {
--fill: #fff;
--strokeWidth: 4px;
--scale: 1;
--strokeDashOffset: 10;
--strokeDashArray: 4 5;
--opacity: 0;
--strokeDashArraySolid: 300;
--strokeDashOffsetSolid: 0;
--opacitySolid: 1;
}
.PlayNow {
display: inline-block;
height: 10em;
}
.PlayNow2 {
--fill: #ccc;
--strokeWidth: 6px;
--scale: 1.5;
}
.PlayNow:hover {
--scale: 1.05;
--strokeDashOffset: 10;
--strokeDashArray: 4 5;
--strokeDashArraySolid: 300;
--strokeDashOffsetSolid: 300;
--opacity: 1;
--opacitySolid: 0;
}
#playTrailerButtonSimple:hover {
fill: green!important;
stroke: green!important;
stroke-dasharray: 10 5;
}
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" id="PlayNowSimple" viewBox="0 0 100 100">
<use href="#playSimple" id="playTrailerButtonSimple" stroke-width="4" fill="red" stroke="red"/>
</svg> Simple icon
</a>
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100">
<use href="#play" id="playTrailerButton" />
</svg>
</a>
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" id="PlayNow2" viewBox="0 0 100 100">
<use href="#play" id="playTrailerButton" />
</svg>
</a>
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="circle">
<path fill="none" style="stroke:var(--fill)" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7 C97.3,23.7,75.7,2.3,49.9,2.5" />
</symbol>
<symbol id="play" viewBox="0 0 100 100">
<use href="#circle" transform-origin="center" style="stroke-width: var(--strokeWidth); stroke-dasharray: var(--strokeDashArraySolid); stroke-dashoffset: var(--strokeDashOffsetSolid); opacity:var(--opacitySolid); transition: stroke-dashoffset 1s ease, opacity 1s ease;" />
<use href="#circle" transform-origin="center" style="stroke-width: var(--strokeWidth); stroke-dasharray: var(--strokeDashArray); stroke-dashoffset: var(--strokeDashOffset); opacity:var(--opacity); animation: spin 4s infinite linear; transition: opacity 1s ease, stroke-width 1s ease;" />
<path transform-origin="center" style="fill:var(--fill);transform:scale(var(--scale));transition:0.3s" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z" />
</symbol>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="circle2">
<path fill="none" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7 C97.3,23.7,75.7,2.3,49.9,2.5" />
</symbol>
<symbol id="playSimple" viewBox="0 0 100 100">
<use href="#circle2" transform-origin="center" />
<path stroke-width="0" transform-origin="center" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z" />
</symbol>
</svg>
External <use>
reference
To some extent, you could also use external svg files like so:
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100" x="0px" y="0px">
<use href="button.svg#play" id="playTrailerButton" style="transition:0.3s"/>
</svg>
</a>
** Drawback:** Your animations/transitions won#t work in most browsers (Firefox can render them)