transform-origin not working in Firefox even prope

2019-01-27 04:54发布

问题:

CSS3 transform-origin not working in firefox browser.

I am trying to run transform: rotate(360deg); in @keyframes for <g class="tyre"> as child of <svg class='truck'>. In the result the truck wheel rotation works fine for all other browser except chrome

There are similar questions in Stack Overflow unfortunately none of them are related with the question.

.tyre{
  -webkit-transform-origin: 50% 50%;
  -moz-transform-origin: 50% 50%;
  transform-origin: 50% 50%;
  transform: rotate(0);
  -webkit-animation: spin 1s linear infinite;
          animation: spin 1s linear infinite;
}

@-webkit-keyframes spin {
  from   { transform: rotate(360deg); }
  to  { transform: rotate(0deg); }
}
@keyframes spin {
  from   { transform: rotate(360deg); }
  to  { transform: rotate(0deg); }
}
<svg class='truck' viewBox='0 0 93 53' xmlns='http://www.w3.org/2000/svg' height="180">
  <g class='chase' fill-rule='evenodd' fill='none'>
    <path d='M32.087 35.263h3.023V5.973h-3.023v29.29z' fill='#EE7C00'></path>
    <path d='M87.84 35.262H5.007v4.065L9.07 43.39h74.707l4.062-4.063v-4.065z' fill='#9B9B9B'></path>
    <path d='M35.11 35.262h57.445v-3.966H35.11v3.966z' fill='#F09E00'></path>
    <path d='M90.393 35.262h2.16v-3.966h-2.16v3.966z' fill='#E2000F'></path>
    <path d='M17.498.493L2.91 15.08v20.182h29.175V.492H17.498z' fill='#FCC400'></path>
    <path d='M29.495 2.905H18.16L6.823 14.24h22.67V2.905z' fill='#575656'></path>
    <path d='M0 35.262h10.014v-3.966H0v3.966z' fill='#F09E00'></path>
    <path d='M5.008 37.294h82.83v-2.032H5.01v2.032z' fill='#575656'></path>
    <path d='M.75 29.858h2.16v-6.995H.75v6.995zM11.015 20.074h3.497v-2.16h-3.497v2.16z' fill='#E2000F'></path>
    <path d='M28.447 35.262h1.05V14.24h-1.05v21.022z' fill='#EE7C00'></path>
    <path d='M53.51 27.23h34.33v4.065H53.51V27.23z' fill='#575656'></path>
  </g>
  <g class='tyre'>
    <path d='M64.827 36.593a9.61 9.61 0 0 0 0 13.59c3.753 3.754 9.837 3.754 13.59 0a9.61 9.61 0 0 0-13.59-13.59' fill='#1A1A18'></path>
    <path d='M67.287 39.053a6.13 6.13 0 0 0 0 8.67 6.13 6.13 0 1 0 0-8.67' fill='#9B9B9B'></path>
    <path d='M67.287 39.053a6.133 6.133 0 0 0 0 8.67 6.134 6.134 0 0 0 8.67 0l-8.67-8.67z' fill='#C5C5C6'></path>
    <path d='M68.784 40.55a4.012 4.012 0 0 0 5.676 5.677 4.012 4.012 0 0 0-5.676-5.676' fill='#868685'></path>
    <path d='M65.526 37.293A8.62 8.62 0 1 1 77.72 49.486a8.62 8.62 0 0 1-12.192-12.193m-.385-.386c-3.578 3.578-3.578 9.384 0 12.963 3.58 3.58 9.385 3.58 12.964 0 3.578-3.58 3.578-9.385 0-12.963-3.58-3.58-9.386-3.58-12.964 0' fill='#3B3A39'></path>
  </g>
  <g class='tyre'>
    <path d='M13.038 36.593c-3.754 3.754-3.754 9.838 0 13.59a9.61 9.61 0 0 0 13.59 0c3.754-3.752 3.754-9.836 0-13.59a9.61 9.61 0 0 0-13.59 0' fill='#1A1A18'></path>
    <path d='M15.498 39.054a6.128 6.128 0 0 0 0 8.67 6.13 6.13 0 0 0 8.67 0 6.13 6.13 0 0 0-8.67-8.67' fill='#9B9B9B'></path>
    <path d='M15.498 39.054a6.13 6.13 0 1 0 8.67 8.67l-8.67-8.67z' fill='#C5C5C6'></path>
    <path d='M16.996 40.55a4.012 4.012 0 1 0 5.675 5.677 4.014 4.014 0 0 0-5.674-5.676' fill='#868685'></path>
    <path d='M13.737 37.293a8.622 8.622 0 0 1 12.192 0 8.622 8.622 0 0 1 0 12.192 8.622 8.622 0 0 1-12.193 0 8.622 8.622 0 0 1 0-12.192m-.385-.385a9.164 9.164 0 0 0 0 12.962c3.578 3.58 9.384 3.58 12.962 0a9.164 9.164 0 0 0 0-12.962 9.164 9.164 0 0 0-12.962 0' fill='#3B3A39'></path>
  </g>
  <g class='tyre'>
    <path d='M44.406 36.593c-3.753 3.754-3.753 9.838 0 13.59 3.754 3.755 9.838 3.755 13.59 0 3.755-3.752 3.755-9.836 0-13.59-3.752-3.753-9.836-3.753-13.59 0' fill='#1A1A18'></path>
    <path d='M46.868 39.054a6.128 6.128 0 0 0 0 8.67 6.128 6.128 0 0 0 8.67 0 6.128 6.128 0 0 0 0-8.67 6.13 6.13 0 0 0-8.67 0' fill='#9B9B9B'></path>
    <path d='M46.868 39.054a6.13 6.13 0 1 0 8.67 8.67l-8.67-8.67z' fill='#C5C5C6'></path>
    <path d='M48.364 40.55a4.014 4.014 0 1 0 0 0' fill='#868685'></path>
    <path d='M45.106 37.293a8.622 8.622 0 0 1 12.192 0 8.622 8.622 0 0 1 0 12.192 8.622 8.622 0 0 1-12.192 0 8.622 8.622 0 0 1 0-12.192m-.385-.385a9.164 9.164 0 0 0 0 12.962c3.58 3.58 9.385 3.58 12.963 0 3.58-3.578 3.58-9.384 0-12.962a9.164 9.164 0 0 0-12.962 0' fill='#3B3A39'></path>
  </g>
</svg>

回答1:

To summarise the comments you have been getting:

  1. The transform-origin property with percentage values on SVG elements has been broken in Firefox, and has only just been fixed/implemented.

  2. The meaning of transform-origin: 50% 50% when applied to SVG elements has not been fully specified until recently. Chrome used the centre of the element's bounding box. Firefox uses the centre of the SVG.

  3. How percentage origins are to be calculated has only recently been decided. There is a new property called transform-box. See: https://drafts.csswg.org/css-transforms/#transform-box

The default value of transform-box for SVG elements is view-box (typically the centre of the whole SVG). However Chrome currently uses the equivalent of fill-box.

In summary, you should not rely on Chrome's behaviour. It is probably going to change to match what is specified by the new transform-box property.

If you want to have your SVG work now on both browsers, don't use percentage values in transform-origin. Use absolute coordinates. See example below.

.tyreA {
  -webkit-transform-origin: 71.59px 43.42px;
  -moz-transform-origin: 71.59px 43.42px;
  transform-origin: 71.59px 43.42px;
  transform: rotate(0);
  -webkit-animation: spin 1s linear infinite;
          animation: spin 1s linear infinite;
}

.tyreB {
  -webkit-transform-origin: 19.83px 43.39px;
  -moz-transform-origin: 19.83px 43.39px;
  transform-origin: 19.83px 43.39px;
  transform: rotate(0);
  -webkit-animation: spin 1s linear infinite;
          animation: spin 1s linear infinite;
}

.tyreC {
  -webkit-transform-origin: 51.2px 43.39px;
  -moz-transform-origin: 51.2px 43.39px;
  transform-origin: 51.2px 43.39px;
  transform: rotate(0);
  -webkit-animation: spin 1s linear infinite;
          animation: spin 1s linear infinite;
}

@-webkit-keyframes spin {
  from   { transform: rotate(360deg); }
  to  { transform: rotate(0deg); }
}
@keyframes spin {
  from   { transform: rotate(360deg); }
  to  { transform: rotate(0deg); }
}
<svg class='truck' viewBox='0 0 93 53' xmlns='http://www.w3.org/2000/svg' height="180">
  <g class='chase' fill-rule='evenodd' fill='none'>
    <path d='M32.087 35.263h3.023V5.973h-3.023v29.29z' fill='#EE7C00'></path>
    <path d='M87.84 35.262H5.007v4.065L9.07 43.39h74.707l4.062-4.063v-4.065z' fill='#9B9B9B'></path>
    <path d='M35.11 35.262h57.445v-3.966H35.11v3.966z' fill='#F09E00'></path>
    <path d='M90.393 35.262h2.16v-3.966h-2.16v3.966z' fill='#E2000F'></path>
    <path d='M17.498.493L2.91 15.08v20.182h29.175V.492H17.498z' fill='#FCC400'></path>
    <path d='M29.495 2.905H18.16L6.823 14.24h22.67V2.905z' fill='#575656'></path>
    <path d='M0 35.262h10.014v-3.966H0v3.966z' fill='#F09E00'></path>
    <path d='M5.008 37.294h82.83v-2.032H5.01v2.032z' fill='#575656'></path>
    <path d='M.75 29.858h2.16v-6.995H.75v6.995zM11.015 20.074h3.497v-2.16h-3.497v2.16z' fill='#E2000F'></path>
    <path d='M28.447 35.262h1.05V14.24h-1.05v21.022z' fill='#EE7C00'></path>
    <path d='M53.51 27.23h34.33v4.065H53.51V27.23z' fill='#575656'></path>
  </g>
  <g class='tyreA'>
    <path d='M64.827 36.593a9.61 9.61 0 0 0 0 13.59c3.753 3.754 9.837 3.754 13.59 0a9.61 9.61 0 0 0-13.59-13.59' fill='#1A1A18'></path>
    <path d='M67.287 39.053a6.13 6.13 0 0 0 0 8.67 6.13 6.13 0 1 0 0-8.67' fill='#9B9B9B'></path>
    <path d='M67.287 39.053a6.133 6.133 0 0 0 0 8.67 6.134 6.134 0 0 0 8.67 0l-8.67-8.67z' fill='#C5C5C6'></path>
    <path d='M68.784 40.55a4.012 4.012 0 0 0 5.676 5.677 4.012 4.012 0 0 0-5.676-5.676' fill='#868685'></path>
    <path d='M65.526 37.293A8.62 8.62 0 1 1 77.72 49.486a8.62 8.62 0 0 1-12.192-12.193m-.385-.386c-3.578 3.578-3.578 9.384 0 12.963 3.58 3.58 9.385 3.58 12.964 0 3.578-3.58 3.578-9.385 0-12.963-3.58-3.58-9.386-3.58-12.964 0' fill='#3B3A39'></path>
  </g>
  <g class='tyreB'>
    <path d='M13.038 36.593c-3.754 3.754-3.754 9.838 0 13.59a9.61 9.61 0 0 0 13.59 0c3.754-3.752 3.754-9.836 0-13.59a9.61 9.61 0 0 0-13.59 0' fill='#1A1A18'></path>
    <path d='M15.498 39.054a6.128 6.128 0 0 0 0 8.67 6.13 6.13 0 0 0 8.67 0 6.13 6.13 0 0 0-8.67-8.67' fill='#9B9B9B'></path>
    <path d='M15.498 39.054a6.13 6.13 0 1 0 8.67 8.67l-8.67-8.67z' fill='#C5C5C6'></path>
    <path d='M16.996 40.55a4.012 4.012 0 1 0 5.675 5.677 4.014 4.014 0 0 0-5.674-5.676' fill='#868685'></path>
    <path d='M13.737 37.293a8.622 8.622 0 0 1 12.192 0 8.622 8.622 0 0 1 0 12.192 8.622 8.622 0 0 1-12.193 0 8.622 8.622 0 0 1 0-12.192m-.385-.385a9.164 9.164 0 0 0 0 12.962c3.578 3.58 9.384 3.58 12.962 0a9.164 9.164 0 0 0 0-12.962 9.164 9.164 0 0 0-12.962 0' fill='#3B3A39'></path>
  </g>
  <g class='tyreC'>
    <path d='M44.406 36.593c-3.753 3.754-3.753 9.838 0 13.59 3.754 3.755 9.838 3.755 13.59 0 3.755-3.752 3.755-9.836 0-13.59-3.752-3.753-9.836-3.753-13.59 0' fill='#1A1A18'></path>
    <path d='M46.868 39.054a6.128 6.128 0 0 0 0 8.67 6.128 6.128 0 0 0 8.67 0 6.128 6.128 0 0 0 0-8.67 6.13 6.13 0 0 0-8.67 0' fill='#9B9B9B'></path>
    <path d='M46.868 39.054a6.13 6.13 0 1 0 8.67 8.67l-8.67-8.67z' fill='#C5C5C6'></path>
    <path d='M48.364 40.55a4.014 4.014 0 1 0 0 0' fill='#868685'></path>
    <path d='M45.106 37.293a8.622 8.622 0 0 1 12.192 0 8.622 8.622 0 0 1 0 12.192 8.622 8.622 0 0 1-12.192 0 8.622 8.622 0 0 1 0-12.192m-.385-.385a9.164 9.164 0 0 0 0 12.962c3.58 3.58 9.385 3.58 12.963 0 3.58-3.578 3.58-9.384 0-12.962a9.164 9.164 0 0 0-12.962 0' fill='#3B3A39'></path>
  </g>
</svg>

In the future, you will be able to do:

transform-origin: 50% 50%;
transform-box: fill-box;

But not until transform-box is supported properly in all browsers.



回答2:

I recently encountered the same problem. Wheels wheeled around the entire cart and not around its axis. In all browsers the transform-origin properties helped.

transform-origin: 50% 50% 0px;

But not in Mozilla. For Mozilla i used static values in pixels.

-moz-transform-origin: 136px 110px 0px;

My codepen example



回答3:

You could use this function to save up some time calculating these static positions. Just pass x, y percent values, a selector and execute right in the browser console:

;(function getStaticCoords(x, y, elementId) {
  var coord = $(elementId)[0].getBBox()
  var coordW = coord.width * x / 100
  var coordH = coord.height * y / 100
  return coord.x + coordW + 'px ' + (coord.y + coordH / 2 + 'px')
})(50, 50, '#myDOMElement')