马黑黑 发表于 2022-12-29 08:18

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 08:19

本帖最后由 马黑黑 于 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:19

本帖最后由 马黑黑 于 2022-12-29 08:23 编辑 <br /><br /><details>
<summary>pic</summary>

</details>

梦油 发表于 2022-12-29 11:01

小姑娘前空翻,哈哈哈……

马黑黑 发表于 2022-12-29 11:25

梦油 发表于 2022-12-29 11:01
小姑娘前空翻,哈哈哈……

还厉害的小姑凉

醉美水芙蓉 发表于 2022-12-29 11:47

醉美水芙蓉 发表于 2022-12-29 11:48

马黑黑 发表于 2022-12-29 13:26

醉美水芙蓉 发表于 2022-12-29 11:47
先为老师的辛苦制作分享点赞!

理解和掌握CSS的3d运动不容易,希望通过此帖,能够帮助大家更轻松地了解XYZ轴以及景深、角度等概念和 transform: rotateX/Y/Z

梦油 发表于 2022-12-29 14:30

马黑黑 发表于 2022-12-29 11:25
还厉害的小姑凉

还是制作者厉害啊。

樵歌 发表于 2022-12-29 14:53

平面转,空间翻,这个小姑娘不简单。

樵歌 发表于 2022-12-29 14:54

但Z轴还是在平面上。{:4_173:}

马黑黑 发表于 2022-12-29 17:40

樵歌 发表于 2022-12-29 14:54
但Z轴还是在平面上。

对,旋转是如此,因为这时,图像和我们的眼睛是平行的。如果是平移,那就不一样了:会变得更大或更小。

马黑黑 发表于 2022-12-29 17:40

樵歌 发表于 2022-12-29 14:53
平面转,空间翻,这个小姑娘不简单。

都是你调教的好

马黑黑 发表于 2022-12-29 17:40

梦油 发表于 2022-12-29 14:30
还是制作者厉害啊。

{:4_173:}

马黑黑 发表于 2022-12-29 17:41

醉美水芙蓉 发表于 2022-12-29 11:48
小妹妹转晕了!哈哈哈!

兜里有糖快拿出来吧

红影 发表于 2022-12-29 19:02

这个好,通过这个,可以更深层次地理解绕各个轴旋转达到的效果了{:4_187:}

红影 发表于 2022-12-29 19:03

非常直观,又生动有趣。黑黑真棒{:4_199:}

马黑黑 发表于 2022-12-29 19:16

红影 发表于 2022-12-29 19:03
非常直观,又生动有趣。黑黑真棒

{:4_205:}

马黑黑 发表于 2022-12-29 19:17

红影 发表于 2022-12-29 19:02
这个好,通过这个,可以更深层次地理解绕各个轴旋转达到的效果了

3D一直是很抽象的,所以弄个

樵歌 发表于 2022-12-29 20:14

马黑黑 发表于 2022-12-29 17:40
对,旋转是如此,因为这时,图像和我们的眼睛是平行的。如果是平移,那就不一样了:会变得更大或更小。

嗯那,这时Z轴看眼应当是一线{:4_189:}
页: [1] 2
查看完整版本: transform变形之3d旋转演示