This may be a browser-bug relating to how Firefox Desktop 100.0.2. handles SVG and CSS Transforms.
Or else I'm doing something wrong to bring about this undesired effect.
I have a <button> containing two SVGs, one positioned on top of the other.
The SVG on the bottom is rotated 180 degrees (using transform: rotateY(180deg)) and invisible (using opacity: 0).
When the <button> is clicked, both SVGs rotate and at the halfway point in the rotation, the SVG on the bottom becomes visible and the SVG on the top becomes invisible.
The overall effect is that the <button> image rotates and transforms in the middle of its rotation.
Why is messing about with opacity necessary when we have backface-visibility?
Because iOS Safari doesn't support backface-visibility.
What's the issue?
The issue is that this isn't a clean rotation. The SVG which suddenly becomes visible turns into a blurry mess - like when the helicopter pilot in the original The Matrix is possessed by one of the agents - before settling into its new shape.
Click the button several times below to see this undesired effect in action. (I've slowed the transition down a little, so you have more time to see it in action.)
Working Example:
const audioButton = document.querySelector('.audioButton');
const audioOn = document.querySelector('.audio-on');
const audioOff = document.querySelector('.audio-off');
const toggleAudio = (e) => {
audioOn.classList.toggle('active');
audioOff.classList.toggle('active');
}
audioButton.addEventListener('click', toggleAudio, false);
.audioButton {
position: relative;
width: 52px;
height: 52px;
margin: 0 12px 0 0;
background-image: linear-gradient(hsl(219, 76%, 50%), hsl(219, 80%, 43%) 50%, hsl(219, 81%, 41%) 51%, hsl(219, 88%, 33%));
border: 2px solid hsl(220, 100%, 25%);
border-bottom: 2px solid hsl(220, 100%, 26%);
border-radius: 4px;
cursor: pointer;
}
.audioButton::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
}
.audioButton:hover::after {
background-color: rgba(0, 0, 0, 0.15);
}
.audioButtonVector {
position: absolute;
display: block;
top: 10%;
left: 10%;
width: 80%;
height: 80%;
opacity: 0;
pointer-events: none;
transform: rotateY(180deg);
transition: transform 1.2s linear, opacity 0s linear 0.6s;
}
.audio-off {
color: rgb(91, 127, 239);
}
.audio-on {
color: rgb(255, 255, 255);
}
.active {
opacity: 1;
transform: rotateY(0deg);
}
<button class="audioButton" type="button" title="Turn Audio On">
<svg xmlns="http://www.w3.org/2000/svg"
lang="en-GB"
class="audioButtonVector audio-off active"
viewBox="0 0 768 768">
<title>Mute Icon</title>
<defs><style><![CDATA[path {fill: currentColor;}]]></style></defs>
<path d="m 514.64857,746.41567 c -7.23403,-2.33279 -15.45533,-6.93789 -23.16845,-12.97761 -3.14331,-2.46136 -44.6698,-43.2877 -92.2811,-90.7252 l -86.56599,-86.25 h -67.29941 c -47.65888,0 -68.66895,-0.33827 -71.99223,-1.1591 -10.38521,-2.56509 -23.41546,-14.17469 -26.78831,-23.86766 -1.83792,-5.28188 -1.90451,-10.42057 -1.90451,-146.97324 v -141.5 l 2.89186,-6.2618 c 3.2572,-7.05289 8.40912,-12.23957 15.39549,-15.4994 2.59196,-1.20939 4.91571,-2.33594 5.16389,-2.50342 0.24818,-0.16749 -20.72025,-21.55146 -46.5965,-47.51995 -30.937231,-31.04751 -47.695971,-48.58514 -48.940811,-51.21543 -2.8746,-6.0739 -2.65973,-18.56296 0.42151,-24.500003 3.16419,-6.09687 8.64277,-11.63242 14.66456,-14.81707 4.20155,-2.222 6.27753,-2.64426 13.000001,-2.64426 6.74443,0 8.78473,0.4178 13,2.6621 3.65377,1.94535 22.6348,20.316143 70.49714,68.230673 l 65.49713,65.56856 h 31.48475 31.48474 l 89.51812,-89.32184 c 95.1437,-94.935093 95.62848,-95.37672 110.05601,-100.257898 6.53075,-2.209511 8.73786,-2.420265 25.34601,-2.420265 16.8774,0 18.51482,0.162627 22.65421,2.25 3.53889,1.784556 5.02413,3.387752 7.17979,7.75 l 2.71791,5.5 0.0321,248.502843 0.0321,248.50284 65.8925,65.88683 c 46.80175,46.79773 66.57555,67.22255 68.25005,70.49716 3.3554,6.56182 3.366,18.66705 0.022,25.11033 -3.1642,6.09686 -8.6428,11.63242 -14.6646,14.81707 -6.9012,3.64972 -18.7705,3.80022 -25.50001,0.32333 -3.02072,-1.5607 -19.21059,-17.00386 -49.25,-46.97853 l -44.75005,-44.65354 v 56.77796 c 0,62.53583 0.17139,60.72201 -6.27221,66.37956 -4.82954,4.24039 -10.80361,5.3457 -28.52701,5.27798 -11.68868,-0.0447 -15.93014,-0.4526 -20.70078,-1.99102 z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
lang="en-GB"
class="audioButtonVector audio-on"
viewBox="0 0 768 768">
<title>Audio Icon</title>
<defs><style><![CDATA[path {fill: currentColor;}]]></style></defs>
<path d="m 470.57734,741.2876 c -7.71475,-2.83606 -11.18777,-4.89195 -18.82603,-11.1443 -2.39807,-1.96296 -43.79807,-42.82236 -92,-90.79868 l -87.63988,-87.22967 -69.5,-0.27033 -69.5,-0.27033 -5.86156,-2.87813 c -8.69995,-4.27183 -19.79481,-15.53374 -22.7789,-23.12187 l -2.35954,-6 v -138 c 0,-131.11094 0.0914,-138.27456 1.83191,-143.5 4.32786,-12.99369 11.24782,-19.42452 26.95392,-25.04871 l 8.21417,-2.94141 66.47695,-0.005 66.47696,-0.005 90.52304,-90.2663 c 95.08695,-94.817141 94.44763,-94.232081 108.57699,-99.360761 5.97505,-2.16883 8.09265,-2.37282 24.63202,-2.37282 16.6968,0 18.4388,0.17171 22.54471,2.2223 2.44735,1.22227 5.35455,3.49301 6.46044,5.04609 4.95602,6.96009 4.73518,-9.62279 4.77327,358.416511 0.0249,240.3642 -0.28452,345.03405 -1.02571,347 -0.58374,1.54831 -2.49624,4.31599 -4.25,6.15042 -5.99091,6.26644 -7.33614,6.60106 -27.68867,6.88738 -18.04936,0.25392 -18.68352,0.19279 -26.03409,-2.50939 z M 600.3594,549.70163 c -5.93421,-2.20326 -10.33035,-6.14828 -13.14459,-11.79572 -5.39826,-10.83291 -3.08865,-16.71172 11.68289,-29.73724 40.36186,-35.59104 59.79177,-80.99428 57.38451,-134.09438 -2.23918,-49.39231 -20.58907,-87.5315 -58.17881,-120.9213 -12.02899,-10.68498 -14.65864,-14.55603 -14.65864,-21.5787 0,-11.90939 13.04063,-24.61151 23.75911,-23.14238 6.3213,0.86643 9.17103,2.59906 20.69094,12.58013 39.46289,34.19135 62.29527,76.84757 69.88539,130.56225 1.92863,13.64871 1.60428,48.41306 -0.58777,63 -5.75409,38.29032 -20.26693,71.24453 -44.36153,100.73141 -8.21433,10.05267 -30.26582,31.0853 -34.9257,33.312 -4.92676,2.35423 -12.81232,2.84138 -17.5458,1.08393 z" />
</svg>
</button>
Nota Bene:
I note that I if I change the transition from:
transition: transform 1.2s linear, opacity 0s linear 0.6s;
to:
transition: transform 1.2s linear, opacity 0.2s linear 0.5s;
the bizarre effect is minimised.
Using magic numbers like this, isn't an ideal compromise, I'll fall back to that if I can't get to the bottom of the issue.
A Significant Improvement:
I recalled some advice about sometimes needing to put different transitions on different elements. The updated version below is a clear improvement in that if you keep the mouse cursor hovered over the button after you click, the rotation is clean.
But if you move the mouse cursor off the button after clicking, the same messy effect is still visible.
Improved Working Example:
const audioButton = document.querySelector('.audioButton');
const audioOn = document.querySelector('.audio-on');
const audioOff = document.querySelector('.audio-off');
const toggleAudio = (e) => {
audioOn.classList.toggle('active');
audioOff.classList.toggle('active');
}
audioButton.addEventListener('click', toggleAudio, false);
.audioButton {
position: relative;
width: 52px;
height: 52px;
margin: 0 12px 0 0;
background-image: linear-gradient(hsl(219, 76%, 50%), hsl(219, 80%, 43%) 50%, hsl(219, 81%, 41%) 51%, hsl(219, 88%, 33%));
border: 2px solid hsl(220, 100%, 25%);
border-bottom: 2px solid hsl(220, 100%, 26%);
border-radius: 4px;
cursor: pointer;
}
.audioButton::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0);
}
.audioButton:hover::after {
background-color: rgba(0, 0, 0, 0.15);
}
.audioButtonVector {
position: absolute;
display: block;
top: 10%;
left: 10%;
width: 80%;
height: 80%;
transform: rotateY(180deg);
pointer-events: none;
transition: transform 0.6s linear;
}
.audioButtonVector.active {
transform: rotateY(0deg);
}
.audioButtonVector path {
opacity: 0;
transition: opacity 0s linear 0.3s;
}
.audioButtonVector.active path {
opacity: 1;
}
.audio-off {
color: rgb(91, 127, 239);
}
.audio-on {
color: rgb(255, 255, 255);
}
<button class="audioButton" type="button" title="Turn Audio On">
<svg xmlns="http://www.w3.org/2000/svg"
lang="en-GB"
class="audioButtonVector audio-off active"
viewBox="0 0 768 768">
<title>Mute Icon</title>
<defs><style><![CDATA[path {fill: currentColor;}]]></style></defs>
<path d="m 514.64857,746.41567 c -7.23403,-2.33279 -15.45533,-6.93789 -23.16845,-12.97761 -3.14331,-2.46136 -44.6698,-43.2877 -92.2811,-90.7252 l -86.56599,-86.25 h -67.29941 c -47.65888,0 -68.66895,-0.33827 -71.99223,-1.1591 -10.38521,-2.56509 -23.41546,-14.17469 -26.78831,-23.86766 -1.83792,-5.28188 -1.90451,-10.42057 -1.90451,-146.97324 v -141.5 l 2.89186,-6.2618 c 3.2572,-7.05289 8.40912,-12.23957 15.39549,-15.4994 2.59196,-1.20939 4.91571,-2.33594 5.16389,-2.50342 0.24818,-0.16749 -20.72025,-21.55146 -46.5965,-47.51995 -30.937231,-31.04751 -47.695971,-48.58514 -48.940811,-51.21543 -2.8746,-6.0739 -2.65973,-18.56296 0.42151,-24.500003 3.16419,-6.09687 8.64277,-11.63242 14.66456,-14.81707 4.20155,-2.222 6.27753,-2.64426 13.000001,-2.64426 6.74443,0 8.78473,0.4178 13,2.6621 3.65377,1.94535 22.6348,20.316143 70.49714,68.230673 l 65.49713,65.56856 h 31.48475 31.48474 l 89.51812,-89.32184 c 95.1437,-94.935093 95.62848,-95.37672 110.05601,-100.257898 6.53075,-2.209511 8.73786,-2.420265 25.34601,-2.420265 16.8774,0 18.51482,0.162627 22.65421,2.25 3.53889,1.784556 5.02413,3.387752 7.17979,7.75 l 2.71791,5.5 0.0321,248.502843 0.0321,248.50284 65.8925,65.88683 c 46.80175,46.79773 66.57555,67.22255 68.25005,70.49716 3.3554,6.56182 3.366,18.66705 0.022,25.11033 -3.1642,6.09686 -8.6428,11.63242 -14.6646,14.81707 -6.9012,3.64972 -18.7705,3.80022 -25.50001,0.32333 -3.02072,-1.5607 -19.21059,-17.00386 -49.25,-46.97853 l -44.75005,-44.65354 v 56.77796 c 0,62.53583 0.17139,60.72201 -6.27221,66.37956 -4.82954,4.24039 -10.80361,5.3457 -28.52701,5.27798 -11.68868,-0.0447 -15.93014,-0.4526 -20.70078,-1.99102 z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
lang="en-GB"
class="audioButtonVector audio-on"
viewBox="0 0 768 768">
<title>Audio Icon</title>
<defs><style><![CDATA[path {fill: currentColor;}]]></style></defs>
<path d="m 470.57734,741.2876 c -7.71475,-2.83606 -11.18777,-4.89195 -18.82603,-11.1443 -2.39807,-1.96296 -43.79807,-42.82236 -92,-90.79868 l -87.63988,-87.22967 -69.5,-0.27033 -69.5,-0.27033 -5.86156,-2.87813 c -8.69995,-4.27183 -19.79481,-15.53374 -22.7789,-23.12187 l -2.35954,-6 v -138 c 0,-131.11094 0.0914,-138.27456 1.83191,-143.5 4.32786,-12.99369 11.24782,-19.42452 26.95392,-25.04871 l 8.21417,-2.94141 66.47695,-0.005 66.47696,-0.005 90.52304,-90.2663 c 95.08695,-94.817141 94.44763,-94.232081 108.57699,-99.360761 5.97505,-2.16883 8.09265,-2.37282 24.63202,-2.37282 16.6968,0 18.4388,0.17171 22.54471,2.2223 2.44735,1.22227 5.35455,3.49301 6.46044,5.04609 4.95602,6.96009 4.73518,-9.62279 4.77327,358.416511 0.0249,240.3642 -0.28452,345.03405 -1.02571,347 -0.58374,1.54831 -2.49624,4.31599 -4.25,6.15042 -5.99091,6.26644 -7.33614,6.60106 -27.68867,6.88738 -18.04936,0.25392 -18.68352,0.19279 -26.03409,-2.50939 z M 600.3594,549.70163 c -5.93421,-2.20326 -10.33035,-6.14828 -13.14459,-11.79572 -5.39826,-10.83291 -3.08865,-16.71172 11.68289,-29.73724 40.36186,-35.59104 59.79177,-80.99428 57.38451,-134.09438 -2.23918,-49.39231 -20.58907,-87.5315 -58.17881,-120.9213 -12.02899,-10.68498 -14.65864,-14.55603 -14.65864,-21.5787 0,-11.90939 13.04063,-24.61151 23.75911,-23.14238 6.3213,0.86643 9.17103,2.59906 20.69094,12.58013 39.46289,34.19135 62.29527,76.84757 69.88539,130.56225 1.92863,13.64871 1.60428,48.41306 -0.58777,63 -5.75409,38.29032 -20.26693,71.24453 -44.36153,100.73141 -8.21433,10.05267 -30.26582,31.0853 -34.9257,33.312 -4.92676,2.35423 -12.81232,2.84138 -17.5458,1.08393 z" />
</svg>
</button>
No Further Improvement:
In the past I've seen issues in iOS Safari related to CSS 3D Rotations.
So I've replaced:
transform: rotateY(180deg)
transform: rotateY(0deg)
with:
transform: scale(-1, 1)
transform: scale(1, 1)
The minimal flicker that was previously visible in iOS Safari (I didn't mention this before - it's an unrelated issue) has now gone.
But the CSS update above hasn't made any significant difference to the undesired visual effect in Firefox Desktop.
I am having troubles to scale the SVG to fit the window size.
In this example, I have a wavy path and a text element, what I want to achieve here is to move the text element along the wavy path from left to right (which is done by GSAP) and stop in the half way of the path in the initial load; it will move to the end when users start scrolling.
My problem is that, the wavy path created by SVG is too long, even the half way of the path will be off the window, I tried to scale down the wavy path by using viewBox, failed; using css width: 100vw, failed.
I also used the css transform property, it did scale the wavy path down, but that was a fixed size, I want to make it as responsive as possible, which means regardless the window width, the text element always stops in the middle of the screen first ( half way of the wavy path ), then moves to the right hand side of the screen. Is this possible when using inline SVG element? If so, please point me in the right direction.
Thank you in advance!
(Please view the example in full page mode, that will explain my problem perfectly, but the scroll function will be disabled because the height in that mode is 100vh, there is no room for scrolling)
document.getElementById("MyPath").setAttribute("d", document.getElementById("Path").getAttribute("d"));
var tl = new TimelineMax({
repeat: 0,
delay: 1
});
tl.to("#Text", 3, {
attr: {
startOffset: '50%',
opacity: 1
}
});
window.addEventListener('scroll', function() {
tl.to("#Text", 3, {
attr: {
startOffset: '100%',
opacity: 0
}
});
}, true);
#import url(https://fonts.googleapis.com/css?family=Oswald);
body {
background-color: #222;
}
svg {
overflow: visible;
width: 100%;
height: 100%;
background-color: #fff;
left: 0;
top: 0;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/plugins/TextPlugin.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<svg xml:space="preserve">
<defs><path id="MyPath"/></defs>
<path id="Path" fill="none" stroke="#000" stroke-miterlimit="10" d="M0,188.2c186.2,84,261.8,84.9,440,66.4s295.2-130,535.2-129.4c240,0.6,357,144.3,591.1,144.3
s450.1-141.2,651.1-141.2c271.7,0,354.2,141.2,612.1,141.2c240,0,423-141.2,669.1-141.2c119.1,0,202.3,33.8,281,68.7"/>
<text font-size="7em" >
<textPath id="Text" fill='#88CE02' font-family=Oswald xlink:href="#MyPath" opacity=0 startOffset="0%" letter-spacing="5px">Love the little things.</textPath>
</text>
</svg>
If you want your SVG to scale to fit the screen (or any parent container), it needs to have a viewBox attribute. This attribute tells the browser the dimensions of the SVG content. Without it, the browser has know way of knowing how much it needs to be scaled.
Your path is about 3780 width, and the bottom of it is at y=144. So a reasonable value of viewBox would be:
viewBox="0 0 3780 150"
document.getElementById("MyPath").setAttribute("d", document.getElementById("Path").getAttribute("d"));
var tl = new TimelineMax({
repeat: 0,
delay: 1
});
tl.to("#Text", 3, {
attr: {
startOffset: '50%',
opacity: 1
}
});
window.addEventListener('scroll', function() {
tl.to("#Text", 3, {
attr: {
startOffset: '100%',
opacity: 0
}
});
}, true);
#import url(https://fonts.googleapis.com/css?family=Oswald);
body {
background-color: #222;
}
svg {
overflow: visible;
width: 100%;
height: 100%;
background-color: #fff;
left: 0;
top: 0;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/plugins/TextPlugin.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<svg viewBox="0 0 3780 150" xml:space="preserve">
<defs><path id="MyPath"/></defs>
<path id="Path" fill="none" stroke="#000" stroke-miterlimit="10" d="M0,188.2c186.2,84,261.8,84.9,440,66.4s295.2-130,535.2-129.4c240,0.6,357,144.3,591.1,144.3
s450.1-141.2,651.1-141.2c271.7,0,354.2,141.2,612.1,141.2c240,0,423-141.2,669.1-141.2c119.1,0,202.3,33.8,281,68.7"/>
<text font-size="7em" >
<textPath id="Text" fill='#88CE02' font-family=Oswald xlink:href="#MyPath" opacity=0 startOffset="0%" letter-spacing="5px">Love the little things.</textPath>
</text>
</svg>
Here's what you could do: add a media query defining the desired width and then apply the following styles separately for the text and path elements inside the svg element:
text {
font-size: 2em;
}
path {
-webkit-transform: scale(.3);
-ms-transform: scale(.3);
transform: scale(.3);
}
See the snippet below:
document.getElementById("MyPath").setAttribute("d", document.getElementById("Path").getAttribute("d"));
var tl = new TimelineMax({
repeat: 0,
delay: 1
});
tl.to("#Text", 3, {
attr: {
startOffset: '50%',
opacity: 1
}
});
window.addEventListener('scroll', function() {
tl.to("#Text", 3, {
attr: {
startOffset: '100%',
opacity: 0
}
});
}, true);
#import url(https://fonts.googleapis.com/css?family=Oswald);
body {
background-color: #222;
}
svg {
overflow: visible;
width: 100%;
height: 100%;
background-color: #fff;
left: 0;
top: 0;
position: absolute;
}
#media only screen and (max-width: 500px) {
text {
font-size: 2em;
}
path {
-webkit-transform: scale(.3);
-ms-transform: scale(.3);
transform: scale(.3);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/plugins/TextPlugin.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<svg xml:space="preserve">
<defs><path id="MyPath"/></defs>
<path id="Path" fill="none" stroke="#000" stroke-miterlimit="10" d="M0,188.2c186.2,84,261.8,84.9,440,66.4s295.2-130,535.2-129.4c240,0.6,357,144.3,591.1,144.3
s450.1-141.2,651.1-141.2c271.7,0,354.2,141.2,612.1,141.2c240,0,423-141.2,669.1-141.2c119.1,0,202.3,33.8,281,68.7"/>
<text font-size="7em" >
<textPath id="Text" fill='#88CE02' font-family=Oswald xlink:href="#MyPath" opacity=0 startOffset="0%" letter-spacing="5px">Love the little things.</textPath>
</text>
</svg>
I hope it helps!
Problem
I'm trying to simply move an svg element using transform=matrix(a,b,c,d,e,f)
The element is moving fine but when I apply a css transition it has no effect.
Question
Is this possible on svg elements without an external library like d3?
Code I'm trying
html:
<svg width="100%" height="100%" viewbox="0 0 200 200">
<rect x="20" y="20" width="50" height="50"
style="fill: #3333cc"
transform="matrix(1,0,0,1,1,1)"
id="blueBox"
/>
</svg>
<button id="boxMover">
Move it
</button>
jQuery
$(function(){
$('#boxMover').click(function(){
var blueBox = $('#blueBox');
if(blueBox.attr('transform')=='matrix(1,0,0,1,1,1)'){
blueBox.attr('transform', 'matrix(1,0,0,1,100,30)');
} else {
blueBox.attr('transform', 'matrix(1,0,0,1,1,1)');
}
})
})
CSS
svg {
display: block
}
#boxMover {
position: absolute;
left: 20px;
top: 20px;
transition: transform .5s ease;
}
Here's a fiddle I created to test it
A simpler solution:
Create the following class:
.boxEase {
transform: matrix(1,0,0,1,100,30);
transition: all .5s ease;
}
Change your jQuery code to just attach the above class to your box when the button is clicked:
$(function(){
$('#boxMover').click(function(){
var blueBox = $('#blueBox');
blueBox.attr('class', 'boxEase');
})
})
Added dynamic case with variable ending (starting) positions
Use the following jQuery code where transform and transition properties are added to the box conditionally. I imagine you can adjust the conditional to something else but I have used your original example for this case:
`$(function(){
$('#boxMover').click(function(){
var startPos = 'matrix(1,0,0,1,1,1)',
endPos = 'matrix(1,0,0,1,100,30)';
var blueBox = $('#blueBox');
if(blueBox.attr('transform') == startPos){
blueBox.attr('transform', endPos);
blueBox.css({'transform': endPos, 'transition': 'all 0.5s ease'});
} else {
blueBox.attr('transform', startPos);
blueBox.css({'transform': startPos, 'transition': 'all 0.5s ease'});
}
})
}); `
There's a horrible grey area between the CSS and SVG namespaces where things like this happen all the time.
However, you can fix your problem as follows:
Move the transform CSS statement out of the #boxMover rules and put it somewhere it can actually affect the behaviour of your #blueBox SVG element.
Changing the transform attributes of the SVG element directly still won't work because you're talking to the SVG namespace, and the CSS rules aren't having any say in the matter. Instead, set up CSS classes containing the required transform attributes, and switch between those instead. There is no class attribute in the SVG namespace, so the CSS rules will come to life.
Also note that you can't use JQuery's addClass() and removeClass() methods to change the class of an SVG element, so use attr('class') instead
This should work:
$(function() {
$('#boxMover').click(function() {
var blueBox = $('#blueBox');
if (blueBox.attr('class') == 'overHere') {
blueBox.attr('class', 'overThere');
} else {
blueBox.attr('class', 'overHere');
}
})
})
svg {
display: block
}
#boxMover {
position: absolute;
left: 20px;
top: 20px;
}
#blueBox {
transition: transform .5s ease;
}
.overHere {
transform: matrix(1, 0, 0, 1, 1, 1);
}
.overThere {
transform: matrix(1, 0, 0, 1, 100, 30);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="100%" height="100%" viewbox="0 0 200 200">
<rect x="20" y="20" width="50" height="50"
style="fill: #3333cc" class="overHere" id="blueBox" />
</svg>
<button id="boxMover">
Move it
</button>