Přizpůsobení tvarů prezentace v PHP
Přehled
Tento článek popisuje, jak přizpůsobit tvary prezentace v Aspose.Slides úpravou geometrie tvaru pomocí editačních bodů a geometrických cest. Ukazuje, jak pracovat s GeometryPath k úpravě existujících tvarů, provádění základních operací úpravy cesty, přidávání nebo odstraňování bodů a aplikaci aktualizované geometrie zpět na tvar.
Také demonstruje, jak vytvořit vlastní a složené tvary, sestavit tvary s zakřivenými rohy, určit, zda je geometrie tvaru uzavřená, prozkoumat prvky tvaru a převést obrysy textu Java AWT na geometrické cesty.
Změna tvaru pomocí editačních bodů
- Přesunout roh dovnitř nebo ven.
- Upravit zakřivení v bodě.
- Přidat nové body.
Úprava bodů vám umožní měnit obrys tvaru nebo použít existující tvar jako základ pro nový.
Tipy pro úpravu tvarů

Při úpravě tvarů v PowerPointu mějte na paměti následující koncepty:
- Tvar (nebo jeho cesta) může být buď uzavřená, nebo otevřená.
- Cesta tvaru se skládá z kotevních bodů propojených segmenty.
- Segment může být přímý nebo zakřivený. Kotevní body a ovládací úchyty určují jeho tvar.
- Kotevní body existují jako rohové body, přímé body nebo hladké body:
- V rohovém bodě se sousední segmenty mohou setkat pod úhlem.
- V hladkém bodě jsou oba ovládací úchyty zarovnány a stejně vzdálené od kotevního bodu.
- V přímém bodě jsou oba ovládací úchyty zarovnány, ale mohou mít od kotevního bodu různou vzdálenost.
- Přesunutím kotevních bodů nebo úpravou jejich úchytů se mění obrys tvaru.
Pro úpravu tvarů PowerPointu pomocí editačních bodů poskytuje Aspose.Slides třídu GeometryPath.
- Instance GeometryPath představuje geometrickou cestu objektu GeometryShape.
- Chcete-li získat GeometryPath z instance GeometryShape, můžete použít metodu GeometryShape::getGeometryPaths.
- Pro nastavení GeometryPath pro tvar můžete použít tyto metody: GeometryShape::setGeometryPath pro tvary s jednou cestou a GeometryShape::setGeometryPaths pro tvary s více cestami.
- Pro přidání segmentů můžete použít metody pod GeometryPath.
- Pomocí metod GeometryPath::setStroke a GeometryPath::setFillMode můžete nastavit vzhled geometrické cesty.
- Pomocí metody GeometryPath::getPathData můžete získat geometrickou cestu GeometryShape jako pole segmentů cesty.
- Pro přístup k dalším možnostem přizpůsobení geometrie tvaru můžete přečíst java.awt.Shape pomocí jeho PathIterator a zopakovat segmenty na GeometryPath.
Jednoduché operace úpravy
Použijte následující metody k úpravě geometrické cesty. Přetížení, která přijímají index, vloží segment na pozici s nulovým základem v poli segmentů cesty.
| Operace | Metoda |
|---|---|
| Přidat nebo vložit přímou čáru. | GeometryPath::lineTo |
| Přidat nebo vložit kubickou Bézierovu křivku se dvěma řídicími body a koncovým bodem. | GeometryPath::cubicBezierTo |
| Přidat nebo vložit kvadratickou Bézierovu křivku s jedním řídicím bodem a koncovým bodem. | GeometryPath::quadraticBezierTo |
| Přidat eliptický oblouk se zadanými rozměry a úhly ve stupních. | GeometryPath::arcTo |
| Uzavřít aktuální figurku spojením koncového bodu s počátečním bodem. | GeometryPath::closeFigure |
| Nastavit počáteční bod figurky. | GeometryPath::moveTo |
| Odstranit segment na nultém indexu. | GeometryPath::removeAt |
Přidání vlastních bodů do tvaru
Tento příklad vloží dva body do obdélníkového tvaru pomocí GeometryPath::lineTo a použije upravenou cestu s GeometryShape::setGeometryPath. Souřadnice jsou lokální k tvaru: oba nové body jsou ve středu, 100 bodů od levého okraje a 50 bodů od horního okraje. Indexy segmentů 1 a 4 je umístí na horní a dolní hrany a tyto hrany stáhnou dovnitř.
use aspose\slides\Presentation;
use aspose\slides\ShapeType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$shape = $slide->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 {
$presentation->dispose();
}

Odstranění bodů z tvaru
Tento příklad změní obrys tvaru srdce odebráním segmentu na nultém indexu 2 pomocí GeometryPath::removeAt. Použitím upravené cesty s GeometryShape::setGeometryPath se aktualizuje kontura tvaru.
use aspose\slides\Presentation;
use aspose\slides\ShapeType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$shape = $slide->getShapes()->addAutoShape(ShapeType::Heart, 100, 100, 300, 300);
$path = $shape->getGeometryPaths()[0];
$path->removeAt(2);
$shape->setGeometryPath($path);
} finally {
$presentation->dispose();
}

Vytvoření vlastního tvaru
Tento příklad vytvoří pětibodovou hvězdu pomocí GeometryPath. Střídavé vnější a vnitřní poloměry 100 a 50 bodů definují špičky a zapouzdření; krok 72 stupňů rovnoměrně rozmístí pět špiček. Cesta je uzavřena pomocí GeometryPath::closeFigure a aplikována na obdélníkový tvar pomocí GeometryShape::setGeometryPath, čímž se nahradí jeho obrys.
use aspose\slides\GeometryPath;
use aspose\slides\Presentation;
use aspose\slides\ShapeType;
$points = [];
$outerRadius = 100;
$innerRadius = 50;
$angleStep = 72;
for ($angle = -90; $angle < 270; $angle += $angleStep) {
$radians = deg2rad($angle);
$points[] = [$outerRadius * cos($radians) + $outerRadius, $outerRadius * sin($radians) + $outerRadius];
$radians = deg2rad($angle + $angleStep / 2);
$points[] = [$innerRadius * cos($radians) + $outerRadius, $innerRadius * sin($radians) + $outerRadius];
}
$starPath = new GeometryPath();
$starPath->moveTo($points[0][0], $points[0][1]);
for ($i = 1; $i < count($points); $i++) {
$starPath->lineTo($points[$i][0], $points[$i][1]);
}
$starPath->closeFigure();
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$shape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 100, 100, $outerRadius * 2, $outerRadius * 2);
$shape->setGeometryPath($starPath);
} finally {
$presentation->dispose();
}

Vytvoření složeného vlastního tvaru
Tento příklad definuje dva uzavřené GeometryPath objekty pro horní a spodní třetinu tvaru. Použitím obou cest s GeometryShape::setGeometryPaths se vytvoří jediný složený tvar s mezerou uprostřed jeho střední třetiny.
use aspose\slides\GeometryPath;
use aspose\slides\Presentation;
use aspose\slides\ShapeType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$shape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 100, 100, 200, 100);
$topPath = new GeometryPath();
$topPath->moveTo(0, 0);
$topPath->lineTo(java_values($shape->getWidth()), 0);
$topPath->lineTo(java_values($shape->getWidth()), java_values($shape->getHeight()) / 3);
$topPath->lineTo(0, java_values($shape->getHeight()) / 3);
$topPath->closeFigure();
$bottomPath = new GeometryPath();
$bottomPath->moveTo(0, java_values($shape->getHeight()) / 3 * 2);
$bottomPath->lineTo(java_values($shape->getWidth()), java_values($shape->getHeight()) / 3 * 2);
$bottomPath->lineTo(java_values($shape->getWidth()), java_values($shape->getHeight()));
$bottomPath->lineTo(0, java_values($shape->getHeight()));
$bottomPath->closeFigure();
$shape->setGeometryPaths([$topPath, $bottomPath]);
} finally {
$presentation->dispose();
}

Vytvoření vlastního tvaru s zakřivenými rohy
Tento příklad kombinuje přímé segmenty s GeometryPath::arcTo k vytvoření tvaru s vnitřně zakřivenými rohy. Velikost každého rohu určuje šířku a výšku oblouku v bodech a úhel -90° vykreslí proti směru hodinových ručiček čtvrtinu elipsy. Dokončená cesta je aplikována pomocí GeometryShape::setGeometryPath a prezentace je uložena ve formátu PPTX.
use aspose\slides\GeometryPath;
use aspose\slides\Point2DFloat;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;
$shapeX = 20;
$shapeY = 20;
$shapeWidth = 300;
$shapeHeight = 200;
$leftTopSize = 50;
$rightTopSize = 20;
$rightBottomSize = 40;
$leftBottomSize = 10;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$shape = $slide->getShapes()->addAutoShape(ShapeType::Custom, $shapeX, $shapeY, $shapeWidth, $shapeHeight);
$topLeft = new Point2DFloat($leftTopSize, 0);
$topRight = new Point2DFloat($shapeWidth - $rightTopSize, 0);
$rightBottom = new Point2DFloat($shapeWidth, $shapeHeight - $rightBottomSize);
$bottomLeft = new Point2DFloat($leftBottomSize, $shapeHeight);
$leftTop = new Point2DFloat(0, $leftTopSize);
$geometryPath = new GeometryPath();
$geometryPath->moveTo($topLeft);
$geometryPath->lineTo($topRight);
$geometryPath->arcTo($rightTopSize, $rightTopSize, 180, -90);
$geometryPath->lineTo($rightBottom);
$geometryPath->arcTo($rightBottomSize, $rightBottomSize, -90, -90);
$geometryPath->lineTo($bottomLeft);
$geometryPath->arcTo($leftBottomSize, $leftBottomSize, 0, -90);
$geometryPath->lineTo($leftTop);
$geometryPath->arcTo($leftTopSize, $leftTopSize, 90, -90);
$geometryPath->closeFigure();
$shape->setGeometryPath($geometryPath);
$presentation->save("output.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
Zjistěte, zda je geometrie tvaru uzavřená
Následující pomocná metoda kontroluje, zda každý neprázdný geometrický segment končí uzavíracím segmentem. Čte GeometryPath::getPathData a porovnává poslední segmentův PathSegment::getPathCommand s PathCommandType::Close. Vrací false, pokud neexistují neprázdné cesty. Kontroluje poslední příkaz každé cesty; neprozkoumává každou podfiguru uvnitř cesty. Příklad vytiskne true pro obdélník.
use aspose\slides\PathCommandType;
use aspose\slides\Presentation;
use aspose\slides\ShapeType;
function isGeometryClosed($geometryShape)
{
$hasNonemptyPath = false;
foreach ($geometryShape->getGeometryPaths() as $geometryPath) {
$segments = java_values($geometryPath->getPathData());
if (count($segments) === 0) {
continue;
}
$hasNonemptyPath = true;
$lastSegment = $segments[count($segments) - 1];
if (java_values($lastSegment->getPathCommand()) !== PathCommandType::Close) {
return false;
}
}
return $hasNonemptyPath;
}
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$shape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 100, 100, 200, 100);
$closed = isGeometryClosed($shape);
echo ($closed ? "true" : "false") . PHP_EOL;
} finally {
$presentation->dispose();
}
Extrahování a kontrola prvků tvaru
Použijte GeometryShape::createShapeElements k prozkoumání existujícího tvaru jako prvků obsahujících body cesty a typy bodů. Každý vrácený ShapeElement použijte k získání polí bodů a typů přes metody getPathPoints a getPathTypes. Toto zastoupení je užitečné pro analýzu kontur nebo předání geometrie vlastním kreslícím nástrojům.
Příklad otevře input.pptx, najde první geometrický tvar přímo na první snímku a vytiskne jeho segmenty cesty. Použijte prezentaci obsahující tvar s přímými i zakřivenými segmenty, abyste viděli oba typy výstupu. Nepřehledává skupiny.
use aspose\slides\Presentation;
$presentation = new Presentation("input.pptx");
try {
$slide = $presentation->getSlides()->get_Item(0);
$shape = null;
$shapes = $slide->getShapes();
for ($shapeIndex = 0; $shapeIndex < java_values($shapes->size()); $shapeIndex++) {
$candidate = $shapes->get_Item($shapeIndex);
if (java_instanceof($candidate, java("com.aspose.slides.GeometryShape"))) {
$shape = $candidate;
break;
}
}
if ($shape === null) {
echo "No geometry shape found on the first slide." . PHP_EOL;
} else {
foreach ($shape->createShapeElements() as $element) {
$points = java_values($element->getPathPoints());
$types = array_values(unpack("C*", java_values($element->getPathTypes())));
echo "Shape element:" . PHP_EOL;
for ($i = 0; $i < count($points); $i++) {
$pointType = $types[$i] & 0x07; // Zachovat typ segmentu, vyjma příznaků.
switch ($pointType) {
case 0:
echo "Start figure at " . $points[$i] . PHP_EOL;
break;
case 1:
echo "Line to " . $points[$i] . PHP_EOL;
break;
case 3:
echo "Cubic Bezier: controls " . $points[$i] . ", " . $points[$i + 1] . "; end " . $points[$i + 2] . PHP_EOL;
$i += 2; // Zpracovat oba řídicí body a koncový bod.
break;
}
if (($types[$i] & 0x80) !== 0) {
echo "Close subpath back to its starting point." . PHP_EOL;
}
}
}
}
} finally {
$presentation->dispose();
}
Pole jsou seřazena podle indexu: $points[$i] je bod a $types[$i] popisuje jeho roli. Typ 0 začíná figurku a typ 1 kreslí čáru od předchozího bodu k aktuálnímu bodu. Kubický Bézierův segment začíná předchozím koncovým bodem a používá tři po sobě jdoucí položky typu 3: dva řídicí body následované novým koncovým bodem. Smyčka konzumuje tyto tři položky najednou a kontroluje koncový bod na uzavření.
Typy bodů také obsahují příznaky. Pro identifikaci typu segmentu maskujte 0x07 a pro detekci uzavřené podcesty testujte 0x80 zvlášť. Například 129 (0x81) znamená koncový bod čáry, který uzavírá podcestu, a 131 (0x83) znamená koncový bod Bézieru, který uzavírá podcestu. PHP/Java Bridge vrací bajtové pole jako binární řetězec; rozbalením pomocí "C*" získáte neznaménkové bajtové hodnoty. Maskování zachovává zamýšlené bitové hodnoty. Porovnávání surové hodnoty pouze s 1 nebo 3 by tyto případy neodhalilo. Další příznaky, jako pomlčka (0x10) a značka (0x20), nemění základní typ segmentu.
Souřadnice a transformace. Body jsou měřeny v bodech (1/72 palce), přičemž X roste doprava a Y roste dolů. Pro nezhroucený tvar extrahované souřadnice již zahrnují pozici vrácenou metodami getX a getY a odrážejí jeho aktuální šířku a výšku. Například neotočený obdélník v bodě (100, 200) s velikostí 120 × 80 má hranice kontury (100, 200)–(220, 280). Nepřidávejte pozici tvaru znovu. Odečtěte jeho X a Y, aby vznikly souřadnice relativní k jeho neotočenému rámci.
Extrahované body neaplikují rotaci tvaru, kterou vrací getRotation, ani horizontální a vertikální převrácení. Pro reprodukci zobrazené kontury aplikujte tyto transformace kolem středu tvaru. U seskupených tvarů také zohledněte mapování souřadnic skupiny a transformace; nepředpokládejte, že extrahované body jsou konečné souřadnice snímku, ani neaplikujte posun nebo měřítko dvakrát, pokud již jsou zahrnuty v rámci dítěte.
Kontrola vs. úprava. Extrahovaná pole popisují konturu; jejich změna neaktualizuje původní tvar. Zvolte tento přístup, když vaše analýza nebo kreslící kód potřebuje pole bodů/typů. Použijte getGeometryPaths, když potřebujete geometrické příkazy v lokálním souřadnicovém systému tvaru nebo chcete upravit jeho geometrii. Aplikujte upravené cesty pomocí setGeometryPath nebo setGeometryPaths.
Převod Java AWT Shape na GeometryPath
Tento příklad kombinuje obdélníkový obrys s textem převedeným na geometrii. Metoda setFillMode obrysu zakáže jeho výplň. GlyphVector vytvoří obrys textu v java.awt.Shape. Jeho PathIterator poskytuje pohyby, čáry, kvadratické, kubické a uzavírací segmenty, které příklad zopakuje na GeometryPath.
Příklad používá pole typu float v Javě, aby PHP/Java Bridge zachoval souřadnice zapisované iterátorem. Text používá písmo Arial o velikosti 40 bodů. Obrys je posunut o 20 bodů vodorovně a umístěn tak, že jeho vizuální horní část je 10 bodů pod horním okrajem tvaru. Cesta textu je vyplněna, zatímco původní obdélník zůstává jen obrysem. Použitím obou cest s GeometryShape::setGeometryPaths vznikne jediný tvar obsahující obdélník i text.
use aspose\slides\GeometryPath;
use aspose\slides\PathFillModeType;
use aspose\slides\Presentation;
use aspose\slides\ShapeType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$shape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 100, 100, 300, 100);
$originalPath = $shape->getGeometryPaths()[0];
$originalPath->setFillMode(PathFillModeType::None);
$fontClass = java("java.awt.Font");
$imageClass = java("java.awt.image.BufferedImage");
$font = new Java("java.awt.Font", "Arial", $fontClass->PLAIN, 40);
$image = new Java("java.awt.image.BufferedImage", 100, 100, $imageClass->TYPE_INT_ARGB);
$graphics = $image->createGraphics();
try {
$fontContext = $graphics->getFontRenderContext();
$glyphVector = $font->createGlyphVector($fontContext, "Text in shape");
$textBounds = $glyphVector->getVisualBounds();
$baseline = -java_values($textBounds->getY()) + 10;
$graphicsPath = $glyphVector->getOutline(20.0, $baseline);
} finally {
$graphics->dispose();
}
$textPath = new GeometryPath();
$pathIterator = $graphicsPath->getPathIterator(null);
$iteratorClass = java("java.awt.geom.PathIterator");
$arrayClass = java("java.lang.reflect.Array");
$floatClass = java("java.lang.Float");
$coordinates = $arrayClass->newInstance($floatClass->TYPE, 6);
while (!java_values($pathIterator->isDone())) {
$segmentType = java_values($pathIterator->currentSegment($coordinates));
$points = java_values($coordinates);
switch ($segmentType) {
case java_values($iteratorClass->SEG_MOVETO):
$textPath->moveTo($points[0], $points[1]);
break;
case java_values($iteratorClass->SEG_LINETO):
$textPath->lineTo($points[0], $points[1]);
break;
case java_values($iteratorClass->SEG_QUADTO):
$textPath->quadraticBezierTo($points[0], $points[1], $points[2], $points[3]);
break;
case java_values($iteratorClass->SEG_CUBICTO):
$textPath->cubicBezierTo($points[0], $points[1], $points[2], $points[3], $points[4], $points[5]);
break;
case java_values($iteratorClass->SEG_CLOSE):
$textPath->closeFigure();
break;
}
$pathIterator->next();
}
$textPath->setFillMode(PathFillModeType::Normal);
$shape->setGeometryPaths([$originalPath, $textPath]);
} finally {
$presentation->dispose();
}

Často kladené otázky
Co se stane s výplní a obrysem po nahrazení geometrie?
Styl zůstane u tvaru; pouze se změní kontura. Výplň a obrys jsou automaticky aplikovány na novou geometrii.
Jak správně otočit vlastní tvar spolu s jeho geometrií?
Použijte metodu tvaru setRotation; geometrie se otáčí spolu s tvarem, protože je svázána s jeho vlastním souřadnicovým systémem.
Mohu převést vlastní tvar na obrázek, aby výsledek byl „uzamčen“?
Ano. Exportujte požadovanou slide nebo samotný shape do rastrového formátu; to usnadní další práci s komplexními geometriemi.