From ce89ee1b4d294ea75f5dbcdaf1b3923e8828839a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E8=BF=9B?= Date: Mon, 27 Jul 2026 17:16:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9B=9B=E5=9C=86=E8=A7=92=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E5=A4=84=E7=90=86=20+=20transform=20rotate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 圆角:取四角最大值(PPT只支持统一圆角) - 旋转:CSS transform:rotate → pptxgenjs rotate - 两个文件同步 --- convert-w2p.js | 31 ++++++++++++++++++++++--------- web-to-ppt/convert-browser.js | 3 +-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/convert-w2p.js b/convert-w2p.js index fd4cf78..aeafe46 100644 --- a/convert-w2p.js +++ b/convert-w2p.js @@ -826,13 +826,25 @@ async function convert(input) { shapeOpts.fill.transparency = Math.max(shapeOpts.fill.transparency || 0, opTrans); } - // 圆角 - var brVal = n.styles.borderTopLeftRadius; - if (brVal && brVal !== '0px') { - if (brVal.includes('%')) { - shapeOpts.rectRadius = parseFloat(brVal) / 100; - } else { - shapeOpts.rectRadius = parseFloat(brVal) / 72; + // 圆角(取四角最大值,PPT 只支持统一圆角) + var brCorners = [ + n.styles.borderTopLeftRadius, + n.styles.borderTopRightRadius, + n.styles.borderBottomLeftRadius, + n.styles.borderBottomRightRadius + ].filter(v => v && v !== '0px').map(v => { + if (v.includes('%')) return parseFloat(v) / 100; + return parseFloat(v) / 72; + }); + if (brCorners.length > 0) { + shapeOpts.rectRadius = Math.max(...brCorners); + } + + // 旋转(CSS transform: rotate) + if (n.styles.transform && n.styles.transform !== 'none') { + var rotateMatch = n.styles.transform.match(/rotate\(([\d.]+)deg\)/); + if (rotateMatch) { + shapeOpts.rotate = parseFloat(rotateMatch[1]); } } @@ -866,8 +878,8 @@ async function convert(input) { // 选择形状类型:圆角 >= 50% 且 w≈h 时用 ellipse(正圆),否则用 roundRect var useShape = 'rect'; if (shapeOpts.rectRadius) { - var brPct = parseFloat(n.styles.borderTopLeftRadius); - var isCircle = (brPct >= 50 || (brPct.toString().includes('%') && parseFloat(brPct) >= 50)) && Math.abs(opts.w - opts.h) < 0.05; + var maxBrPct = Math.max(...brCorners.map(v => v * 72)); // 转回 px 参考 + var isCircle = shapeOpts.rectRadius >= 0.5 && Math.abs(opts.w - opts.h) < 0.05; useShape = isCircle ? 'ellipse' : 'roundRect'; } objects.push({ type: 'shape', shapeName: useShape, options: shapeOpts }); @@ -1042,6 +1054,7 @@ if (require.main === module) { else shapeOpts.line = { type: 'none' }; // 去掉 pptxgenjs 默认边框 if (o.shadow) shapeOpts.shadow = o.shadow; if (o.rectRadius) shapeOpts.rectRadius = o.rectRadius; + if (o.rotate) shapeOpts.rotate = o.rotate; slide.addShape(pres.ShapeType[st] || pres.ShapeType.rect, shapeOpts); } else if (obj.type === 'image') { slide.addImage({ diff --git a/web-to-ppt/convert-browser.js b/web-to-ppt/convert-browser.js index 95faac9..ec42832 100644 --- a/web-to-ppt/convert-browser.js +++ b/web-to-ppt/convert-browser.js @@ -476,8 +476,7 @@ async function convertToPptx(input, onProgress) { // 形状类型 var useShape = 'rect'; if (shapeOpts.rectRadius) { - var brPct = parseFloat(n.styles.borderTopLeftRadius); - var isCircle = (brPct >= 50 || (brPct.toString().includes('%') && parseFloat(brPct) >= 50)) && Math.abs(opts.w - opts.h) < 0.05; + var isCircle = shapeOpts.rectRadius >= 0.5 && Math.abs(opts.w - opts.h) < 0.05; useShape = isCircle ? 'ellipse' : 'roundRect'; } objects.push({ type: 'shape', shapeName: useShape, options: shapeOpts });