PHP を使用したプレゼンテーションへのシェイプ アニメーションの適用

概要

Aspose.Slides for PHP via Java は、スライドアニメーションをスライドタイムライン上のエフェクトとして表現します。エフェクトには対象シェイプ、アニメーションの種類とサブタイプ、トリガー、タイミング設定、そしてサウンドやアフターアニメーション動作といったオプションプロパティがあります。

タイムラインには 2 種類のシーケンスがあります:

  • メインシーケンス はスライドが進むと再生されます。
  • インタラクティブシーケンス はトリガーシェイプがクリックされたときに開始します。

テキストボックス、画像、チャート、テーブル、その他のスライドオブジェクトはすべてシェイプであるため、ほとんどのスライドコンテンツには同じSequence::addEffectメソッドを使用します。利用可能なエフェクトはEffectTypeクラスに一覧表示されています。

シェイプ アニメーションの追加

アニメーションを追加するには、スライドのメインシーケンスを取得し、対象シェイプ、エフェクトタイプ、サブタイプ、トリガーを指定してSequence::addEffectを呼び出します。他のシェイプがクリックされたときに開始するエフェクトの場合、そのシェイプをトリガーとしたインタラクティブシーケンスを作成します。

以下の例は両方のタイプのアニメーションを作成し、結果を shape-animations.pptx に保存します。

use aspose\slides\EffectSubtype;
use aspose\slides\EffectTriggerType;
use aspose\slides\EffectType;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;

$presentation = new Presentation();
try {
    $slide = $presentation->getSlides()->get_Item(0);

    $targetShape = $slide->getShapes()->addAutoShape(ShapeType::RoundCornerRectangle, 120, 100, 320, 80);
    $targetShape->addTextFrame("Click to animate this shape");

    $mainSequence = $slide->getTimeline()->getMainSequence();
    $entranceEffect = $mainSequence->addEffect($targetShape, EffectType::Fade, EffectSubtype::None, EffectTriggerType::OnClick);
    $entranceEffect->getTiming()->setDuration(1.5);

    $triggerShape = $slide->getShapes()->addAutoShape(ShapeType::Bevel, 20, 20, 100, 40);
    $triggerShape->addTextFrame("Move");

    $interactiveSequence = $slide->getTimeline()->getInteractiveSequences()->add($triggerShape);
    $interactiveSequence->addEffect($targetShape, EffectType::PathFootball, EffectSubtype::None, EffectTriggerType::OnClick);

    $presentation->save("shape-animations.pptx", SaveFormat::Pptx);
} finally {
    $presentation->dispose();
}

トリガーはエフェクトの開始時期を制御します:

画像、チャート、その他のシェイプタイプをアニメーションさせるには、$targetShape の代わりにそのオブジェクトをSequence::addEffectに渡します。チャート固有のグループ化オプションについてはAnimated Chartsをご覧ください。

シェイプ アニメーションの読み取り

対象シェイプが分かっている場合はSequence::getEffectsByShapeを使用します。すべてのエフェクトを確認するには、メインシーケンスとすべてのインタラクティブシーケンスを列挙します。列挙することでシーケンスがインデックス 0 にエフェクトを持つと仮定することを防げます。

以下の例はメインシーケンスとインタラクティブエフェクトを持つシェイプを作成し、シェイプを対象としたエフェクトを取得し、さらにスライド上のすべてのシーケンスを列挙します。

use aspose\slides\EffectSubtype;
use aspose\slides\EffectTriggerType;
use aspose\slides\EffectType;
use aspose\slides\Presentation;
use aspose\slides\ShapeType;

function printSequence($label, $sequence)
{
    $effectCount = java_values($sequence->getCount());

    echo "  " . $label . ": " . $effectCount . " effect(s)" . PHP_EOL;

    for ($effectIndex = 0; $effectIndex < $effectCount; $effectIndex++) {
        $effect = $sequence->get_Item($effectIndex);
        $targetShape = $effect->getTargetShape();
        $targetName = java_is_null($targetShape) ? "unknown" : java_values($targetShape->getName());
        $effectType = java_values($effect->getType());
        $effectSubtype = java_values($effect->getSubtype());
        $triggerType = java_values($effect->getTiming()->getTriggerType());
        echo "    type: " . $effectType . "; subtype: " . $effectSubtype . "; target: " . $targetName . "; trigger: " . $triggerType . PHP_EOL;
    }
}

$presentation = new Presentation();
try {
    $slide = $presentation->getSlides()->get_Item(0);
    $targetShape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 120, 100, 320, 80);
    $targetShape->addTextFrame("Animated shape");

    $mainSequence = $slide->getTimeline()->getMainSequence();
    $mainSequence->addEffect($targetShape, EffectType::Fade, EffectSubtype::None, EffectTriggerType::OnClick);

    $triggerShape = $slide->getShapes()->addAutoShape(ShapeType::Bevel, 20, 20, 100, 40);
    $triggerShape->addTextFrame("Move");

    $interactiveSequence = $slide->getTimeline()->getInteractiveSequences()->add($triggerShape);
    $interactiveSequence->addEffect($targetShape, EffectType::PathFootball, EffectSubtype::None, EffectTriggerType::OnClick);

    $targetEffects = $mainSequence->getEffectsByShape($targetShape);
    $Array = new JavaClass("java.lang.reflect.Array");
    echo "The main sequence contains " . java_values($Array->getLength($targetEffects)) . " effect(s) for " . java_values($targetShape->getName()) . "." . PHP_EOL;

    printSequence("Main sequence", $mainSequence);

    $interactiveSequences = $slide->getTimeline()->getInteractiveSequences();
    $interactiveCount = java_values($interactiveSequences->getCount());
    for ($interactiveIndex = 0; $interactiveIndex < $interactiveCount; $interactiveIndex++) {
        $sequence = $interactiveSequences->get_Item($interactiveIndex);
        $sequenceTrigger = $sequence->getTriggerShape();
        $triggerName = java_is_null($sequenceTrigger) ? "unknown" : java_values($sequenceTrigger->getName());
        printSequence("Interactive sequence " . ($interactiveIndex + 1) . ", trigger: " . $triggerName, $sequence);
    }
} finally {
    $presentation->dispose();
}

1 つのシェイプに対するエフェクトだけが必要な場合は、まず名前、プレースホルダータイプ、または他の安定したプロパティでシェイプを特定し、次にSequence::getEffectsByShapeを呼び出します。ShapeCollection::get_Item のインデックス 0 が常に目的のオブジェクトであると仮定しないでください。

継承されたプレースホルダー エフェクトの操作

通常のスライド上のプレースホルダーは、レイアウトスライドやマスタースライド上の対応するプレースホルダーからアニメーション動作を継承できます。Shape::getBasePlaceholder はその親プレースホルダーを返し、親が存在しない場合は null を返します。

以下の例のプレゼンテーションでは、フッターは通常のスライドでRandom Bars、レイアウトスライドでSplit、マスタースライドでFly In のアニメーションを持ちます。

通常のスライド上のフッター アニメーション効果

レイアウトスライド上のフッター プレースホルダー アニメーション効果

マスタースライド上のフッター プレースホルダー アニメーション効果

次の例は新しいプレゼンテーションからのプレースホルダー階層を使用します。マスタープレースホルダー、レイアウトプレースホルダー、および通常スライド上の対応するプレースホルダーにエフェクトを追加します。Shape::getBasePlaceholder の呼び出しは、返されたシェイプが使用される前に必ずチェックされます。

use aspose\slides\EffectSubtype;
use aspose\slides\EffectTriggerType;
use aspose\slides\EffectType;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\SlideLayoutType;

function findLayoutPlaceholderWithBase($layoutSlide)
{
    $shapes = $layoutSlide->getShapes();
    $shapeCount = java_values($shapes->size());
    for ($shapeIndex = 0; $shapeIndex < $shapeCount; $shapeIndex++) {
        $shape = $shapes->get_Item($shapeIndex);
        if (!java_is_null($shape->getBasePlaceholder())) {
            return $shape;
        }
    }

    return null;
}

function findSlidePlaceholderWithBase($slide, $expectedBase)
{
    $shapes = $slide->getShapes();
    $shapeCount = java_values($shapes->size());
    for ($shapeIndex = 0; $shapeIndex < $shapeCount; $shapeIndex++) {
        $shape = $shapes->get_Item($shapeIndex);
        $basePlaceholder = $shape->getBasePlaceholder();
        if (!java_is_null($basePlaceholder) && java_values($basePlaceholder->equals($expectedBase))) {
            return $shape;
        }
    }

    return null;
}

function printEffects($source, $effects)
{
    $Array = new JavaClass("java.lang.reflect.Array");
    echo $source . ": " . java_values($Array->getLength($effects)) . " effect(s)" . PHP_EOL;

    foreach ($effects as $effect) {
        echo "  type: " . java_values($effect->getType()) . "; subtype: " . java_values($effect->getSubtype()) . PHP_EOL;
    }
}

$presentation = new Presentation();
try {
    $layoutSlide = $presentation->getLayoutSlides()->getByType(SlideLayoutType::TitleAndObject);
    $layoutPlaceholder = findLayoutPlaceholderWithBase($layoutSlide);

    if ($layoutPlaceholder === null) {
        throw new RuntimeException("The layout slide does not contain a placeholder linked to its master slide.");
    }

    $masterPlaceholder = $layoutPlaceholder->getBasePlaceholder();
    $layoutSlide->getMasterSlide()->getTimeline()->getMainSequence()->addEffect($masterPlaceholder, EffectType::Fly, EffectSubtype::Bottom, EffectTriggerType::OnClick);
    $layoutSlide->getTimeline()->getMainSequence()->addEffect($layoutPlaceholder, EffectType::Split, EffectSubtype::VerticalIn, EffectTriggerType::OnClick);

    $slide = $presentation->getSlides()->addEmptySlide($layoutSlide);
    $slidePlaceholder = findSlidePlaceholderWithBase($slide, $layoutPlaceholder);

    if ($slidePlaceholder === null) {
        throw new RuntimeException("The slide does not contain a placeholder linked to its layout slide.");
    }

    $slide->getTimeline()->getMainSequence()->addEffect($slidePlaceholder, EffectType::RandomBars, EffectSubtype::Horizontal, EffectTriggerType::OnClick);
    printEffects("Normal slide", $slide->getTimeline()->getMainSequence()->getEffectsByShape($slidePlaceholder));

    $baseLayoutPlaceholder = $slidePlaceholder->getBasePlaceholder();
    if (!java_is_null($baseLayoutPlaceholder)) {
        printEffects("Layout slide", $layoutSlide->getTimeline()->getMainSequence()->getEffectsByShape($baseLayoutPlaceholder));

        $baseMasterPlaceholder = $baseLayoutPlaceholder->getBasePlaceholder();
        if (!java_is_null($baseMasterPlaceholder)) {
            printEffects("Master slide", $layoutSlide->getMasterSlide()->getTimeline()->getMainSequence()->getEffectsByShape($baseMasterPlaceholder));
        }
    }

    $presentation->save("placeholder-animations.pptx", SaveFormat::Pptx);
} finally {
    $presentation->dispose();
}

アニメーション タイミングの変更

PowerPoint のTiming ダイアログはTiming のプロパティに対応しています。

アニメーション効果の PowerPoint タイミング ダイアログ

この独立した例はエフェクトを追加し、Sequence::addEffect が返すオブジェクトを通じてそのタイミングを変更し、結果を保存します。返されたEffect の参照を保持することで不要なコレクションインデックスを避けられます。

use aspose\slides\EffectSubtype;
use aspose\slides\EffectTriggerType;
use aspose\slides\EffectType;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;

$presentation = new Presentation();
try {
    $slide = $presentation->getSlides()->get_Item(0);
    $shape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 120, 100, 320, 80);
    $shape->addTextFrame("Timed animation");

    $effect = $slide->getTimeline()->getMainSequence()->addEffect($shape, EffectType::Fade, EffectSubtype::None, EffectTriggerType::OnClick);
    $effect->getTiming()->setTriggerType(EffectTriggerType::OnClick);
    $effect->getTiming()->setDuration(2.0);
    $effect->getTiming()->setTriggerDelayTime(0.5);
    $effect->getTiming()->setRepeatUntilNextClick(false);
    $effect->getTiming()->setRepeatUntilEndSlide(false);
    $effect->getTiming()->setRepeatCount(2.0);
    $effect->getTiming()->setRewind(true);

    $presentation->save("shape-animation-timing.pptx", SaveFormat::Pptx);
} finally {
    $presentation->dispose();
}

意図的に 1 つのリピートモードのみを使用してください。リピート回数と「until」フラグを組み合わせると、ビューアーによって混乱する結果になることがあります。リピートモードを変更する際は、Timing::setRepeatCount の前にTiming::setRepeatUntilNextClickTiming::setRepeatUntilEndSlide を設定してください。これらのフラグの設定はアクティブなリピートモードも変更します。

アニメーションサウンドの追加と抽出

アニメーションエフェクトはEffect::getSound を使用して埋め込み音声を参照できます。Effect::setStopPreviousSound は、以前のエフェクトで開始された音声を停止するようエフェクトに指示します。

エフェクトにサウンドを追加

以下の例は animation-sound.wav というローカル音声ファイルを前提とします。2 つのエフェクトを作成し、最初のエフェクトのサウンドとしてそのファイルを埋め込み、2 番目のエフェクトがサウンドを停止するよう構成します。Sequence::addEffect が返すオブジェクトを使用するため、シーケンスインデックスは不要です。

use aspose\slides\EffectSubtype;
use aspose\slides\EffectTriggerType;
use aspose\slides\EffectType;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;

$Files = new JavaClass("java.nio.file.Files");

$presentation = new Presentation();
try {
    $slide = $presentation->getSlides()->get_Item(0);
    $firstShape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 80, 100, 240, 80);
    $secondShape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 400, 100, 240, 80);
    $firstShape->addTextFrame("Starts sound");
    $secondShape->addTextFrame("Stops sound");

    $sequence = $slide->getTimeline()->getMainSequence();
    $firstEffect = $sequence->addEffect($firstShape, EffectType::Fade, EffectSubtype::None, EffectTriggerType::OnClick);
    $secondEffect = $sequence->addEffect($secondShape, EffectType::Fade, EffectSubtype::None, EffectTriggerType::OnClick);

    $baseDirectory = getcwd();
    $audioPath = (new Java("java.io.File", $baseDirectory . DIRECTORY_SEPARATOR . "animation-sound.wav"))->toPath();
    $audioData = $Files->readAllBytes($audioPath);
    $effectSound = $presentation->getAudios()->addAudio($audioData);
    $firstEffect->setSound($effectSound);
    $secondEffect->setStopPreviousSound(true);

    $presentation->save($baseDirectory . DIRECTORY_SEPARATOR . "shape-animation-sound.pptx", SaveFormat::Pptx);
} finally {
    $presentation->dispose();
}

埋め込みエフェクトサウンドの抽出

以下の例は presentation-with-animation-sounds.pptx というローカルプレゼンテーションを前提とします。メインシーケンスとインタラクティブシーケンスの両方を走査し、埋め込まれたエフェクトサウンドをすべて extracted-animation-sounds ディレクトリに書き出します。拡張子はAudio::getContentType が提供する音声 MIME タイプから選択されます。

use aspose\slides\Presentation;

function getAudioExtension($contentType)
{
    $normalizedType = strtolower($contentType === null ? "" : java_values($contentType));

    if ($normalizedType === "audio/mpeg") {
        return ".mp3";
    }

    if ($normalizedType === "audio/mp4") {
        return ".m4a";
    }

    if ($normalizedType === "audio/ogg") {
        return ".ogg";
    }

    if ($normalizedType === "audio/wav" || $normalizedType === "audio/x-wav") {
        return ".wav";
    }

    return ".bin";
}

function saveSounds($sequence, $outputDirectory, $soundIndex)
{
    $effectCount = java_values($sequence->getCount());
    for ($effectIndex = 0; $effectIndex < $effectCount; $effectIndex++) {
        $effect = $sequence->get_Item($effectIndex);
        $sound = $effect->getSound();
        if (java_is_null($sound)) {
            continue;
        }

        $extension = getAudioExtension($sound->getContentType());
        $outputPath = $outputDirectory->resolve("effect-sound-" . $soundIndex . $extension);
        $outputStream = new Java("java.io.FileOutputStream", $outputPath->toFile());
        try {
            $outputStream->write($sound->getBinaryData());
        } finally {
            $outputStream->close();
        }
        $soundIndex++;
    }

    return $soundIndex;
}

$baseDirectory = getcwd();
$inputPath = (new Java("java.io.File", $baseDirectory . DIRECTORY_SEPARATOR . "presentation-with-animation-sounds.pptx"))->toPath();
$outputDirectoryName = $baseDirectory . DIRECTORY_SEPARATOR . "extracted-animation-sounds";
if (!is_dir($outputDirectoryName)) {
    mkdir($outputDirectoryName, 0777, true);
}
$outputDirectory = (new Java("java.io.File", $outputDirectoryName))->toPath();

$presentation = new Presentation($inputPath->toString());
try {
    $soundIndex = 1;

    $slides = $presentation->getSlides();
    $slideCount = java_values($slides->size());
    for ($slideIndex = 0; $slideIndex < $slideCount; $slideIndex++) {
        $slide = $slides->get_Item($slideIndex);
        $soundIndex = saveSounds($slide->getTimeline()->getMainSequence(), $outputDirectory, $soundIndex);

        $interactiveSequences = $slide->getTimeline()->getInteractiveSequences();
        $interactiveCount = java_values($interactiveSequences->getCount());
        for ($sequenceIndex = 0; $sequenceIndex < $interactiveCount; $sequenceIndex++) {
            $sequence = $interactiveSequences->get_Item($sequenceIndex);
            $soundIndex = saveSounds($sequence, $outputDirectory, $soundIndex);
        }
    }

    echo "Extracted " . ($soundIndex - 1) . " sound file(s) to " . java_values($outputDirectory->toAbsolutePath()->toString()) . "." . PHP_EOL;
} finally {
    $presentation->dispose();
}

大きな音声オブジェクトの場合は、Audio::getStream を使用し、全体をバイト配列に読み込むのではなくストリームをファイルにコピーしてください。

アフターアニメーション 動作の設定

After animation オプションは、エフェクトが終了した後にシェイプに何が起こるかを制御します。

After animation 設定を示す PowerPoint エフェクトオプション ダイアログ

AfterAnimationType クラスは、シェイプを変更せずに保持する、色を変更する、アニメーション後に非表示にする、または次のクリックで非表示にする、という動作をサポートします。タイプがAfterAnimationType::Color の場合は、Effect::getAfterAnimationColor も設定してください。

この独立した例はエフェクトを作成し、返されたエフェクトオブジェクトを通じてアフターアニメーション動作を設定し、結果を保存します。

use aspose\slides\AfterAnimationType;
use aspose\slides\EffectSubtype;
use aspose\slides\EffectTriggerType;
use aspose\slides\EffectType;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;

$presentation = new Presentation();
try {
    $slide = $presentation->getSlides()->get_Item(0);
    $shape = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 120, 100, 320, 80);
    $shape->addTextFrame("Dim after animation");

    $effect = $slide->getTimeline()->getMainSequence()->addEffect($shape, EffectType::Fade, EffectSubtype::None, EffectTriggerType::OnClick);
    $effect->setAfterAnimationType(AfterAnimationType::Color);
    $effect->getAfterAnimationColor()->setColor(java("java.awt.Color")->LIGHT_GRAY);

    $presentation->save("shape-animation-after-effect.pptx", SaveFormat::Pptx);
} finally {
    $presentation->dispose();
}

AfterAnimationType::Color 以外のタイプに変更すると、アフターアニメーションのカラー設定はクリアされます。

テキスト アニメーション

テキストアニメーションには 2 つの関連する制御があります:

  • TextAnimation::getBuildType は段落がまとめて表示されるか段落レベルで表示されるかを制御します。
  • Effect::getAnimateTextType はテキストが一度に表示されるか、単語ごと、または文字ごとに表示されるかを制御します。Effect::getDelayBetweenTextParts は単語または文字間の遅延を設定します。正の値はエフェクト期間のパーセンテージ、負の値は秒単位の遅延です。

以下の独立した例はテキストボックス内の単語をアニメーション化します。BuildType::AsOneObject は段落ごとのビルドを無効にし、単語設定がテキストフレーム全体に適用されるようにします。

use aspose\slides\AnimateTextType;
use aspose\slides\BuildType;
use aspose\slides\EffectSubtype;
use aspose\slides\EffectTriggerType;
use aspose\slides\EffectType;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;

$presentation = new Presentation();
try {
    $slide = $presentation->getSlides()->get_Item(0);
    $textBox = $slide->getShapes()->addAutoShape(ShapeType::Rectangle, 80, 80, 560, 100);
    $textBox->addTextFrame("Aspose.Slides animates this sentence word by word.");

    $effect = $slide->getTimeline()->getMainSequence()->addEffect($textBox, EffectType::Fade, EffectSubtype::None, EffectTriggerType::OnClick);
    $effect->getTextAnimation()->setBuildType(BuildType::AsOneObject);
    $effect->setAnimateTextType(AnimateTextType::ByWord);
    $effect->setDelayBetweenTextParts(20.0);

    $presentation->save("animated-text.pptx", SaveFormat::Pptx);
} finally {
    $presentation->dispose();
}

段落単位でテキストボックスをビルドするには、BuildType::ByLevelParagraphs1(または他の段落レベル)を設定します。単一の段落に固有のエフェクトを適用するには、Paragraph を受け取るSequence::addEffect のオーバーロードを使用してください。段落レベルの例についてはAnimated Textをご覧ください。

エクスポートと互換性に関する注意点

  • PPT または PPTX への保存はアニメーションモデルを保持しますが、最終的な再生はプレゼンテーションビューアーが制御します。
  • PDF や静止画像はアニメーションを再生しません。出力に動きが必要な場合はHTML5 export、アニメーション GIF、またはvideo conversion を使用してください。
  • HTML5 用にはHtml5Options::setAnimateShapes を有効にし、必要に応じてHtml5Options::setAnimateTransitions を設定してください。
  • ビデオレンダリングは多数の一般的な入場、強調、退出、モーションパスエフェクトをサポートしますが、すべての PowerPoint エフェクトがサポートされているわけではありません。現在のsupported animations and effects を確認し、重要なプレゼンテーションを対象の Aspose.Slides バージョンでテストしてください。
  • 高度なカスタムエフェクトや他のプレゼンテーション形式からインポートされたエフェクトはファイル内で保持される場合がありますが、PowerPoint、HTML5、またはビデオでのレンダリングが異なることがあります。エフェクト名のみで判断せず、エクスポート結果を検証してください。

よくある質問

なぜアニメーションは PowerPoint では表示されるが PDF では表示されないのですか?

PDF は静的な形式であるため、アニメーションやスライド遷移は再生されません。動きを保持する必要がある場合は、HTML5、アニメーション GIF、またはビデオにエクスポートしてください。

なぜエフェクトはビデオで異なる再生になるのですか?

ビデオエクスポートはアニメーションをレンダリングし、元の PowerPoint の動作を保持しません。一部の高度なエフェクトはサポートされていないか、近似されています。サポートされているエフェクトの表を確認し、実際のプレゼンテーションを本番使用前にテストしてください。

シェイプを前方または後方に移動するとアニメーションの順序が変わりますか?

いいえ。シェイプの Z 順序は重なりを制御し、シーケンスの順序とトリガーがアニメーションの再生を制御します。再生順序を変更したい場合は、タイムラインを調整してください。