CSS 3D等距简单旋转变换
CSS 3D isometric simple rotation transform
我正在尝试制作一个 CSS 小动画,其中包含 door
折叠动画。我使用 SVG 作为基础,对其进行等距变换,现在我希望橙色方块像 3D 一样折叠 space。
我尝试过透视、倾斜、变换 3D 但失败了。
#svgbox {
position: absolute;
transform: rotate(-45deg) skew(15deg, 15deg);
left: 200px;
}
#rect5 {
animation: rect5anim 3s ease forwards;
transform-origin: 0% 50%;
perspective: 1500px;
/*transform-style: preserve-3d;*/
}
@keyframes rect5anim {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(-180deg);
}
}
<div id="svgbox">
<svg viewBox="0 0 1200 1200" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="123.587715%" y1="49.9380835%" x2="24.1186732%" y2="49.9380835%" id="linearGradient-1" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F59427" offset="28.32%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="126.190394%" y1="50.060688%" x2="22.2418719%" y2="50.060688%" id="linearGradient-2" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="122.778325%" y1="50.0081081%" x2="24.5036946%" y2="50.0081081%" id="linearGradient-3" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#98C54C" offset="14.59%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
<linearGradient x1="-27.65086%" y1="50.0081081%" x2="72.4520885%" y2="50.0081081%" id="linearGradient-4" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
</defs>
<g>
<rect id="rect1" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect2" x="201" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect3" x="401" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect4" x="601" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect5" x="801" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect6" y="201" width="200" height="200" fill="url(#linearGradient-3)" />
<rect id="rect7" y="401" width="200" height="200" fill="url(#linearGradient-4)" />
<rect id="rect8" y="601" width="200" height="200" fill="url(#linearGradient-4)" />
</g>
</svg>
</div>
问题是因为您使用的是 perspective
属性 而不是将透视应用于变换 (transform: perspective(x)
)。 perspective
属性 不影响元素的渲染。它只创建一个 3D space 供其子项使用。您可以在 this CSS Tricks Article.
中找到更多相关信息
另一件可能值得注意的事情是 transform-origin
的百分比值在 Firefox 中似乎效果不佳。它需要基于 px 的值,并且它也应该参考 SVG 的 (0,0)。因此,对于 #rect5
,设置 transform-origin: 801px 100px
会在 FF 中产生预期的输出。 This CSS Tricks Article 有关于这个特定问题的详细信息。
下面是一个片段,它使用带有透视图的变换来产生所需的效果。
#svgbox {
position: absolute;
transform: rotate(-45deg) skew(15deg, 15deg);
left: 200px;
}
#rect5 {
animation: rect5anim 3s ease forwards;
transform-origin: 801px 100px;
transform-style: preserve-3d;
}
@keyframes rect5anim {
0% {
transform: perspective(1000px) rotateY(0deg);
}
100% {
transform: perspective(1000px) rotateY(180deg);
}
}
<div id="svgbox">
<svg viewBox="0 0 1200 1200" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="123.587715%" y1="49.9380835%" x2="24.1186732%" y2="49.9380835%" id="linearGradient-1" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F59427" offset="28.32%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="126.190394%" y1="50.060688%" x2="22.2418719%" y2="50.060688%" id="linearGradient-2" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="122.778325%" y1="50.0081081%" x2="24.5036946%" y2="50.0081081%" id="linearGradient-3" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#98C54C" offset="14.59%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
<linearGradient x1="-27.65086%" y1="50.0081081%" x2="72.4520885%" y2="50.0081081%" id="linearGradient-4" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
</defs>
<g>
<rect id="rect1" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect2" x="201" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect3" x="401" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect4" x="601" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect5" x="801" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect6" y="201" width="200" height="200" fill="url(#linearGradient-3)" />
<rect id="rect7" y="401" width="200" height="200" fill="url(#linearGradient-4)" />
<rect id="rect8" y="601" width="200" height="200" fill="url(#linearGradient-4)" />
</g>
</svg>
</div>
我正在尝试制作一个 CSS 小动画,其中包含 door
折叠动画。我使用 SVG 作为基础,对其进行等距变换,现在我希望橙色方块像 3D 一样折叠 space。
我尝试过透视、倾斜、变换 3D 但失败了。
#svgbox {
position: absolute;
transform: rotate(-45deg) skew(15deg, 15deg);
left: 200px;
}
#rect5 {
animation: rect5anim 3s ease forwards;
transform-origin: 0% 50%;
perspective: 1500px;
/*transform-style: preserve-3d;*/
}
@keyframes rect5anim {
0% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(-180deg);
}
}
<div id="svgbox">
<svg viewBox="0 0 1200 1200" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="123.587715%" y1="49.9380835%" x2="24.1186732%" y2="49.9380835%" id="linearGradient-1" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F59427" offset="28.32%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="126.190394%" y1="50.060688%" x2="22.2418719%" y2="50.060688%" id="linearGradient-2" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="122.778325%" y1="50.0081081%" x2="24.5036946%" y2="50.0081081%" id="linearGradient-3" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#98C54C" offset="14.59%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
<linearGradient x1="-27.65086%" y1="50.0081081%" x2="72.4520885%" y2="50.0081081%" id="linearGradient-4" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
</defs>
<g>
<rect id="rect1" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect2" x="201" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect3" x="401" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect4" x="601" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect5" x="801" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect6" y="201" width="200" height="200" fill="url(#linearGradient-3)" />
<rect id="rect7" y="401" width="200" height="200" fill="url(#linearGradient-4)" />
<rect id="rect8" y="601" width="200" height="200" fill="url(#linearGradient-4)" />
</g>
</svg>
</div>
问题是因为您使用的是 perspective
属性 而不是将透视应用于变换 (transform: perspective(x)
)。 perspective
属性 不影响元素的渲染。它只创建一个 3D space 供其子项使用。您可以在 this CSS Tricks Article.
另一件可能值得注意的事情是 transform-origin
的百分比值在 Firefox 中似乎效果不佳。它需要基于 px 的值,并且它也应该参考 SVG 的 (0,0)。因此,对于 #rect5
,设置 transform-origin: 801px 100px
会在 FF 中产生预期的输出。 This CSS Tricks Article 有关于这个特定问题的详细信息。
下面是一个片段,它使用带有透视图的变换来产生所需的效果。
#svgbox {
position: absolute;
transform: rotate(-45deg) skew(15deg, 15deg);
left: 200px;
}
#rect5 {
animation: rect5anim 3s ease forwards;
transform-origin: 801px 100px;
transform-style: preserve-3d;
}
@keyframes rect5anim {
0% {
transform: perspective(1000px) rotateY(0deg);
}
100% {
transform: perspective(1000px) rotateY(180deg);
}
}
<div id="svgbox">
<svg viewBox="0 0 1200 1200" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="123.587715%" y1="49.9380835%" x2="24.1186732%" y2="49.9380835%" id="linearGradient-1" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F59427" offset="28.32%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="126.190394%" y1="50.060688%" x2="22.2418719%" y2="50.060688%" id="linearGradient-2" gradientTransform="rotate(45)">
<stop stop-color="#F6851F" offset="0%"></stop>
<stop stop-color="#F5BB42" offset="100%"></stop>
</linearGradient>
<linearGradient x1="122.778325%" y1="50.0081081%" x2="24.5036946%" y2="50.0081081%" id="linearGradient-3" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#98C54C" offset="14.59%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
<linearGradient x1="-27.65086%" y1="50.0081081%" x2="72.4520885%" y2="50.0081081%" id="linearGradient-4" gradientTransform="rotate(45)">
<stop stop-color="#8CC151" offset="0%"></stop>
<stop stop-color="#D7DF23" offset="99%"></stop>
</linearGradient>
</defs>
<g>
<rect id="rect1" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect2" x="201" width="200" height="200" fill="url(#linearGradient-1)" />
<rect id="rect3" x="401" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect4" x="601" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect5" x="801" width="200" height="200" fill="url(#linearGradient-2)" />
<rect id="rect6" y="201" width="200" height="200" fill="url(#linearGradient-3)" />
<rect id="rect7" y="401" width="200" height="200" fill="url(#linearGradient-4)" />
<rect id="rect8" y="601" width="200" height="200" fill="url(#linearGradient-4)" />
</g>
</svg>
</div>