|
@@ -0,0 +1,166 @@
|
|
|
+<template>
|
|
|
+ <div class="air-door-container" @click="toggleDoor">
|
|
|
+ <!-- 添加3D变换专用包装器 -->
|
|
|
+ <div class="svg-3d-wrapper">
|
|
|
+ <svg viewBox="0 0 800 400" width="800" height="400">
|
|
|
+ <!-- 定义渐变和图案 -->
|
|
|
+ <defs>
|
|
|
+ <linearGradient id="tunnelGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
|
+ <stop offset="0%" stop-color="#222" />
|
|
|
+ <stop offset="50%" stop-color="#444" />
|
|
|
+ <stop offset="100%" stop-color="#222" />
|
|
|
+ </linearGradient>
|
|
|
+ <pattern id="tunnelBottomPattern" width="40" height="40" patternUnits="userSpaceOnUse">
|
|
|
+ <!-- <rect width="40" height="40" fill="#333" fill-opacity="0.8" /> -->
|
|
|
+ </pattern>
|
|
|
+ </defs>
|
|
|
+
|
|
|
+ <!-- 巷道顶部 - 只有左上和右上圆角 -->
|
|
|
+ <path d="M0,20 A20,20 0 0 1 20,0 H780 A20,20 0 0 1 800,20 V120 H0 Z"
|
|
|
+ fill="url(#tunnelGradient)" />
|
|
|
+
|
|
|
+ <!-- 巷道底部 -->
|
|
|
+ <rect x="0" y="120" width="800" height="300" fill="url(#tunnelBottomPattern)" />
|
|
|
+
|
|
|
+ <!-- 门框 -->
|
|
|
+ <rect x="8" y="128" width="784" height="272" rx="20" ry="10" fill="none" stroke="#8B4513" stroke-width="8" />
|
|
|
+
|
|
|
+ <!-- 左门 -->
|
|
|
+ <g
|
|
|
+ :class="{ 'left-door-open': isOpen, 'left-door-closed': !isOpen }"
|
|
|
+ transform-origin="left center"
|
|
|
+ >
|
|
|
+ <rect
|
|
|
+ x="16"
|
|
|
+ y="136"
|
|
|
+ width="384"
|
|
|
+ height="256"
|
|
|
+
|
|
|
+ fill="#A9A9A9"
|
|
|
+ stroke="#696969"
|
|
|
+ stroke-width="2"
|
|
|
+ />
|
|
|
+ <line x1="200" y1="146" x2="200" y2="392" stroke="#696969" stroke-width="1" />
|
|
|
+ <line x1="16" y1="264" x2="399" y2="264" stroke="#696969" stroke-width="1" />
|
|
|
+ </g>
|
|
|
+
|
|
|
+ <!-- 右门 -->
|
|
|
+ <g
|
|
|
+ :class="{ 'right-door-open': isOpen, 'right-door-closed': !isOpen }"
|
|
|
+ transform-origin="right center"
|
|
|
+ >
|
|
|
+ <rect
|
|
|
+ x="400"
|
|
|
+ y="136"
|
|
|
+ width="384"
|
|
|
+ height="256"
|
|
|
+ fill="#A9A9A9"
|
|
|
+ stroke="#696969"
|
|
|
+ stroke-width="2"
|
|
|
+ />
|
|
|
+ <line x1="584" y1="146" x2="584" y2="392" stroke="#696969" stroke-width="1" />
|
|
|
+ <line x1="400" y1="264" x2="783" y2="264" stroke="#696969" stroke-width="1" />
|
|
|
+ </g>
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ <div class="status">
|
|
|
+ {{ isOpen ? '风门开启' : '风门关闭' }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref } from 'vue';
|
|
|
+
|
|
|
+const isOpen = ref(false);
|
|
|
+
|
|
|
+const toggleDoor = () => {
|
|
|
+ isOpen.value = !isOpen.value;
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.air-door-container {
|
|
|
+ position: relative;
|
|
|
+ width: 800px;
|
|
|
+ height: 400px;
|
|
|
+ margin: 0 auto;
|
|
|
+}
|
|
|
+
|
|
|
+.svg-3d-wrapper {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ perspective: 800px; /* 透视距离 */
|
|
|
+ transform-style: preserve-3d;
|
|
|
+}
|
|
|
+
|
|
|
+svg {
|
|
|
+ display: block;
|
|
|
+ overflow: visible; /* 确保旋转内容不被裁剪 */
|
|
|
+ transform-style: preserve-3d;
|
|
|
+}
|
|
|
+
|
|
|
+/* 门元素3D优化 */
|
|
|
+g {
|
|
|
+ transform-box: fill-box;
|
|
|
+ backface-visibility: visible;
|
|
|
+ will-change: transform; /* 性能优化 */
|
|
|
+}
|
|
|
+
|
|
|
+/* 左门打开动画 */
|
|
|
+@keyframes leftDoorOpen {
|
|
|
+ from { transform: translateZ(1px) rotateY(0deg); }
|
|
|
+ to { transform: translateZ(1px) rotateY(-75deg); }
|
|
|
+}
|
|
|
+
|
|
|
+/* 左门关闭动画 */
|
|
|
+@keyframes leftDoorClose {
|
|
|
+ from { transform: translateZ(1px) rotateY(-75deg); }
|
|
|
+ to { transform: translateZ(1px) rotateY(0deg); }
|
|
|
+}
|
|
|
+
|
|
|
+/* 右门打开动画 */
|
|
|
+@keyframes rightDoorOpen {
|
|
|
+ from { transform: translateZ(1px) rotateY(0deg); }
|
|
|
+ to { transform: translateZ(1px) rotateY(-75deg); }
|
|
|
+}
|
|
|
+
|
|
|
+/* 右门关闭动画 */
|
|
|
+@keyframes rightDoorClose {
|
|
|
+ from { transform: translateZ(1px) rotateY(-75deg); }
|
|
|
+ to { transform: translateZ(1px) rotateY(0deg); }
|
|
|
+}
|
|
|
+
|
|
|
+/* 左门打开状态 */
|
|
|
+.left-door-open {
|
|
|
+ animation: leftDoorOpen 2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
|
|
+}
|
|
|
+
|
|
|
+/* 左门关闭状态 */
|
|
|
+.left-door-closed {
|
|
|
+ animation: leftDoorClose 2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
|
|
+}
|
|
|
+
|
|
|
+/* 右门打开状态 */
|
|
|
+.right-door-open {
|
|
|
+ animation: rightDoorOpen 2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
|
|
+}
|
|
|
+
|
|
|
+/* 右门关闭状态 */
|
|
|
+.right-door-closed {
|
|
|
+ animation: rightDoorClose 2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
|
|
+}
|
|
|
+
|
|
|
+.status {
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #fff;
|
|
|
+ text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
|
|
|
+ pointer-events: none; /* 防止遮挡点击事件 */
|
|
|
+}
|
|
|
+</style>
|