css实现3D长方形,可旋转

本文介绍了一种使用CSS3实现的3D立方体翻转效果,通过精确控制每个面的位置和旋转角度来创建一个交互式的3D立方体。用户可以通过鼠标操作使立方体沿着X轴和Y轴旋转,并提供了自动展示各个面的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上图:

实现过程:

1、长方体六个面 

before,after, top ,buttom,left,right

2、每个面不同旋转角度

before: 向前移动一半width宽度,transform: translateZ(${width/2}px)
after: 向后移动一半width宽度、y轴旋转180度  transform: `translateZ(${-width/2}px) rotateY(180deg)`
top: 以top为轴,x轴旋转90度,向后移动一半宽度 transform-origin: top; transform: `rotateX(90deg) translate(0, ${-width/2}px)`}
bottom: 以bottom为轴,x轴旋90度,向后移动一半宽度, 放缩width/height,width: `${width}px`, height: `${height}px`,transform: `rotateX(90deg) translate(0, ${-width/2}px) scale(0,width/height)`
left: 以left为轴,y轴旋转-90度,向左移动一半宽度,{transform: `rotateY(-90deg) translate(${-width/2}px, 0)`}
right: 以right为轴,y轴旋转90度,向右移动一半宽度,{transform: `rotateY(90deg) translate(${width/2}px, 0)`}
3、在外圈div做旋转
4、代码:box.vue
<template>
    <div class="box-wrap">
        <div class="box" id="box" style="transform: rotateX(0deg) rotateY(0deg);" :style="{width: `${width}px`, height: `${height}px`}" @mousedown="mousedown" @mousemove="mousemove" @mouseup="mouseup" @mouseout="mouseup">
            <div id="face-before" class="face face-before" :style="{transform: `translateZ(${width/2}px)`}">
                <slot name="before" ></slot>
            </div>
            <div id="face-after" class="face face-after" :style="{transform: `translateZ(${-width/2}px) rotateY(180deg)`}">
                <slot name="after"></slot>
            </div>
            <div id="face-top" class="face face-top" :style="{width: `${width}px`, height: `${width}px`, transform: `rotateX(90deg) translate(0, ${-width/2}px)`}">
                <slot name="top"></slot>
            </div>
            <div id="face-bottom" class="face face-bottom" :style="{width: `${width}px`, height: `${height}px`,transform: `rotateX(90deg) translate(0, ${width/2}px) scale(0,width/height)`}">
                <slot name="buttom"></slot>
            </div>
            <div id="face-left" class="face face-left" :style="{transform: `rotateY(-90deg) translate(${-width/2}px, 0)`}" >
                <slot name="left"></slot>
            </div>
            <div id="face-right" class="face face-right" :style="{transform: `rotateY(90deg) translate(${width/2}px, 0)`}">
                <slot name="right"></slot>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: 'box',
    data() {
        return {
            canMove: false,
            startX: 0,
            startY: 0,
            currentDeg: 0,
        }
    },
    props: {
        width: {
            type: Number,
            default: 300,
        },
        height: {
            type: Number,
            default: 300,
        },
    },
    methods: {
        //  mouseenter(ev) { // 按下鼠标
        //     this.canMove = true;
        //     this.startX = ev.clientX;
        //     this.startY = ev.clientY;
        // },
        mousedown(ev) { // 按下鼠标
            this.canMove = true;
            this.startX = ev.clientX;
            this.startY = ev.clientY;
        },
        mousemove(ev) {  // 鼠标移动
            if(this.canMove) {
                const $box = document.getElementById('box');
                const obj = this.getTransform();
                const x = this.startX - ev.clientX;
                const y = this.startY - ev.clientY;
                const newx = (obj.x - (y / this.height * 180));
                const newy = (obj.y - (x / this.width * 180));
                console.log('x / this.width * 90===', x / this.width * 180);
                console.log('newy===', newy);
                this.startX = ev.clientX;
                this.startY = ev.clientY;
                $box.style.transform = `rotateX(-5deg) rotateY(${newy}deg)`;
                this.currentDeg = newy;
            }
        },
        mouseout() { // 鼠标离开
            if(this.canMove) {
                const $box = document.getElementById('box');
                const value = this.currentDeg % 90;
                if(Math.abs(value) >= 45) {
                    $box.style.transform = `rotateX(0deg) rotateY(${this.currentDeg + (90 - value) + 0.01}deg)`;
                }else {
                    $box.style.transform = `rotateX(0deg) rotateY(${this.currentDeg - value + 0.01}deg)`;
                }
                
                this.canMove = false;
            }
        },
        showAuto() {
            const $box = document.getElementById('box');
            $box.style['transform-origin'] = 'center';
            $box.style.transform = `rotateX(-20deg) rotateY(20deg)`;
        },
        showTop() {
            const $box = document.getElementById('box');
            $box.style['transform-origin'] = 'center';
            $box.style.transform = `rotateX(-89.999deg) rotateY(0deg)`;
        },
        showLeft() {
            const $box = document.getElementById('box');
            $box.style['transform-origin'] = 'center';
            $box.style.transform = `rotateX(0deg) rotateY(89.999deg)`;
        },
        mouseup() { // 鼠标离开
            if(this.canMove) {
                const $box = document.getElementById('box');
                const value = this.currentDeg % 90;
                if(Math.abs(value) >= 45) {
                    if(value < 0) {
                        $box.style.transform = `rotateX(0deg) rotateY(${this.currentDeg - (90 - Math.abs(value)) + 0.01}deg)`;
                    }else {
                        $box.style.transform = `rotateX(0deg) rotateY(${this.currentDeg + (90 - Math.abs(value)) + 0.01}deg)`;
                    }
                    
                }else {
                    if(value < 0) {
                        $box.style.transform = `rotateX(0deg) rotateY(${this.currentDeg - value + 0.01}deg)`;
                    }else {
                        $box.style.transform = `rotateX(0deg) rotateY(${this.currentDeg + value + 0.01}deg)`;
                    }
                    
                }
                
                this.canMove = false;
            }
        },
        reset() {
            const $box = document.getElementById('box');
            $box.style.transform = `rotateX(-20deg) rotateY(20deg)`;
        },
        getTransform() {
            const $box = document.getElementById('box');
            const ts = $box.style.transform.split(' ');

            const xs = ts[0].indexOf('X(');
            const xe = ts[0].indexOf('deg');

            const ys = ts[1].indexOf('Y(');
            const ye = ts[1].indexOf('deg');

            const x = ts[0].substring(xs + 2, xe);
            const y = ts[1].substring(ys + 2, ye);
            return {
                x,
                y,
            }
        },
    },
    mounted() {

    },
}
</script>
<style lang="scss" scoped>
    .box-wrap {
        .box { 
            position: relative;
            z-index: 6;
            margin: auto;
            transform-style: preserve-3d;
            transform-origin: center, center;
            transition: transform 1s;
            .face {
                position: absolute;
                width: 100%;
                height: 100%;
                opacity: 0.3;
                font-size: 30px;
                
            }
            .face-before {
                transform: translateZ(150px);
                background-color:  rgb(0, 255, 170);
                text-align: left;
                
            } 
            .face-after {
                transform-origin: center;
                transform: translateZ(-150px) rotateX(-180deg);
                background-color: #0088cc;
            } 
            .face-top {
                transform-origin: top;
                transform: rotateX(90deg) translate(0, -150px);
                background-color: rgb(255, 0, 170);
            } 
            .face-bottom {
                transform-origin: bottom;
                transform: rotateX(-90deg) translate(0, 150px);
                background-color:  rgb(0, 255, 85);
            } 
            .face-left {
                transform-origin: left;
                transform: rotateY(-90deg) translate(-150px, 0);
                background-color: rgb(255, 208, 0);
            }
            .face-right {
                transform-origin: right;
                transform: rotateY(90deg) translate(150px, 0);
                background-color: rgb(255, 208, 0);
            }
        }
    }
</style>


5、使用:

<template>
    <div class="app-home">
        <header class="header">
            <div class="content">
                <div class="header-left">
                    <span class="title">凡夫俗子</span>
                    <span class="desc">我们追寻梦想, 因为那最令人开心</span>
                </div>
                <div class="header-right">

                </div>
            </div>
        </header>
        <box :height="300" :width="600" ref="box">
            <template slot="before">
                <div>before</div>
            </template>
            <template slot="after">
                <div>after</div>
            </template>
            <template slot="left">
                <div>left</div>
            </template>
            <template slot="right">
                <div>right</div>
            </template>
            <template slot="top">
                <div>top</div>
            </template>
            <template slot="bottom">
                <div>bottom</div>
            </template>
        </box>
    </div>
</template>

<script>
import box from '@/web/components/box3.vue'
export default {
    name: 'HelloWorld',
    data () {
        return {
            boxWidth: 1152,
            boxHeight: 600,
        }
    },
    components: {
        box
    },
    methods: {
        goTopClick() {
            this.$refs.box.showTop();
        },
        goLeftClick() {
            this.$refs.box.showLeft();
        },
        showAuto() {
            this.$refs.box.showAuto();
        }
    },
    mounted() {
        this.boxHeight = document.documentElement.clientHeight - 15;
        window.onresize = () => {
            this.boxHeight = document.documentElement.clientHeight - 15;
        };
    }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss">
    .app-home {
        background-color: #f5f5f5;
        .header {
            width: 100%;
            height: 60px;
            margin-bottom: 15px;
            background-color: rgba(255,255,255,.5);
            .content {
                width: 1200px;
                min-width: 1200px;
                margin: auto;
                overflow: auto;
                padding-left: 24px;
                padding-right: 24px;
                
                color: #00bbd3;
                .header-left {
                    .title {
                        display: inline-block;
                        vertical-align: middle;
                        margin-right: 24px;
                        line-height: 60px;
                        font-size: 25px;
                        letter-spacing: 0.2em;
                    }
                    .desc {
                        display: inline-block;
                        vertical-align: middle;
                        line-height: 60px;
                        font-size: 14px;
                    }
                }
                .header-right {
                    font-size: 12px;
                }
            }
        }
        
    }
</style>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值