transform变形之3d旋转演示
本帖最后由 马黑黑 于 2022-12-29 20:33 编辑 <br /><br /><style>#papa { margin: 0 0 0 calc(50% - 581px); width: 1000px; height: 640px; background: snow linear-gradient( to left top,hsla(30, 70%, 60%, .6),hsla(125,30%,30%,.55)); box-shadow: 3px 3px 20px #000; display: grid; place-items: center start; grid-template-areas: 'tit tit' 'set spic' 'code spic'; padding: 10px; font: normal 14px sans-serif; position: relative; opacity: .95; z-index: 1; }
#spic { grid-area: spic; width: 680px; height: 545px; display: grid; place-items: center; perspective:1500px; }
#spic > img { transform-style: preserve-3d; width: 360px; box-shadow: 2px 4px 8px gray; cursor: pointer; }
#set { grid-area: set; width: 260px; border: 1px solid #ccc; border-radius: 6px; }
#tit { grid-area: tit; width: 100%; margin: 0; padding: 4px; height: 2em; font: bold 1.8em/2em sans-serif; text-align: center; color: #555; text-shadow: 1px 1px 2px #000; letter-spacing: 2px; }
#code { grid-area: code; width: 260px; border: 1px solid #ccc; border-radius: 6px; }
#codebox { font: normal 14px sans-serif; border: none; outline: none; resize: none; width: 250px; height: 100px; padding: 4px; background: none; }
#papa input { outline: none; }
#papa fieldset { padding: 6px; }
#papa p { padding: 6px 0; display: flex; align-items: center; }
@keyframes rotX { from { transform: rotateX(-360deg); } to { transform: rotateX(360deg); } }
@keyframes rotY { from { transform: rotateY(-360deg); } to { transform: rotateY(360deg); } }
@keyframes rotZ { from { transform: rotateZ(-360deg); } to { transform: rotateZ(360deg); } }
</style>
<div id="papa">
<h2 id="tit">3d旋转演示</h2>
<div id="spic"><img id="pic" src="https://www.huachaowang.com/forum.php?mod=attachment&aid=NDM4MjN8MjJkM2ZjMmJ8MTY3MjMxNzE3MHw3MTMwfDY1NTI4&noupdate=yes" title="沿当前轴自动旋转" alt="" /></div>
<fieldset id="set">
<legend>设置轴、角度与景深:</legend>
<p><input id="rd1" class="radio" type="radio" name="rd" checked /> <label for="rd1" id="rd1Msg">X轴</label> <input id="rd2" class="radio" type="radio" name="rd" /> <label for="rd1">全部</label></p>
<p><label>X轴 : </label><input class="range" min="-360" max="360" type="range" /> <span class="rg">0deg</span></p>
<p><label>Y轴 : </label><input class="range" min="-360" max="360" type="range" /> <span class="rg">0deg</span></p>
<p><label>Z轴 : </label><input class="range" min="-360" max="360" type="range" /> <span class="rg">0deg</span></p>
<hr>
<p><label>景深 : </label><input id="jingshen" min="500" max="3000" type="range" /> <span id="jingshenMsg">1000px</span></p>
<hr>
<p style="justify-content: flex-end;"><input type="button" onclick="defaultset();" value=" 重置 " /></p>
</fieldset>
<fieldset id="code">
<legend>代码:</legend>
<textarea id="codebox">rotateX(0deg)</textArea>
</fieldset>
</div>
<script>
let ranges = document.querySelectorAll('.range'),
radios = document.querySelectorAll('.radio'),
rgs = document.querySelectorAll('.rg');
let rangeID = 0;
let rotAr = ['X','Y','Z'];
let defaultset = () => {
rd1.checked = true;
rd1Msg.innerText = 'X轴';
for(key in ranges) {
ranges.value = '0';
rgs.innerHTML = '0deg';
}
let jings = spic.style.perspective = '1500px';
jingshenMsg.innerText = jings;
jingshen.value = parseInt(jings);
pic.style.transform = 'rotateX(0deg)';
codebox.value = 'transform: ' + pic.style.transform;
};
let setChange = () => {
if (rd1.checked) {
pic.style.transform = `rotate${rotAr}(${ranges.value}deg)`;
} else {
pic.style.transform = `rotateX(${ranges.value}deg) rotateY(${ranges.value}deg) rotateZ(${ranges.value}deg)`;
}
codebox.value = 'transform: ' + pic.style.transform;
}
let autoRot = () => {
let aniName = 'rot' + rotAr;
pic.style.animation = aniName + ' 10s forwards linear';
setTimeout('pic.style.animation = ""',10000);
};
rd1.onchange = () => setChange();
rd2.onchange = () => setChange();
ranges.forEach( (item,key) => {
item.onchange = () => {
rangeID = key;
rd1Msg.innerText = rotAr + '轴';
rgs.innerText = item.value + 'deg';
setChange();
};
});
jingshen.onchange = () => spic.style.perspective = jingshenMsg.innerText = jingshen.value + 'px';
codebox.oninput = () =>pic.style.cssText += codebox.value;
defaultset();
pic.onclick = () => autoRot();
</script>
本帖最后由 马黑黑 于 2022-12-29 11:27 编辑
本帖可以帮助理解 transform 变形中的 rotateX、rotateY、rotateZ 的具体运作。具体操作:
一、单轴旋转
程序启动时默认轴是X轴,改变当前旋转轴,请点击或滑动对应轴滑杆。滑杆取值范围从 -360度 ~ 360 度,图片的单轴转动实时对应于相应的滑杆值。滑杆控制可用鼠标操作,也可以用键盘左右方向键操作。
景深(perspective)值从 500px ~ 3000px 之间,可以通过滑杆改变。景深也称视距,它是元素3d效果的依托,但景深对 rotateZ 不会产生直接效果,原理与几何有关——Z轴是纵深方向的轴,自屏幕里景深最深点到观察者眼睛之间,元素与之垂直,因此在Z轴某一点上所做的 rotateZ 旋转,观察者捕捉不到因景深的实时变化而产生的在Z轴上的 rotateZ 的形态上的变化。所以,不要奇怪,当图片 rotateZ 一定角度后,改变景深看不到有什么变化。
二、多轴旋转
点选“全部”选项按钮,图片随后要做的旋转将是多轴旋转,可以通过设置各轴的值观察多轴旋转效果。
三、自动旋转
自动旋转仅基于单轴,即当前轴。点击或滑动滑杆,可更换当前轴。
自动旋转需要通过单击图片触发,图片正在自动旋转以外的任何时候,都可点击图片触发图片的自动旋转。
自动旋转对观察单轴旋转,有一定的帮助。
三、代码框触发旋转
程序界面左下角的代码框支持手动输入,输入的语句若符合CSS语法规范,图片会在输入当中实时响应。
在代码框输入代码对图片产生作用。所输入的代码不局限于 transform,可以试一下 width: 600px; 看看。
程序写的有些匆忙,错误与不足在所难免,又发现的请及时反馈,谢谢。
本帖最后由 马黑黑 于 2022-12-29 08:23 编辑 <br /><br /><details>
<summary>pic</summary>
</details>
小姑娘前空翻,哈哈哈…… 梦油 发表于 2022-12-29 11:01
小姑娘前空翻,哈哈哈……
还厉害的小姑凉 醉美水芙蓉 发表于 2022-12-29 11:47
先为老师的辛苦制作分享点赞!
理解和掌握CSS的3d运动不容易,希望通过此帖,能够帮助大家更轻松地了解XYZ轴以及景深、角度等概念和 transform: rotateX/Y/Z 马黑黑 发表于 2022-12-29 11:25
还厉害的小姑凉
还是制作者厉害啊。 平面转,空间翻,这个小姑娘不简单。 但Z轴还是在平面上。{:4_173:} 樵歌 发表于 2022-12-29 14:54
但Z轴还是在平面上。
对,旋转是如此,因为这时,图像和我们的眼睛是平行的。如果是平移,那就不一样了:会变得更大或更小。 樵歌 发表于 2022-12-29 14:53
平面转,空间翻,这个小姑娘不简单。
都是你调教的好 梦油 发表于 2022-12-29 14:30
还是制作者厉害啊。
{:4_173:} 醉美水芙蓉 发表于 2022-12-29 11:48
小妹妹转晕了!哈哈哈!
兜里有糖快拿出来吧 这个好,通过这个,可以更深层次地理解绕各个轴旋转达到的效果了{:4_187:} 非常直观,又生动有趣。黑黑真棒{:4_199:} 红影 发表于 2022-12-29 19:03
非常直观,又生动有趣。黑黑真棒
{:4_205:} 红影 发表于 2022-12-29 19:02
这个好,通过这个,可以更深层次地理解绕各个轴旋转达到的效果了
3D一直是很抽象的,所以弄个 马黑黑 发表于 2022-12-29 17:40
对,旋转是如此,因为这时,图像和我们的眼睛是平行的。如果是平移,那就不一样了:会变得更大或更小。
嗯那,这时Z轴看眼应当是一线{:4_189:}
页:
[1]
2