3d transforms on SVG element

2020-01-28 10:04发布

问题:

Is it possible to achieve perspective with 3d transforms on a SVG elements?

I'm talking about something similar with how the Star Wars opening titles look like with 3d perspective. This is a jsfiddle with the desired effect achieved using CSS3 3d transforms:

<section style="transform: perspective(200px) rotateX(-30deg); transform-origin: 50% 100%; text-align: justify; width: 100px;">
  <p style="backface-visibility: hidden;">TEXTTEXTTEXT</p>
</section>

回答1:


Update Nov 2018:

Testing the snipet from the question in latest chrome and Firefox works. Although support for 3d transforms on svg elements isn't very wide, browsers are implementing it more and more.


Origin answer :

3D transforms aren't supported on SVG elements. There are a few workarounds though :

If the svg doesn't contain elements that shouldn't be transformed, you can use CSS 3d transforms on the SVG element itself :

svg {
  width: 70%;
  margin: 0 auto;
  display: block;
  -webkit-transform: perspective(300px) rotateX(30deg);
  transform: perspective(300px) rotateX(30deg);
}
<svg viewbox="0 0 100 20">
  <text x="0" y="20">TEXTEXTEX</text>
</svg>

In case of polygons, you make a 2D polygon look like a 3D polygon. In the following example, the red rectangle is 3D rotated (rotateX(40deg)) and the black rectangle is a 2D SVG polygon made to look like a 3D rotated rectangle:

div{
  display:inline-block;
  width:200px; height:100px;
  background:red;
  transform:perspective(500px) rotateX(40deg);
}
svg{
  display:inline-block;
  width:220px; height:auto;
}
div, svg{
  display:inline-block;
  margin:0 10px;
}
<div></div>
<svg viewbox="0 0.5 10 4">
  <polygon points="9.9 4.1 0.1 4.1 0.7 0.6 9.3 0.6" fill=""/>
</svg>



回答2:

3D transforms are supported inside <svg> elements (f.e. on <circle>) (at least to some extent, it seems like perspective is isometric only).

For example, here's animation of transform: rotate3d applied to <circle> elements (tested in Chrome only):

body, html {
  background: black;
  width: 100%;  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  display: flex;
}

svg {
  width: 100%;
}

.gAExgp {
  transform-origin: 50% 50% 0px;
  animation-name: phEs, ipaUyp;
  animation-duration: 4s, 7s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.PwswZ {
  transform-origin: 50% 50% 0px;
  animation-name: gcRPJT, ipaUyp;
  animation-duration: 4s, 8s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

@keyframes phEs {
  50% {
    transform: rotate3d(0, 2, 1, 180deg);
  }
  100% {
    transform: rotate3d(0, 2, 1, 360deg);
  }
}

@keyframes gcRPJT {
  50% {
    transform: rotate3d(2, 0, 1, 180deg);
  }
  100% {
    transform: rotate3d(2, 0, 1, 360deg);
  }
}

@keyframes ipaUyp {
  0% {
    stroke: magenta;
  }
  33% {
    stroke: cyan;
  }
  66% {
    stroke: yellow;
  }
  100% {
    stroke: magenta;
  }
}
<!-- Logo from https://rebassjs.org -->

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" style="display:block;max-width:100%;margin:0;fill:none;stroke:cyan" vector-effect="non-scaling-stroke" class="sc-htoDjs hCHUAb"><circle cx="32" cy="32" r="32" fill="#000" stroke="none"></circle><circle cx="32" cy="32" r="30" stroke-width="1" vector-effect="non-scaling-stroke" opacity="0.5"></circle><g><circle cx="32" cy="32" r="24" stroke-width="2" vector-effect="non-scaling-stroke" class="sc-dnqmqq gAExgp"></circle><circle cx="32" cy="32" r="24" stroke-width="2" vector-effect="non-scaling-stroke" class="sc-iwsKbI PwswZ"></circle></g><text x="32" y="34" text-anchor="middle" font-family="system-ui, sans-serif" font-weight="bold" font-size="4" stroke="none" fill="white" style="text-transform:uppercase;letter-spacing:0.5em">Rebass</text></svg>

Also available here: https://codepen.io/anon/pen/MPeyEj