在 PHP 中自定义演示文稿形状
使用编辑点更改形状
考虑一个正方形。在 PowerPoint 中,使用 编辑点,您可以
- 将正方形的角向内或向外移动
- 指定角或点的曲率
- 向正方形添加新点
- 操作正方形上的点等
本质上,您可以对任何形状执行上述任务。使用编辑点,您可以更改形状或从现有形状创建新形状。
形状编辑技巧

在通过编辑点开始编辑 PowerPoint 形状之前,您可能需要考虑以下关于形状的要点:
- 形状(或其路径)可以是闭合的,也可以是开放的。
- 闭合的形状没有起点或终点。开放的形状有起始点和结束点。
- 所有形状至少由 2 个锚点组成,锚点之间通过线段相连
- 线段可以是直线或曲线。锚点决定线段的属性。
- 锚点可以是拐角点、直线点或平滑点:
- 拐角点是两条直线在某个角度相交的点。
- 平滑点是两个手柄在同一直线上,且线段以平滑曲线相连的点。在这种情况下,所有手柄与锚点的距离相等。
- 直线点是两个手柄在同一直线上且线段以平滑曲线相连的点。但在这种情况下,手柄与锚点的距离不必相等。
- 通过移动或编辑锚点(从而改变线段的角度),您可以改变形状的外观。
要通过编辑点编辑 PowerPoint 形状,Aspose.Slides 提供了 GeometryPath 类。
- 一个 GeometryPath 实例表示 GeometryShape 对象的几何路径。
- 要从
GeometryShape实例检索GeometryPath,可以使用 GeometryShape::getGeometryPaths 方法。 - 要为形状设置
GeometryPath,可以使用以下方法:对 实心形状 使用 GeometryShape::setGeometryPath,对 复合形状 使用 GeometryShape::setGeometryPaths。 - 要添加线段,可以使用 GeometryPath 下的方法。
- 使用 GeometryPath::setStroke 和 GeometryPath::setFillMode 方法,可以设置几何路径的外观。
- 使用 GeometryPath::getPathData 方法,您可以将
GeometryShape的几何路径作为路径段数组检索。 - 要访问更多形状几何自定义选项,可以将 GeometryPath 转换为 java.awt.Shape。
- 使用 geometryPathToGraphicsPath 和 graphicsPathToGeometryPath 方法(来自 ShapeUtil 类)在 GeometryPath 与 java.awt.Shape 之间相互转换。
简单编辑操作
以下 PHP 代码演示如何
在路径末尾添加直线
在路径的指定位置添加直线:
在路径末尾添加三次贝塞尔曲线:
在路径的指定位置添加三次贝塞尔曲线:
在路径末尾添加二次贝塞尔曲线:
在路径的指定位置添加二次贝塞尔曲线:
向路径追加给定弧线:
关闭路径的当前图形:
设置下一个点的位置:
移除给定索引处的路径段:
向形状添加自定义点
- 创建 GeometryShape 类的实例,并将其类型设置为 ShapeType::Rectangle。
- 从形状获取 GeometryPath 类的实例。
- 在路径的两个顶部点之间添加新点。
- 在路径的两个底部点之间添加新点。
- 将路径应用于形状。
以下 PHP 代码演示如何向形状添加自定义点:
$pres = new Presentation();
try {
$shape = $pres->getSlides()->get_Item(0)->getShapes()->addAutoShape(ShapeType::Rectangle, 100, 100, 200, 100);
$geometryPath = $shape->getGeometryPaths()[0];
$geometryPath->lineTo(100, 50, 1);
$geometryPath->lineTo(100, 50, 4);
$shape->setGeometryPath($geometryPath);
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}

从形状中移除点
- 创建 GeometryShape 类的实例,并将其类型设置为 ShapeType::Heart。
- 从形状获取 GeometryPath 类的实例。
- 移除路径的线段。
- 将路径应用于形状。
以下 PHP 代码演示如何从形状中移除点:
$pres = new Presentation();
try {
$shape = $pres->getSlides()->get_Item(0)->getShapes()->addAutoShape(ShapeType::Heart, 100, 100, 300, 300);
$path = $shape->getGeometryPaths()[0];
$path->removeAt(2);
$shape->setGeometryPath($path);
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}

创建自定义形状
- 计算形状的点。
- 创建 GeometryPath 类的实例。
- 用这些点填充路径。
- 创建 GeometryShape 类的实例。
- 将路径应用于形状。
以下 Java 代码演示如何创建自定义形状:
$points = new Java("java.util.ArrayList");
$R = 100;
$r = 50;
$step = 72;
for($angle = -90; $angle < 270; $angle += $step) {
$radians = $angle * java("java.lang.Math")->PI / 180.0;
$x = $R * java("java.lang.Math")->cos($radians);
$y = $R * java("java.lang.Math")->sin($radians);
$points->add(new Point2DFloat($x + $R, $y + $R));
$radians = java("java.lang.Math")->PI * $angle . $step / 2 / 180.0;
$x = $r * java("java.lang.Math")->cos($radians);
$y = $r * java("java.lang.Math")->sin($radians);
$points->add(new Point2DFloat($x + $R, $y + $R));
}
$starPath = new GeometryPath();
$starPath->moveTo($points->get(0));
for($i = 1; $i < java_values($points->size()) ; $i++) {
$starPath->lineTo($points->get($i));
}
$starPath->closeFigure();
$pres = new Presentation();
try {
$shape = $pres->getSlides()->get_Item(0)->getShapes()->addAutoShape(ShapeType::Rectangle, 100, 100, $R * 2, $R * 2);
$shape->setGeometryPath($starPath);
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}

创建复合自定义形状
- 创建 GeometryShape 类的实例。
- 创建第一个 GeometryPath 类的实例。
- 创建第二个 GeometryPath 类的实例。
- 将这些路径应用于形状。
以下 PHP 代码演示如何创建复合自定义形状:
$pres = new Presentation();
try {
$shape = $pres->getSlides()->get_Item(0)->getShapes()->addAutoShape(ShapeType::Rectangle, 100, 100, 200, 100);
$geometryPath0 = new GeometryPath();
$geometryPath0->moveTo(0, 0);
$geometryPath0->lineTo($shape->getWidth(), 0);
$geometryPath0->lineTo($shape->getWidth(), $shape->getHeight() / 3);
$geometryPath0->lineTo(0, $shape->getHeight() / 3);
$geometryPath0->closeFigure();
$geometryPath1 = new GeometryPath();
$geometryPath1->moveTo(0, $shape->getHeight() / 3 * 2);
$geometryPath1->lineTo($shape->getWidth(), $shape->getHeight() / 3 * 2);
$geometryPath1->lineTo($shape->getWidth(), $shape->getHeight());
$geometryPath1->lineTo(0, $shape->getHeight());
$geometryPath1->closeFigure();
$shape->setGeometryPaths(array($geometryPath0, $geometryPath1 ));
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}

创建带有弧形角的自定义形状
以下 PHP 代码演示如何创建带有弧形角(向内)的自定义形状;
$shapeX = 20.0;
$shapeY = 20.0;
$shapeWidth = 300.0;
$shapeHeight = 200.0;
$leftTopSize = 50.0;
$rightTopSize = 20.0;
$rightBottomSize = 40.0;
$leftBottomSize = 10.0;
$pres = new Presentation();
try {
$childShape = $pres->getSlides()->get_Item(0)->getShapes()->addAutoShape(ShapeType::Custom, $shapeX, $shapeY, $shapeWidth, $shapeHeight);
$geometryPath = new GeometryPath();
$point1 = new Point2DFloat($leftTopSize, 0);
$point2 = new Point2DFloat($shapeWidth - $rightTopSize, 0);
$point3 = new Point2DFloat($shapeWidth, $shapeHeight - $rightBottomSize);
$point4 = new Point2DFloat($leftBottomSize, $shapeHeight);
$point5 = new Point2DFloat(0, $leftTopSize);
$geometryPath->moveTo($point1);
$geometryPath->lineTo($point2);
$geometryPath->arcTo($rightTopSize, $rightTopSize, 180, -90);
$geometryPath->lineTo($point3);
$geometryPath->arcTo($rightBottomSize, $rightBottomSize, -90, -90);
$geometryPath->lineTo($point4);
$geometryPath->arcTo($leftBottomSize, $leftBottomSize, 0, -90);
$geometryPath->lineTo($point5);
$geometryPath->arcTo($leftTopSize, $leftTopSize, 90, -90);
$geometryPath->closeFigure();
$childShape->setGeometryPath($geometryPath);
$pres->save("output.pptx", SaveFormat::Pptx);
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}
了解形状几何是否闭合
闭合形状的定义是其所有边相连,形成没有间隙的单一边界。此类形状可以是简单的几何形状,也可以是复杂的自定义轮廓。以下代码示例展示如何检查形状几何是否闭合:
function isGeometryClosed($geometryShape)
{
$isClosed = null;
foreach ($geometryShape->getGeometryPaths() as $geometryPath) {
$dataLength = count(java_values($geometryPath->getPathData()));
if ($dataLength === 0) {
continue;
}
$lastSegment = java_values($geometryPath->getPathData())[$dataLength - 1];
$isClosed = $lastSegment->getPathCommand() === PathCommandType::Close;
if ($isClosed === false) {
return false;
}
}
return $isClosed === true;
}
将 GeometryPath 转换为 java.awt.Shape
- 创建 GeometryShape 类的实例。
- 创建 java.awt.Shape 类的实例。
- 使用 ShapeUtil 将 java.awt.Shape 实例转换为 GeometryPath 实例。
- 将路径应用于形状。
以下 PHP 代码实现上述步骤,演示 GeometryPath 到 GraphicsPath 的转换过程:
$pres = new Presentation();
try {
# 创建新形状
$shape = $pres->getSlides()->get_Item(0)->getShapes()->addAutoShape(ShapeType::Rectangle, 100, 100, 300, 100);
# 获取形状的几何路径
$originalPath = $shape->getGeometryPaths()[0];
$originalPath->setFillMode(PathFillModeType::None);
# 使用文本创建新的图形路径
$graphicsPath;
$font = new Font("Arial", Font->PLAIN, 40);
$text = "Text in shape";
$img = new BufferedImage(100, 100, BufferedImage->TYPE_INT_ARGB);
$g2 = $img->createGraphics();
try {
$glyphVector = $font->createGlyphVector($g2->getFontRenderContext(), $text);
$graphicsPath = $glyphVector->getOutline(20.0, -$glyphVector->getVisualBounds()->getY() + 10);
} finally {
$g2->dispose();
}
# 将图形路径转换为几何路径
$textPath = ShapeUtil->graphicsPathToGeometryPath($graphicsPath);
$textPath->setFillMode(PathFillModeType::Normal);
# 将新的几何路径和原始几何路径的组合设置到形状
$shape->setGeometryPaths(array($originalPath, $textPath ));
} finally {
if (!java_is_null($pres)) {
$pres->dispose();
}
}

常见问题
替换几何后填充和轮廓会怎样?
样式仍保留在形状上,仅轮廓发生变化。填充和轮廓会自动应用到新的几何形状。
如何正确旋转自定义形状及其几何?
使用形状的 setRotation 方法;几何会随形状一起旋转,因为它绑定在形状自身的坐标系上。
我可以将自定义形状转换为图像以“锁定”结果吗?
可以。将所需的 slide 区域或 shape 本身导出为光栅格式;这有助于后续处理复杂几何。