.NET でプレゼンテーションにシェイプ アニメーションを適用する

概要

エフェクト内の個々の動作やモーション パス セグメントを編集するには、カスタム アニメーションをご覧ください。

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

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

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

テキスト ボックス、画像、チャート、表、その他のスライド オブジェクトはすべて IShape を実装しているため、ほとんどのスライド コンテンツに対して同じ ISequence.AddEffect メソッドを使用します。利用可能なエフェクトは EffectType 列挙体に一覧表示されています。

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

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

次の例は 2 種類のアニメーションを作成し、結果を shape-animations.pptx に保存します。

using Aspose.Slides;
using Aspose.Slides.Animation;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];

var targetShape = slide.Shapes.AddAutoShape(ShapeType.RoundCornerRectangle, 120, 100, 320, 80);
targetShape.TextFrame.Text = "Click to animate this shape";

var mainSequence = slide.Timeline.MainSequence;
var entranceEffect = mainSequence.AddEffect(targetShape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
entranceEffect.Timing.Duration = 1.5f;

var triggerShape = slide.Shapes.AddAutoShape(ShapeType.Bevel, 20, 20, 100, 40);
triggerShape.TextFrame.Text = "Move";

var interactiveSequence = slide.Timeline.InteractiveSequences.Add(triggerShape);
interactiveSequence.AddEffect(targetShape, EffectType.PathFootball, EffectSubtype.None, EffectTriggerType.OnClick);

presentation.Save("shape-animations.pptx", SaveFormat.Pptx);

トリガーはエフェクトの開始タイミングを制御します。

画像、チャート、その他のシェイプ タイプをアニメーション化する場合は、targetShape の代わりにそのオブジェクトを ISequence.AddEffect に渡します。チャート固有のグループ化オプションについては、アニメーション チャート を参照してください。

シェイプ アニメーションの取得

対象シェイプが分かっている場合は、ISequence.GetEffectsByShape を使用します。すべてのエフェクトを検査したいときは、メイン シーケンスとすべてのインタラクティブ シーケンスを列挙します。列挙はインデックス 0 にエフェクトが必ず存在すると仮定しないようにしてください。

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

using System;
using Aspose.Slides;
using Aspose.Slides.Animation;

using var presentation = new Presentation();
var slide = presentation.Slides[0];
var targetShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 120, 100, 320, 80);
targetShape.TextFrame.Text = "Animated shape";

var mainSequence = slide.Timeline.MainSequence;
mainSequence.AddEffect(targetShape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);

var triggerShape = slide.Shapes.AddAutoShape(ShapeType.Bevel, 20, 20, 100, 40);
triggerShape.TextFrame.Text = "Move";

var interactiveSequence = slide.Timeline.InteractiveSequences.Add(triggerShape);
interactiveSequence.AddEffect(targetShape, EffectType.PathFootball, EffectSubtype.None, EffectTriggerType.OnClick);

var targetEffects = mainSequence.GetEffectsByShape(targetShape);
Console.WriteLine($"The main sequence contains {targetEffects.Length} effect(s) for {targetShape.Name}.");

PrintSequence("Main sequence", mainSequence);

var interactiveIndex = 1;
foreach (var sequence in slide.Timeline.InteractiveSequences)
{
    var triggerName = sequence.TriggerShape == null ? "unknown" : sequence.TriggerShape.Name;
    var sequenceLabel = $"Interactive sequence {interactiveIndex}, trigger: {triggerName}";
    PrintSequence(sequenceLabel, sequence);
    interactiveIndex++;
}

static void PrintSequence(string label, ISequence sequence)
{
    Console.WriteLine($"  {label}: {sequence.Count} effect(s)");

    foreach (var effect in sequence)
    {
        var targetName = effect.TargetShape == null ? "unknown" : effect.TargetShape.Name;
        var effectDescription = $"{effect.Type} {effect.Subtype}; target: {targetName}; trigger: {effect.Timing.TriggerType}";
        Console.WriteLine($"    {effectDescription}");
    }
}

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

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

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

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

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

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

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

次の例はプレースホルダー階層を自分で構築します。マスタープレースホルダー、レイアウトプレースホルダー、通常スライド上の対応プレースホルダーにエフェクトを追加し、各呼び出しで IShape.GetBasePlaceholder の結果が null でないことを確認しています。

using System;
using Aspose.Slides;
using Aspose.Slides.Animation;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var layoutSlide = presentation.LayoutSlides.GetByType(SlideLayoutType.Blank);
var layoutPlaceholder = layoutSlide.PlaceholderManager.AddTextPlaceholder(100, 100, 400, 80);
layoutSlide.Timeline.MainSequence.AddEffect(layoutPlaceholder, EffectType.Split, EffectSubtype.VerticalIn, EffectTriggerType.OnClick);

var masterPlaceholder = layoutPlaceholder.GetBasePlaceholder();
if (masterPlaceholder != null)
{
    var masterSequence = layoutSlide.MasterSlide.Timeline.MainSequence;
    masterSequence.AddEffect(masterPlaceholder, EffectType.Fly, EffectSubtype.Bottom, EffectTriggerType.OnClick);
}

var slide = presentation.Slides.AddEmptySlide(layoutSlide);
var slidePlaceholder = FindPlaceholderWithBase(slide);

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

slide.Timeline.MainSequence.AddEffect(slidePlaceholder, EffectType.RandomBars, EffectSubtype.Horizontal, EffectTriggerType.OnClick);
PrintEffects("Normal slide", slide.Timeline.MainSequence.GetEffectsByShape(slidePlaceholder));

var baseLayoutPlaceholder = slidePlaceholder.GetBasePlaceholder();
if (baseLayoutPlaceholder != null)
{
    PrintEffects("Layout slide", layoutSlide.Timeline.MainSequence.GetEffectsByShape(baseLayoutPlaceholder));

    var baseMasterPlaceholder = baseLayoutPlaceholder.GetBasePlaceholder();
    if (baseMasterPlaceholder != null)
    {
        PrintEffects("Master slide", layoutSlide.MasterSlide.Timeline.MainSequence.GetEffectsByShape(baseMasterPlaceholder));
    }
}

presentation.Save("placeholder-animations.pptx", SaveFormat.Pptx);

static IShape FindPlaceholderWithBase(ISlide slide)
{
    foreach (var shape in slide.Shapes)
    {
        if (shape.GetBasePlaceholder() != null)
        {
            return shape;
        }
    }

    return null;
}

static void PrintEffects(string source, IEffect[] effects)
{
    Console.WriteLine($"{source}: {effects.Length} effect(s)");

    foreach (var effect in effects)
    {
        Console.WriteLine($"  {effect.Type} {effect.Subtype}");
    }
}

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

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

アニメーション エフェクトの PowerPoint タイミング ダイアログ

この独立した例はエフェクトを追加し、ISequence.AddEffect が返すオブジェクトを介してタイミングを変更し、結果を保存します。返された IEffect 参照を保持することで不要なコレクション インデックス取得を回避します。

using Aspose.Slides;
using Aspose.Slides.Animation;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];
var shape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 120, 100, 320, 80);
shape.TextFrame.Text = "Timed animation";

var effect = slide.Timeline.MainSequence.AddEffect(shape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
effect.Timing.TriggerType = EffectTriggerType.OnClick;
effect.Timing.Duration = 2.0f;
effect.Timing.TriggerDelayTime = 0.5f;
effect.Timing.RepeatUntilNextClick = false;
effect.Timing.RepeatUntilEndSlide = false;
effect.Timing.RepeatCount = 2.0f;
effect.Timing.Rewind = true;

presentation.Save("shape-animation-timing.pptx", SaveFormat.Pptx);

繰り返しモードは 1 つだけ使用してください。繰り返し回数と「until」フラグを組み合わせると、ビューアー間で混乱を招く結果になることがあります。繰り返しモードを変更する際は、ITiming.RepeatUntilNextClick と ITiming.RepeatUntilEndSlide を先に設定し、最後に ITiming.RepeatCount を設定してください。いずれかのフラグを設定するとアクティブな繰り返しモードも変更されます。

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

アニメーション エフェクトは IEffect.Sound を介して埋め込みオーディオを参照できます。IEffect.StopPreviousSound は、以前のエフェクトが開始したオーディオを停止させます。

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

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

using System.IO;
using Aspose.Slides;
using Aspose.Slides.Animation;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];
var firstShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 80, 100, 240, 80);
var secondShape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 400, 100, 240, 80);
firstShape.TextFrame.Text = "Starts sound";
secondShape.TextFrame.Text = "Stops sound";

var sequence = slide.Timeline.MainSequence;
var firstEffect = sequence.AddEffect(firstShape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
var secondEffect = sequence.AddEffect(secondShape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);

var audioData = File.ReadAllBytes("animation-sound.wav");
var effectSound = presentation.Audios.AddAudio(audioData);
firstEffect.Sound = effectSound;
secondEffect.StopPreviousSound = true;

presentation.Save("shape-animation-sound.pptx", SaveFormat.Pptx);

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

次の例はローカルのプレゼンテーション presentation-with-animation-sounds.pptx を前提とします。メイン シーケンスとインタラクティブ シーケンスを走査し、すべての埋め込みエフェクト サウンドを extracted-animation-sounds ディレクトリに書き出します。拡張子は IAudio.ContentType が示すオーディオ MIME タイプから選択します。

using System;
using System.IO;
using Aspose.Slides;
using Aspose.Slides.Animation;

var inputPath = "presentation-with-animation-sounds.pptx";
var outputDirectory = "extracted-animation-sounds";

Directory.CreateDirectory(outputDirectory);

using var presentation = new Presentation(inputPath);
var soundIndex = 1;

foreach (var slide in presentation.Slides)
{
    SaveSounds(slide.Timeline.MainSequence, outputDirectory, ref soundIndex);

    foreach (var sequence in slide.Timeline.InteractiveSequences)
    {
        SaveSounds(sequence, outputDirectory, ref soundIndex);
    }
}

Console.WriteLine($"Extracted {soundIndex - 1} sound file(s) to {Path.GetFullPath(outputDirectory)}.");

static void SaveSounds(ISequence sequence, string outputDirectory, ref int soundIndex)
{
    foreach (var effect in sequence)
    {
        if (effect.Sound == null)
            continue;

        var extension = GetAudioExtension(effect.Sound.ContentType);
        var outputPath = Path.Combine(outputDirectory, $"effect-sound-{soundIndex}{extension}");
        File.WriteAllBytes(outputPath, effect.Sound.BinaryData);
        soundIndex++;
    }
}

static string GetAudioExtension(string contentType)
{
    var normalizedType = contentType == null ? string.Empty : contentType.ToLowerInvariant();

    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";
}

大きなオーディオ オブジェクトの場合は、IAudio.GetStream を使用してストリームをファイルにコピーし、全体をバイト配列として読み込むのを避けてください。

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

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

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

AfterAnimationType 列挙体は、シェイプをそのまま残す、色を変更する、アニメーション後に非表示にする、次のクリックで非表示にする、などをサポートします。タイプが AfterAnimationType.Color の場合は、IEffect.AfterAnimationColor も設定してください。

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

using System.Drawing;
using Aspose.Slides;
using Aspose.Slides.Animation;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];
var shape = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 120, 100, 320, 80);
shape.TextFrame.Text = "Dim after animation";

var effect = slide.Timeline.MainSequence.AddEffect(shape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
effect.AfterAnimationType = AfterAnimationType.Color;
effect.AfterAnimationColor.Color = Color.LightGray;

presentation.Save("shape-animation-after-effect.pptx", SaveFormat.Pptx);

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

テキストのアニメーション

テキスト アニメーションには次の 2 つの関連設定があります。

  • ITextAnimation.BuildType は段落単位で表示するか、全体として表示するかを制御します。
  • IEffect.AnimateTextType はテキストの表示方法(すべて同時、単語単位、文字単位)を制御します。IEffect.DelayBetweenTextParts は単語または文字間の遅延を設定します。正の値はエフェクト期間の割合、負の値は秒数です。

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

using Aspose.Slides;
using Aspose.Slides.Animation;
using Aspose.Slides.Export;

using var presentation = new Presentation();
var slide = presentation.Slides[0];
var textBox = slide.Shapes.AddAutoShape(ShapeType.Rectangle, 80, 80, 560, 100);
textBox.TextFrame.Text = "Aspose.Slides animates this sentence word by word.";

var effect = slide.Timeline.MainSequence.AddEffect(textBox, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
effect.TextAnimation.BuildType = BuildType.AsOneObject;
effect.AnimateTextType = AnimateTextType.ByWord;
effect.DelayBetweenTextParts = 20.0f;

presentation.Save("animated-text.pptx", SaveFormat.Pptx);

段落単位でテキスト ボックスを構築したい場合は、BuildType.ByLevelParagraphs1(または他の段落レベル)を設定します。単一の段落に独自のエフェクトを適用したいときは、IParagraph を受け取る ISequence.AddEffect のオーバーロードを使用してください。段落レベルの例については、アニメーション テキスト を参照してください。

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

  • PPT または PPTX に保存するとアニメーション モデルは保持されますが、最終的な再生はプレゼンテーション ビューアーが制御します。
  • PDF および静止画像はアニメーションを再生しません。モーションを示す必要がある場合は、HTML5 エクスポート、アニメーション GIF、またはビデオ変換 を使用してください。
  • HTML5 では Html5Options.AnimateShapes を有効にし、必要に応じて Html5Options.AnimateTransitions も有効にしてください。
  • ビデオ描画は多くの一般的な入場、強調、退出、モーション パス エフェクトをサポートしますが、すべての PowerPoint エフェクトがサポートされるわけではありません。現在の サポートされるアニメーションとエフェクト を確認し、対象の Aspose.Slides バージョンで重要なプレゼンテーションをテストしてください。
  • カスタム エフェクトや他のプレゼンテーション形式からインポートされたエフェクトはファイル内に保持されることがありますが、PowerPoint、HTML5、ビデオでの描画が異なる場合があります。エフェクト名だけに依存せず、エクスポート結果を検証してください。

FAQ

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

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

なぜエフェクトはビデオで異なる動作をするのですか?

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

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

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