Przeglądaj źródła

修改一张横版样式

wangfumin 1 miesiąc temu
rodzic
commit
7ffda4abee

+ 66 - 19
src/view/gaPhoto/index.vue

@@ -170,9 +170,9 @@ const createPlaceholder = (text: string) => {
 
 // paperList:每页一个数组,数组内为图片项(四页,每页两个槽位,共8个)
 // 默认使用占位图和默认说明文字,方便后续删除时进行跨页补位
-const paperList = Array.from({ length: 3 }, (_, pIdx) => {
-  // 默认第一页两张,后两页各一张(配合 pageTypes 演示)
-  const count = pIdx === 0 ? 2 : 1;
+const paperList = Array.from({ length: 4 }, (_, pIdx) => {
+  // 初始化生成四页一页两张
+  const count = 2;
   return Array.from({ length: count }, (_, sIdx) => ({
     id: pIdx * 2 + sIdx + 1,
     imgUrl: createPlaceholder("现场照片"),
@@ -184,8 +184,7 @@ const renderCanvas = () => {
   scene = new Scene(canvas);
   scene.init();
   window.scene = scene;
-  // 加载布局:第一页两张(1),第二页横版(3),第三页竖版(2)
-  pageTypes.value = [1, 3, 2];
+  // 加载布局
   scene.load(paperList, pageTypes.value);
 };
 onMounted(() => {
@@ -337,23 +336,71 @@ const onKeyDown = (e: KeyboardEvent) => {
 const onLayoutCommand = (cmd: string) => {
   if (selectedPageIndex.value == null) return
   const p = selectedPageIndex.value
-  if (cmd === 'two') pageTypes.value[p] = 1
-  if (cmd === 'v1') pageTypes.value[p] = 2
-  if (cmd === 'h1') pageTypes.value[p] = 3
-
-  // 根据布局类型调整该页的槽位数量(two:2,h1/v1:1)
-  const targetLen = pageTypes.value[p] === 1 ? 2 : 1
-  const cur = paperList[p]
-  if (cur.length > targetLen) {
-    cur.splice(targetLen) // 截断多余槽位
-  } else if (cur.length < targetLen) {
-    const need = targetLen - cur.length
-    for (let i = 0; i < need; i++) {
-      cur.push({ id: getNewSlotId(), imgUrl: createPlaceholder('现场照片'), imgInfo: '说明文字' })
+
+  let newType = 1
+  if (cmd === 'two') newType = 1
+  if (cmd === 'v1') newType = 2
+  if (cmd === 'h1') newType = 3
+
+  if (pageTypes.value[p] === newType) return
+  pageTypes.value[p] = newType
+
+  // 1. Flatten all slots
+  const allSlots: any[] = []
+  paperList.forEach(page => page.forEach(slot => allSlots.push(slot)))
+
+  // 2. Re-distribute
+  const newPaperList: any[][] = []
+  let slotIdx = 0
+  
+  // Helper to get new ID (temporary)
+  let maxId = 0
+  allSlots.forEach(s => { if(s.id > maxId) maxId = s.id })
+  const getNextId = () => ++maxId
+
+  // Fill existing pages
+  for (let i = 0; i < pageTypes.value.length; i++) {
+    const type = pageTypes.value[i]
+    const capacity = (type === 1) ? 2 : 1
+    const page: any[] = []
+    for (let k = 0; k < capacity; k++) {
+      if (slotIdx < allSlots.length) {
+        page.push(allSlots[slotIdx++])
+      } else {
+        page.push({ id: getNextId(), imgUrl: createPlaceholder('现场照片'), imgInfo: '说明文字' })
+      }
+    }
+    newPaperList.push(page)
+  }
+
+  // Handle remaining slots by adding new pages
+  while (slotIdx < allSlots.length) {
+    pageTypes.value.push(1)
+    const capacity = 2
+    const page: any[] = []
+    for (let k = 0; k < capacity; k++) {
+      if (slotIdx < allSlots.length) {
+        page.push(allSlots[slotIdx++])
+      } else {
+        page.push({ id: getNextId(), imgUrl: createPlaceholder('现场照片'), imgInfo: '说明文字' })
+      }
+    }
+    newPaperList.push(page)
+  }
+
+  // 3. Update paperList
+  paperList.length = 0
+  newPaperList.forEach(p => paperList.push(p))
+
+  // 4. Re-index IDs to ensure sequential order
+  let idCounter = 1
+  for (const page of paperList) {
+    for (const slot of page) {
+      slot.id = idCounter++
     }
   }
 
-  // 重新渲染(支持每页独立布局)
+  // 5. Reload
   scene.load(paperList, pageTypes.value)
   updatePageToolbarPosition()
   highlightPageBorder(selectedPageIndex.value)

+ 28 - 2
src/view/gaPhoto/photo/box/SingleHorizontalBox.js

@@ -1,6 +1,6 @@
 import * as THREE from "three";
 import TextLabel from "./object/TextLabel";
-import ImgLabelBox from "./object/ImgLabelBox";
+import ImgLabel from "./object/ImgLabel";
 import SimpleLabel from "./object/SimpleLabel";
 import TouchEdge from "./object/TouchEdge";
 import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
@@ -66,10 +66,36 @@ export default class SingleHorizontalBox extends THREE.Group {
       //img
       let img;
       this.manager.loader.load(i.imgUrl, (texture) => {
+        let imgRatio = texture.image.width / texture.image.height;
         texture.matrixAutoUpdate = false;
+        // 目标框尺寸:宽1.5, 高1.125
+        let planeRatio = 1.5 / 1.125;
+        
+        if (planeRatio < imgRatio) {
+          texture.matrix.setUvTransform(
+            0,
+            0,
+            planeRatio / imgRatio,
+            1,
+            0,
+            0.5,
+            0.5
+          );
+        } else {
+          texture.matrix.setUvTransform(
+            0,
+            0,
+            1,
+            imgRatio / planeRatio,
+            0,
+            0.5,
+            0.5
+          );
+        }
+
         texture.colorSpace = THREE.SRGBColorSpace;
         // 使用自定义尺寸,宽度 1.5,高度 1.125 (4:3)
-        img = new ImgLabelBox(texture, matLine, { width: 1.5, height: 1.125 });
+        img = new ImgLabel(texture, matLine, { width: 1.5, height: 1.125 });
 
         img.userData = i.id;
         img.position.y += 1;

+ 12 - 1
src/view/gaPhoto/photo/box/object/ImgLabel.js

@@ -4,7 +4,18 @@ import TouchEdge from "./TouchEdge";
 export default class ImgLabel extends THREE.Mesh {
   constructor(texture, matLine, isHorizontal = true) {
     let width, height, p;
-    if (isHorizontal) {
+    if (typeof isHorizontal === 'object') {
+      width = isHorizontal.width;
+      height = isHorizontal.height;
+      const halfW = width / 2;
+      const halfH = height / 2;
+      p = [
+        [-halfW, 0, -halfH, halfW, 0, -halfH],
+        [-halfW, 0, -halfH, -halfW, 0, halfH],
+        [-halfW, 0, halfH, halfW, 0, halfH],
+        [halfW, 0, halfH, halfW, 0, -halfH],
+      ];
+    } else if (isHorizontal) {
       width = 1.5;
       height = 0.85;
       p = [