feat: 四圆角独立处理 + transform rotate

- 圆角:取四角最大值(PPT只支持统一圆角)
- 旋转:CSS transform:rotate → pptxgenjs rotate
- 两个文件同步
This commit is contained in:
李进
2026-07-27 17:16:21 +08:00
parent d3bb1fe952
commit ce89ee1b4d
2 changed files with 23 additions and 11 deletions
+22 -9
View File
@@ -826,13 +826,25 @@ async function convert(input) {
shapeOpts.fill.transparency = Math.max(shapeOpts.fill.transparency || 0, opTrans); shapeOpts.fill.transparency = Math.max(shapeOpts.fill.transparency || 0, opTrans);
} }
// 圆角 // 圆角(取四角最大值,PPT 只支持统一圆角)
var brVal = n.styles.borderTopLeftRadius; var brCorners = [
if (brVal && brVal !== '0px') { n.styles.borderTopLeftRadius,
if (brVal.includes('%')) { n.styles.borderTopRightRadius,
shapeOpts.rectRadius = parseFloat(brVal) / 100; n.styles.borderBottomLeftRadius,
} else { n.styles.borderBottomRightRadius
shapeOpts.rectRadius = parseFloat(brVal) / 72; ].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 // 选择形状类型:圆角 >= 50% 且 w≈h 时用 ellipse(正圆),否则用 roundRect
var useShape = 'rect'; var useShape = 'rect';
if (shapeOpts.rectRadius) { if (shapeOpts.rectRadius) {
var brPct = parseFloat(n.styles.borderTopLeftRadius); var maxBrPct = Math.max(...brCorners.map(v => v * 72)); // 转回 px 参考
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'; useShape = isCircle ? 'ellipse' : 'roundRect';
} }
objects.push({ type: 'shape', shapeName: useShape, options: shapeOpts }); objects.push({ type: 'shape', shapeName: useShape, options: shapeOpts });
@@ -1042,6 +1054,7 @@ if (require.main === module) {
else shapeOpts.line = { type: 'none' }; // 去掉 pptxgenjs 默认边框 else shapeOpts.line = { type: 'none' }; // 去掉 pptxgenjs 默认边框
if (o.shadow) shapeOpts.shadow = o.shadow; if (o.shadow) shapeOpts.shadow = o.shadow;
if (o.rectRadius) shapeOpts.rectRadius = o.rectRadius; if (o.rectRadius) shapeOpts.rectRadius = o.rectRadius;
if (o.rotate) shapeOpts.rotate = o.rotate;
slide.addShape(pres.ShapeType[st] || pres.ShapeType.rect, shapeOpts); slide.addShape(pres.ShapeType[st] || pres.ShapeType.rect, shapeOpts);
} else if (obj.type === 'image') { } else if (obj.type === 'image') {
slide.addImage({ slide.addImage({
+1 -2
View File
@@ -476,8 +476,7 @@ async function convertToPptx(input, onProgress) {
// 形状类型 // 形状类型
var useShape = 'rect'; var useShape = 'rect';
if (shapeOpts.rectRadius) { if (shapeOpts.rectRadius) {
var brPct = parseFloat(n.styles.borderTopLeftRadius); var isCircle = shapeOpts.rectRadius >= 0.5 && Math.abs(opts.w - opts.h) < 0.05;
var isCircle = (brPct >= 50 || (brPct.toString().includes('%') && parseFloat(brPct) >= 50)) && Math.abs(opts.w - opts.h) < 0.05;
useShape = isCircle ? 'ellipse' : 'roundRect'; useShape = isCircle ? 'ellipse' : 'roundRect';
} }
objects.push({ type: 'shape', shapeName: useShape, options: shapeOpts }); objects.push({ type: 'shape', shapeName: useShape, options: shapeOpts });