Quellcode durchsuchen

Merge branch 'beta' of https://git.cocorobo.cn/jack/PPT into beta

lsc vor 17 Stunden
Ursprung
Commit
7a85e46140
2 geänderte Dateien mit 45 neuen und 27 gelöschten Zeilen
  1. 5 2
      src/assets/styles/prosemirror.scss
  2. 40 25
      src/hooks/useImport.ts

+ 5 - 2
src/assets/styles/prosemirror.scss

@@ -20,9 +20,12 @@
     font-size: 0;
     padding: 0;
   }
-  p:first-child {
+  p:first-child:has(br) {
+    font-size: 0;
+  }
+  p:first-child br {
     margin-top: 0;
-    // font-size: 0;
+    font-size: 0;
   }
 
   ul, ol, li {

+ 40 - 25
src/hooks/useImport.ts

@@ -50,9 +50,9 @@ const getStyle = (htmlString: string) => {
   // 2. 解析 HTML 字符串为文档对象
   const doc = parser.parseFromString(htmlString, 'text/html')
   // 3. 获取 p 元素
-  const firstElem = doc.querySelector('p, ul, ol, table');
+  const firstElem = doc.querySelector('p, ul, ol, table')
   // 读取该元素的 allstyle 属性
-  const styleAttr = firstElem?.getAttribute('allstyle');
+  const styleAttr = firstElem?.getAttribute('allstyle')
   console.log(styleAttr) // 输出完整的 style 字符串
   return styleAttr || ''
 
@@ -384,29 +384,41 @@ export default () => {
   }
 
   const calculateRotatedPosition = (
-    x: number,
-    y: number,
-    w: number,
-    h: number,
-    ox: number,
-    oy: number,
-    k: number,
+    x: number, // 原外层容器左上角 X
+    y: number, // 原外层容器左上角 Y
+    w: number, // 原外层容器宽度
+    h: number, // 原外层容器高度
+    ox: number, // 子元素在原容器内左上角 X
+    oy: number, // 子元素在原容器内左上角 Y
+    childW: number, // 子元素宽度
+    childH: number, // 子元素高度
+    k: number // 顺时针旋转角度(度)
   ) => {
     const radians = k * (Math.PI / 180)
+    const cos = Math.cos(radians)
+    const sin = Math.sin(radians)
 
+    // 原容器中心点(全局坐标)
     const containerCenterX = x + w / 2
     const containerCenterY = y + h / 2
 
-    const relativeX = ox - w / 2
-    const relativeY = oy - h / 2
+    // 子元素中心相对于容器中心的偏移
+    const childCenterInContainerX = (ox + childW / 2) - w / 2
+    const childCenterInContainerY = (oy + childH / 2) - h / 2
 
-    const rotatedX = relativeX * Math.cos(radians) + relativeY * Math.sin(radians)
-    const rotatedY = -relativeX * Math.sin(radians) + relativeY * Math.cos(radians)
+    // 屏幕坐标系下的顺时针旋转
+    const rotatedOffsetX = childCenterInContainerX * cos - childCenterInContainerY * sin
+    const rotatedOffsetY = childCenterInContainerX * sin + childCenterInContainerY * cos
 
-    const graphicX = containerCenterX + rotatedX
-    const graphicY = containerCenterY + rotatedY
+    // 子元素中心的新全局坐标
+    const newCenterX = containerCenterX + rotatedOffsetX
+    const newCenterY = containerCenterY + rotatedOffsetY
 
-    return { x: graphicX, y: graphicY }
+    // 反推新左上角
+    return {
+      x: newCenterX - childW / 2,
+      y: newCenterY - childH / 2
+    }
   }
 
   /**
@@ -878,7 +890,8 @@ export default () => {
           width = parseFloat(parts[2])
           height = parseFloat(parts[3])
         }
-      } else {
+      }
+      else {
         const svgWidth = tempSvg.getAttribute('width')
         const svgHeight = tempSvg.getAttribute('height')
         if (svgWidth && svgHeight) {
@@ -886,7 +899,8 @@ export default () => {
           height = parseFloat(svgHeight)
         }
       }
-    } catch (e) {
+    }
+    catch (e) {
       console.warn('Failed to get dimensions from SVG, using default', e)
     }
 
@@ -948,7 +962,8 @@ export default () => {
           'image/png'
         )
       })
-    } finally {
+    }
+    finally {
       URL.revokeObjectURL(url)
     }
   }
@@ -1694,10 +1709,9 @@ export default () => {
 
       // 收集当前幻灯片内所有上传任务
       const uploadTasks: Promise<void>[] = []
-      
       // 遍历每一张幻灯片
       for (const item of json.slides) {
-        let type = "", value = "";
+        let type = '', value = ''
         if (item.fill) {
           // ----- 解析背景 -----
           type = item.fill.type
@@ -1986,8 +2000,8 @@ export default () => {
             // ---------- 形状 ----------
             else if (el.type === 'shape') {
               if (el.shapType === 'line' || /Connector/.test(el.shapType)) {
-                //el.isFlipH = el.isFlipV = false;
-                //el.rotate = 0;
+                // el.isFlipH = el.isFlipV = false;
+                // el.rotate = 0;
                 //   // 线条元素(单独处理)
                 //   const lineElement = parseLineElement(el, ratio)
                 //   slide.elements.push(lineElement)
@@ -2100,7 +2114,7 @@ export default () => {
               }
 
               if (element.path) slide.elements.push(element)
-              //}
+              // }
             }
 
             // ---------- 表格 ----------
@@ -2271,7 +2285,7 @@ export default () => {
                 if (el.rotate) {
                   const { x, y } = calculateRotatedPosition(
                     originLeft, originTop, originWidth, originHeight,
-                    _el.left, _el.top, el.rotate
+                    _el.left, _el.top, _el.width, _el.height, el.rotate
                   )
                   left = x
                   top = y
@@ -2284,6 +2298,7 @@ export default () => {
                 }
                 if (el.isFlipH && 'isFlipH' in element) element.isFlipH = true
                 if (el.isFlipV && 'isFlipV' in element) element.isFlipV = true
+                if (el.rotate) element.rotate = (_el.rotate || 0) + el.rotate
 
                 return element
               })