Procházet zdrojové kódy

feat(maotu): 增加拓扑预览方向切换功能

Zimo před 2 dny
rodič
revize
f1ec13b923
1 změnil soubory, kde provedl 79 přidání a 1 odebrání
  1. 79 1
      src/views/maotu/preview.vue

+ 79 - 1
src/views/maotu/preview.vue

@@ -1,6 +1,25 @@
 <template>
-  <div class="preview-page">
+  <div :class="['preview-page', { 'preview-page--switched': orientationSwitched }]">
     <mt-preview ref="MtPreviewRef" @on-event-call-back="onEventCallBack" />
+    <button
+      class="orientation-toggle"
+      type="button"
+      aria-label="切换显示方向"
+      @click="orientationSwitched = !orientationSwitched">
+      <svg
+        class="orientation-toggle__icon"
+        aria-hidden="true"
+        viewBox="0 0 24 24"
+        fill="none">
+        <path
+          d="M20 11a8 8 0 1 0-2.34 5.66M20 4v7h-7"
+          stroke="currentColor"
+          stroke-width="2"
+          stroke-linecap="round"
+          stroke-linejoin="round" />
+      </svg>
+      <span class="orientation-toggle__text">切换方向</span>
+    </button>
   </div>
 </template>
 <script setup lang="ts">
@@ -18,6 +37,7 @@ const MtPreviewRef = ref<InstanceType<typeof MtPreview>>()
 const previewData = ref<IExportJson>()
 const pollingTimer = ref<number>()
 const polling = ref(false)
+const orientationSwitched = ref(false)
 
 const getProjectId = () => {
   const id = Number(route.params.id)
@@ -174,6 +194,7 @@ onUnmounted(() => {
 
 <style scoped>
 .preview-page {
+  position: relative;
   width: 100vw;
   width: 100dvw;
   height: 100vh;
@@ -181,6 +202,54 @@ onUnmounted(() => {
   overflow: hidden;
 }
 
+.preview-page--switched {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100vh;
+  width: 100dvh;
+  height: 100vw;
+  height: 100dvw;
+  transform: rotate(90deg) translateY(-100%);
+  transform-origin: left top;
+}
+
+.orientation-toggle {
+  position: fixed;
+  top: max(12px, env(safe-area-inset-top));
+  right: max(12px, env(safe-area-inset-right));
+  z-index: 10;
+  display: inline-flex;
+  height: 36px;
+  padding: 0 14px;
+  font-size: 14px;
+  line-height: 1;
+  color: #fff;
+  cursor: pointer;
+  background: rgb(0 0 0 / 65%);
+  border: 1px solid rgb(255 255 255 / 35%);
+  border-radius: 18px;
+  box-shadow: 0 2px 10px rgb(0 0 0 / 25%);
+  align-items: center;
+  gap: 6px;
+  backdrop-filter: blur(6px);
+  -webkit-tap-highlight-color: transparent;
+}
+
+.orientation-toggle:active {
+  background: rgb(0 0 0 / 80%);
+}
+
+.orientation-toggle__icon {
+  width: 16px;
+  height: 16px;
+  flex: 0 0 auto;
+}
+
+.orientation-toggle__text {
+  line-height: 16px;
+}
+
 /* 手机竖屏时模拟横屏,横屏状态和桌面端保持原方向 */
 /* stylelint-disable-next-line order/order -- 基础视口样式需要位于移动端覆盖样式之前 */
 @media screen and (width <= 767px) and (orientation: portrait) {
@@ -195,5 +264,14 @@ onUnmounted(() => {
     transform: rotate(90deg) translateY(-100%);
     transform-origin: left top;
   }
+
+  .preview-page.preview-page--switched {
+    position: relative;
+    width: 100vw;
+    width: 100dvw;
+    height: 100vh;
+    height: 100dvh;
+    transform: none;
+  }
 }
 </style>