首页 > 解决方案 > 如何让 translateZ 在 svg 组中工作?

问题描述

我创建了一个 svg 图像动画。我正在尝试使用鼠标悬停来制作一些不错的效果。我想根据鼠标位置移动 svg。到目前为止,旋转部分工作正常。但我也想<g>在 z 轴(弹出)中移动 svg 的内部,以便它们以“不同的层”出现。应该可以translateZ()。但我无法让它工作。

const container = document.querySelector('.container');
const image = document.querySelector('.image');

const sun = document.querySelector('.sun');
const cloudBehind = document.querySelector('.cloud-center');
const cloudLeft = document.querySelector('.cloud-left');
const cloudRight = document.querySelector('.cloud-right');

const devideAxis = 10;

container.addEventListener('mousemove', e => {
  let xAxis = ~(window.innerWidth / 2 - e.pageX) / devideAxis;
  let yAxis = (window.innerHeight / 2 - e.pageY) / devideAxis;
  
    image.style.transform = `rotateY(${xAxis}deg) rotateX(${yAxis}deg)`;
});

container.addEventListener('mouseenter', e => {
    image.style.transition = 'none';
  //popout
  cloudLeft.style.transform = 'translateZ(400px)'
})

container.addEventListener('mouseleave', e => {
    image.style.transition = 'all 0.5s ease';
    image.style.transform = `rotateY(0deg) rotateX(0deg)`
  
  cloudLeft.style.transform = 'translateZ(0)'
})
body,html {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  perspective: 300px;
}

.container {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.image {
  width: 50%;
  transform-style: preserve-3d;
}

.cloud-left {
  transition: all .5s ease-out
}

.cloud-left,
.cloud-right,
.cloud-center {
  transition: transform .5s;
}

.cloud-center{
  fill:url(#CLOUD-CENTER);
}
.cloud-right{
  fill:url(#CLOUD-FRONT);
}
.cloud-left{
  fill:url(#CLOUD-FRONT);
}
.sun{
  fill:url(#SUN);
}
.shine{
  fill:url(#SHINE);
}
<div class="container">
  <div class="image">
    <?xml version="1.0" encoding="utf-8"?>
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
       viewBox="0 0 500 250" >
    
    
    <g id="wheather">
      <radialGradient id="SHINE" cx="100" cy="100" r="100" gradientUnits="userSpaceOnUse">
        <stop  offset="0.7568" style="stop-color:#FFFFFF"/>
        <stop  offset="1" style="stop-color:#FFF3AB"/>
      </radialGradient>
      <linearGradient id="SUN" gradientUnits="userSpaceOnUse" x1="27.6083" y1="98.0519" x2="169.5758" y2="98.0519">
        <stop  offset="0" style="stop-color:#FFF3AB"/>
        <stop  offset="1" style="stop-color:#FFF2C0"/>
      </linearGradient>
      <linearGradient id="CLOUD-CENTER" gradientUnits="userSpaceOnUse" x1="0" y1="66.2549" x2="288.0558" y2="66.2549">
        <stop  offset="0" style="stop-color:#8EABBF"/>
        <stop  offset="1" style="stop-color:#ECF1F7"/>
      </linearGradient>
      <linearGradient id="CLOUD-FRONT" gradientUnits="userSpaceOnUse" x1="0" y1="62.1091" x2="294.4617" y2="62.1091">
        <stop  offset="5.759445e-07" style="stop-color:#FFFFFF"/>
        <stop  offset="1" style="stop-color:#C5D6E5"/>
      </linearGradient>
      
      
      
      <!-- SUN -->
      <g transform="translate(250 0)" class="sun">
        <path class="shine" d="M162.4,147.8l22,0.9l-9.8-15.5c-0.2-0.5-0.5-1-0.8-1.5v0c-3.1-4.9-1.6-11.1,3-14.2l20.3-8.1l-14.9-9.9
          c-0.5-0.5-1-0.9-1.5-1.3h0c-4.9-3.3-6-9.8-2.8-14.5l15-15.3l-17.3-2.9c-0.7-0.3-1.4-0.5-2.2-0.6h0c-6-1-9.7-6.9-8.4-12.6l7.3-19.6
          l-16.9,4.3c-0.7,0-1.5,0.1-2.2,0.3h0c-6.3,1.6-12.5-2.9-12.9-9.4v0c0-0.2,0-0.3,0-0.4l-1.2-19.1l-13.8,10.9
          c-0.6,0.3-1.1,0.7-1.7,1.1c-5.1,4-12.6,2.4-15.6-3.3l0,0c-0.2-0.5-0.5-0.9-0.8-1.3L98.6,0l-8.4,16c-0.3,0.4-0.6,0.9-0.8,1.3v0
          c-3,5.8-10.5,7.4-15.6,3.3h0c-0.5-0.4-1.1-0.8-1.7-1.1L58.3,8.6l-1.2,19.1c0,0.1,0,0.3,0,0.4v0c-0.4,6.5-6.6,11-12.9,9.4h0
          c-0.8-0.2-1.5-0.3-2.2-0.3l-16.9-4.3l7.3,19.6c1.3,5.7-2.4,11.6-8.4,12.6h0c-0.8,0.1-1.5,0.3-2.2,0.6L4.3,68.5l15,15.3
          c3.2,4.7,2.1,11.2-2.8,14.5c-0.6,0.4-1.1,0.8-1.5,1.3L0,109.5l20.3,8.1c4.6,3,6.1,9.3,3,14.2l0,0c-0.3,0.5-0.6,1-0.8,1.5l-9.8,15.5
          l22-0.9c5.4,0.9,9.3,6,8.4,11.7v0c0,0.3-0.1,0.6-0.1,0.9l-2.8,19l19.7-9.8c5-1.3,10.3,1.3,12.2,6.1l5.7,20.4l13.8-16.7
          c3.9-3.4,9.7-3.4,13.5,0l13.8,16.7l5.7-20.4c2-4.9,7.3-7.4,12.2-6.1l19.7,9.8l-2.8-19c0-0.3,0-0.6-0.1-0.9v0
          C153.2,153.8,157,148.7,162.4,147.8z">
          <animateTransform 
            attributeName="transform"
            attributeType="XML"
            type="rotate"
            from="0 100 100"
            to="360 100 100"
            dur="80s"
            repeatCount="indefinite"
          />

        </path>
        <circle class="sun-inside" cx="98.6" cy="98.1" r="71"/>
      </g>
      <!-- / SUN -->
      
      
      
      <!-- CLOUD BEHIND -->
      <g transform="translate(70 70)">
        <path class="cloud-center" style="transform: " d="M261.5,79.4c-3.4,0-6.6,0.6-9.6,1.8c-1.9-5.5-6-10-11.3-12.5c0-0.2,0-0.3,0-0.5c0-27.1-21.9-49-49-49
          c-0.6,0-1.2,0-1.8,0c-9-11.7-23.1-19.2-39-19.2c-18,0-33.8,9.7-42.3,24.1c-3.8-3.1-8.6-5-13.8-5c-11.1,0-20.3,8.4-21.6,19.2
          c-3.7-1.1-7.7-1.7-11.7-1.7C39,36.6,21,54.6,21,76.9c0,2.8,0.3,5.6,0.9,8.3C9.6,86.1,0,96.3,0,108.8c0,13.1,10.6,23.7,23.7,23.7
          h237.8c14.7,0,26.6-11.9,26.6-26.6S276.2,79.4,261.5,79.4z">
          <animateMotion
            path="M50,0 -50,0 50,0 z"
            dur="80s"
            repeatCount="indefinite"
          />
        </path>
      </g>
      <!-- / CLOUD BEHIND -->
      
      
      
      <!-- CLOUD LEFT -->
      <g transform="translate(10 126)">
        <path class="cloud-left" d="M270.4,76.2C270.4,76.2,270.4,76.2,270.4,76.2c-1.1-22-19.3-39.6-41.6-39.6c-5.1,0-9.9,0.9-14.4,2.6
          C206.9,16.4,185.5,0,160.2,0c-20.6,0-38.6,10.9-48.6,27.3c-4.6-1.5-9.4-2.3-14.5-2.3c-23.4,0-42.8,16.9-46.7,39.1
          c-5.1-3.3-11.2-5.2-17.7-5.2C14.6,58.9,0,73.5,0,91.6c0,18,14.6,32.7,32.7,32.7h237.8c13.3,0,24-10.8,24-24
          C294.5,86.9,283.7,76.2,270.4,76.2z M194.9,102.4h-0.2c0.1,0,0.1-0.1,0.2-0.1C194.9,102.4,194.9,102.4,194.9,102.4z">
          <animateMotion
            path="M30,0 0,0 00,0 30,0 z"
            dur="15s"
            repeatCount="indefinite"
          />
        </path>
      </g>
      <!-- / CLOUD LEFT -->



      <!-- CLOUD RIGHT -->
      <g transform="translate(260 140)">
        <path class="cloud-right" d="M228.8,73.7c0-19.9-16.1-36-36-36c-3.5,0-6.8,0.5-10,1.4c-4.4-18.7-21.2-32.7-41.3-32.7c-10.7,0-20.5,4-28,10.6
          C104.6,6.6,91.4,0,76.7,0C49.9,0,28.3,21.7,28.3,48.4c0,1.6,0.1,3.2,0.2,4.8c-0.1,0-0.2,0-0.2,0C12.7,53.2,0,65.9,0,81.5
          s12.7,28.3,28.3,28.3H198v-0.4C215.4,106.8,228.8,91.8,228.8,73.7z">
          <animateMotion
            path="M-40,0 0,0 -100,0 -40,0 z"
            dur="60s"
            repeatCount="indefinite"
          />
        </path>
      </g>
      <!-- / CLOUD RIGHT -->
      
      
    </g>
    </svg>
  </div>
</div>

主要代码内容:

所以我有body,哪个有perspective: 300px;。然后我有.imagewhich hastransform-style: preserve-3d;和在那个元素里面我有<g>'s with classes。

例如,我有一个.cloud-left.

所以结构基本上是:

<body>
  <div class="container">
    <div class="image">
      <svg>
        <g id="wheather">
          <g class="cloud-left">...</g>

          ...

       </g>
      </svg>
    </div>
  </div>
</body>

在javascript中我有这个(缩短,要查看所有代码,请参阅上面的小提琴):

const cloudLeft = document.querySelector('.cloud-left'); // get the element

container.addEventListener('mouseenter', e => {
  //popout
  cloudLeft.style.transform = 'translateZ(400px)'
})

container.addEventListener('mouseleave', e => {
  //popback
  cloudLeft.style.transform = 'translateZ(0)'
})

但这不能按我的意愿工作。

我也尝试设置哪个是其他的直接父transform-style: preserve-3d;级,但没有区别。<g id="weather"><g>

我没有<g>在 z 轴上移动/弹出。我是否遗漏了 svg 中的某些内容,或者这在 svg 组中不起作用?

我有另一个可行的例子,但它不是 svg:https ://jsfiddle.net/saturday99/94o5j8ts/

标签: csstransitionpreserve-3d

解决方案


好的,正如我所怀疑的那样。它适用于 svg 而不是组/路径。如图所示,路径/组仅是 2D 的。但是 svg 可以制作 3D 并继续使用translateZ。下面是未来寻找答案的人的答案。附言。代码可以稍微清理一下,但它可以工作。

因此,基本结构现在被分成许多 svg,而不是一个包含许多组的 svg:

<body>
  <div class="container">
    <div class="image">
      <svg class="sun">
        <g>

          ...

       </g>
      </svg>
      <svg class="cloud-left">
        <g>

          ...

       </g>
      </svg>

      ...

    </div>
  </div>
</body>

这是“结局”代码和解决方案:https ://jsfiddle.net/saturday99/fkrh6bzm/ 。随意分叉代码。


推荐阅读