اعمال انیمیشن شکل‌ها در ارائه‌ها بر روی Android

مرور کلی

برای کار با رفتارهای فردی داخل یک اثر یا ویرایش بخش‌های مسیر حرکت، به Custom Animation for Java مراجعه کنید.

Aspose.Slides برای Android از طریق Java انیمیشن‌های اسلاید را به‌عنوان اثرها در یک جدول زمانی اسلاید نمایش می‌دهد. یک اثر شامل شکل هدف، نوع و زیرنوع انیمیشن، یک محرک، تنظیمات زمان‌بندی و ویژگی‌های اختیاری مانند صدا یا رفتار پس از انیمیشن است.

جدول زمانی دو نوع توالی را شامل می‌شود:

  • توالی اصلی هنگام پیشروی اسلاید اجرا می‌شود.
  • توالی تعاملی زمانی شروع می‌شود که شکل محرک آن کلیک شود.

از آنجا که جعبه‌های متن، تصاویر، نمودارها، جدول‌ها و سایر اشیای اسلاید IShape را پیاده‌سازی می‌کنند، برای بیشتر محتوای اسلاید از همان متد ISequence.addEffect استفاده می‌کنید. اثرهای موجود در کلاس EffectType فهرست شده‌اند.

افزودن انیمیشن به اشکال

برای افزودن یک انیمیشن، توالی اصلی اسلاید را دریافت کنید و متد ISequence.addEffect را با شکل هدف، نوع اثر، زیرنوع و محرک صدا بزنید. برای یک اثر که هنگام کلیک روی شکل دیگری شروع می‌شود، یک توالی تعاملی ایجاد کنید که محرکش همان شکل دیگر باشد.

مثال زیر هر دو نوع انیمیشن را ایجاد می‌کند و نتیجه را در shape-animations.pptx ذخیره می‌گردد.

import com.aspose.slides.*;

public class AddShapeAnimations {
    public static void main(String[] args) {
        Presentation presentation = new Presentation();
        try {
            ISlide slide = presentation.getSlides().get_Item(0);

            IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.RoundCornerRectangle, 120, 100, 320, 80);
            targetShape.addTextFrame("Click to animate this shape");

            ISequence mainSequence = slide.getTimeline().getMainSequence();
            IEffect entranceEffect = mainSequence.addEffect(targetShape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
            entranceEffect.getTiming().setDuration(1.5f);

            IAutoShape triggerShape = slide.getShapes().addAutoShape(ShapeType.Bevel, 20, 20, 100, 40);
            triggerShape.addTextFrame("Move");

            ISequence 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 آن شیء را به ISequence.addEffect پاس می‌دهید. برای گزینه‌های گروه‌بندی خاص نمودارها، به Animated Charts مراجعه کنید.

خواندن انیمیشن‌های شکل

از ISequence.getEffectsByShape زمانی که شکل هدف را می‌دانید استفاده کنید. برای بررسی هر اثر، توالی اصلی و تمام توالی‌های تعاملی را مرور کنید. مرور (enumeration) از فرض داشتن یک اثر در ایندکس 0 جلوگیری می‌کند.

مثال زیر یک شکل با اثرهای توالی اصلی و تعاملی ایجاد می‌کند، اثرهایی که هدف آن شکل هستند را دریافت می‌کند و سپس تمام توالی‌های موجود در اسلاید را مرور می‌کند.

import com.aspose.slides.*;

public class ReadShapeAnimations {
    public static void main(String[] args) {
        Presentation presentation = new Presentation();
        try {
            ISlide slide = presentation.getSlides().get_Item(0);
            IAutoShape targetShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 120, 100, 320, 80);
            targetShape.addTextFrame("Animated shape");

            ISequence mainSequence = slide.getTimeline().getMainSequence();
            mainSequence.addEffect(targetShape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);

            IAutoShape triggerShape = slide.getShapes().addAutoShape(ShapeType.Bevel, 20, 20, 100, 40);
            triggerShape.addTextFrame("Move");

            ISequence interactiveSequence = slide.getTimeline().getInteractiveSequences().add(triggerShape);
            interactiveSequence.addEffect(targetShape, EffectType.PathFootball, EffectSubtype.None, EffectTriggerType.OnClick);

            IEffect[] targetEffects = mainSequence.getEffectsByShape(targetShape);
            System.out.println("The main sequence contains " + targetEffects.length + " effect(s) for " + targetShape.getName() + ".");

            printSequence("Main sequence", mainSequence);

            int interactiveIndex = 1;
            for (ISequence sequence : slide.getTimeline().getInteractiveSequences()) {
                String triggerName = sequence.getTriggerShape() == null ? "unknown" : sequence.getTriggerShape().getName();
                String sequenceLabel = "Interactive sequence " + interactiveIndex + ", trigger: " + triggerName;
                printSequence(sequenceLabel, sequence);
                interactiveIndex++;
            }
        } finally {
            presentation.dispose();
        }
    }

    private static void printSequence(String label, ISequence sequence) {
        System.out.println("  " + label + ": " + sequence.getCount() + " effect(s)");

        for (IEffect effect : sequence) {
            String targetName = effect.getTargetShape() == null ? "unknown" : effect.getTargetShape().getName();
            String typeName = EffectType.getName(EffectType.class, effect.getType());
            String subtypeName = EffectSubtype.getName(EffectSubtype.class, effect.getSubtype());
            String triggerName = EffectTriggerType.getName(EffectTriggerType.class, effect.getTiming().getTriggerType());
            String effectDescription = typeName + " " + subtypeName + "; target: " + targetName + "; trigger: " + triggerName;
            System.out.println("    " + effectDescription);
        }
    }
}

اگر فقط به اثرهای یک شکل نیاز دارید، ابتدا شکل را بر اساس نام، نوع placeholder یا ویژگی پایدار دیگری شناسایی کنید؛ سپس ISequence.getEffectsByShape را فراخوانی کنید. فرض نکنید که IShapeCollection.get_Item در ایندکس 0 همیشه شیء مورد نظر است.

کار با اثرهای Placeholder ارث‌بری شده

یک placeholder روی یک اسلاید عادی می‌تواند رفتار انیمیشن را از placeholder متناظر روی اسلاید طرح‌بندی و اسلاید اصلی به ارث ببرد. IShape.getBasePlaceholder آن placeholder والد را برمی‌گرداند یا وقتی والد وجود نداشته باشد null.

در ارائه مثال زیر، پابرگ دارای Random Bars روی اسلاید عادی، Split روی اسلاید طرح‌بندی، و Fly In روی اسلاید اصلی است.

اثر انیمیشن پابرگ در اسلاید عادی

اثر انیمیشن placeholder پابرگ در اسلاید طرح‌بندی

اثر انیمیشن placeholder پابرگ در اسلاید اصلی

مثال بعدی از یک سلسله‌مراتبی placeholder در یک ارائه جدید استفاده می‌کند. اثرهایی به یک placeholder اصلی، یک placeholder طرح‌بندی و placeholder متناظر در اسلاید عادی اضافه می‌کند. هر فراخوانی به IShape.getBasePlaceholder پیش از استفاده از شکل برگردانده شده بررسی می‌شود.

import com.aspose.slides.*;

public class InheritedPlaceholderAnimations {
    public static void main(String[] args) {
        Presentation presentation = new Presentation();
        try {
            ILayoutSlide layoutSlide = presentation.getLayoutSlides().getByType(SlideLayoutType.TitleAndObject);
            IShape layoutPlaceholder = findPlaceholderWithBase(layoutSlide);

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

            IShape 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);

            ISlide slide = presentation.getSlides().addEmptySlide(layoutSlide);
            IShape slidePlaceholder = findPlaceholderWithBase(slide, layoutPlaceholder);

            if (slidePlaceholder == null) {
                throw new IllegalStateException("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));

            IShape baseLayoutPlaceholder = slidePlaceholder.getBasePlaceholder();
            if (baseLayoutPlaceholder != null) {
                printEffects("Layout slide", layoutSlide.getTimeline().getMainSequence().getEffectsByShape(baseLayoutPlaceholder));

                IShape baseMasterPlaceholder = baseLayoutPlaceholder.getBasePlaceholder();
                if (baseMasterPlaceholder != null) {
                    printEffects("Master slide", layoutSlide.getMasterSlide().getTimeline().getMainSequence().getEffectsByShape(baseMasterPlaceholder));
                }
            }

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

    private static IShape findPlaceholderWithBase(ILayoutSlide layoutSlide) {
        for (IShape shape : layoutSlide.getShapes()) {
            if (shape.getBasePlaceholder() != null) {
                return shape;
            }
        }

        return null;
    }

    private static IShape findPlaceholderWithBase(ISlide slide, IShape expectedBase) {
        for (IShape shape : slide.getShapes()) {
            if (shape.getBasePlaceholder() == expectedBase) {
                return shape;
            }
        }

        return null;
    }

    private static void printEffects(String source, IEffect[] effects) {
        System.out.println(source + ": " + effects.length + " effect(s)");

        for (IEffect effect : effects) {
            String typeName = EffectType.getName(EffectType.class, effect.getType());
            String subtypeName = EffectSubtype.getName(EffectSubtype.class, effect.getSubtype());
            System.out.println("  " + typeName + " " + subtypeName);
        }
    }
}

تغییر زمان‌بندی انیمیشن

پنجره Timing در PowerPoint به ویژگی‌های ITiming نگاشت می‌شود.

پنجره Timing در PowerPoint برای یک اثر انیمیشن

این مثال مستقل یک اثر اضافه می‌کند، زمان‌بندی آن را از طریق شیء بازگشتی توسط ISequence.addEffect تغییر می‌دهد و نتیجه را ذخیره می‌کند. نگه داشتن مرجع بازگشتی IEffect از یک ایندکس‌گذاری غیرضروری جمع‌آوری جلوگیری می‌کند.

import com.aspose.slides.*;

public class ChangeAnimationTiming {
    public static void main(String[] args) {
        Presentation presentation = new Presentation();
        try {
            ISlide slide = presentation.getSlides().get_Item(0);
            IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 120, 100, 320, 80);
            shape.addTextFrame("Timed animation");

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

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

به‌صورت عمدی فقط از یک حالت تکرار استفاده کنید. ترکیب یک شمارش تکرار با پرچم «until» می‌تواند نتایج گیج‌کننده‌ای در نمایشگرهای مختلف ایجاد کند. هنگام تغییر حالت‌های تکرار، قبل از ITiming.setRepeatCount ابتدا ITiming.setRepeatUntilNextClick و ITiming.setRepeatUntilEndSlide را تنظیم کنید، زیرا تنظیم هر یک از پرچم‌ها حالت فعال تکرار را نیز تغییر می‌دهد.

افزودن و استخراج صداهای انیمیشن

یک اثر انیمیشن می‌تواند از طریق IEffect.getSound به صداهای توکار ارجاع دهد. IEffect.setStopPreviousSound به یک اثر می‌گوید صداهای شروع‌شده توسط اثر قبلی را متوقف کند.

افزودن صدا به یک اثر

مثال زیر انتظار دارد یک فایل صوتی محلی به نام animation-sound.wav وجود داشته باشد. دو اثر ایجاد می‌کند، آن فایل را به‌عنوان صدا برای اولین اثر توکار می‌کند و اثر دوم را تنظیم می‌کند تا صدا را متوقف کند. از اشیای بازگشتی توسط ISequence.addEffect استفاده می‌کند، بنابراین نیازی به ایندکس توالی نیست.

import com.aspose.slides.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class AddAnimationSound {
    public static void main(String[] args) throws IOException {
        Presentation presentation = new Presentation();
        try {
            ISlide slide = presentation.getSlides().get_Item(0);
            IAutoShape firstShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 80, 100, 240, 80);
            IAutoShape secondShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 400, 100, 240, 80);
            firstShape.addTextFrame("Starts sound");
            secondShape.addTextFrame("Stops sound");

            ISequence sequence = slide.getTimeline().getMainSequence();
            IEffect firstEffect = sequence.addEffect(firstShape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
            IEffect secondEffect = sequence.addEffect(secondShape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);

            byte[] audioData = Files.readAllBytes(Paths.get("animation-sound.wav"));
            IAudio effectSound = presentation.getAudios().addAudio(audioData);
            firstEffect.setSound(effectSound);
            secondEffect.setStopPreviousSound(true);

            presentation.save("shape-animation-sound.pptx", SaveFormat.Pptx);
        } finally {
            presentation.dispose();
        }
    }
}

استخراج صداهای توکار اثر

مثال زیر انتظار دارد یک ارائه محلی به نام presentation-with-animation-sounds.pptx وجود داشته باشد. هر دو توالی اصلی و تعاملی را اسکن می‌کند و تمام صداهای توکار اثرها را در پوشه extracted-animation-sounds می‌نویسد. پسوند از نوع MIME صوتی که توسط IAudio.getContentType ارائه شده انتخاب می‌شود.

import com.aspose.slides.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Locale;

public class ExtractAnimationSounds {
    public static void main(String[] args) throws IOException {
        Path inputPath = Paths.get("presentation-with-animation-sounds.pptx");
        Path outputDirectory = Paths.get("extracted-animation-sounds");

        Files.createDirectories(outputDirectory);

        Presentation presentation = new Presentation(inputPath.toString());
        try {
            int soundIndex = 1;

            for (ISlide slide : presentation.getSlides()) {
                soundIndex = saveSounds(slide.getTimeline().getMainSequence(), outputDirectory, soundIndex);

                for (ISequence sequence : slide.getTimeline().getInteractiveSequences()) {
                    soundIndex = saveSounds(sequence, outputDirectory, soundIndex);
                }
            }

            System.out.println("Extracted " + (soundIndex - 1) + " sound file(s) to " + outputDirectory.toAbsolutePath() + ".");
        } finally {
            presentation.dispose();
        }
    }

    private static int saveSounds(ISequence sequence, Path outputDirectory, int soundIndex) throws IOException {
        for (IEffect effect : sequence) {
            if (effect.getSound() == null) {
                continue;
            }

            String extension = getAudioExtension(effect.getSound().getContentType());
            Path outputPath = outputDirectory.resolve("effect-sound-" + soundIndex + extension);
            Files.write(outputPath, effect.getSound().getBinaryData());
            soundIndex++;
        }

        return soundIndex;
    }

    private static String getAudioExtension(String contentType) {
        String normalizedType = contentType == null ? "" : contentType.toLowerCase(Locale.ROOT);

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

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

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

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

        return ".bin";
    }
}

برای اشیای صوتی بزرگ، از IAudio.getStream استفاده کنید و به‌جای بارگذاری کل شیء در یک آرایه بایت، جریان را به یک فایل کپی کنید.

تنظیم رفتار پس از انیمیشن

گزینه After animation تعیین می‌کند پس از پایان اثر، چه اتفاقی برای شکل می‌افتد.

پنجره تنظیمات گزینه‌های اثر PowerPoint که تنظیمات After animation را نشان می‌دهد

کلاس AfterAnimationType پشتیبانی می‌کند از عدم تغییر شکل، تغییر رنگ آن، مخفی کردن آن پس از انیمیشن، یا مخفی کردن آن در کلیک بعدی. هنگامی که نوع برابر با AfterAnimationType.Color باشد، همچنین IEffect.getAfterAnimationColor را تنظیم کنید.

این مثال مستقل یک اثر ایجاد می‌کند، رفتار پس از انیمیشن آن را از طریق شیء اثر بازگشتی تنظیم می‌کند و نتیجه را ذخیره می‌نماید.

import com.aspose.slides.*;
import android.graphics.Color;

public class SetAfterAnimationBehavior {
    public static void main(String[] args) {
        Presentation presentation = new Presentation();
        try {
            ISlide slide = presentation.getSlides().get_Item(0);
            IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 120, 100, 320, 80);
            shape.addTextFrame("Dim after animation");

            IEffect effect = slide.getTimeline().getMainSequence().addEffect(shape, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
            effect.setAfterAnimationType(AfterAnimationType.Color);
            effect.getAfterAnimationColor().setColor(Color.LTGRAY);

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

تغییر نوع از AfterAnimationType.Color تنظیم رنگ پس از انیمیشن را پاک می‌کند.

انیمیشن متن

انیمیشن متن دو کنترل مرتبط دارد:

  • ITextAnimation.getBuildType تعیین می‌کند که پاراگراف‌ها به‌صورت همزمان یا به‌سطح پاراگراف ظاهر شوند.
  • IEffect.getAnimateTextType تعیین می‌کند که متن به‌صورت یک‌باره، به‌واحد کلمه یا به‌واحد حرف ظاهر شود. IEffect.getDelayBetweenTextParts تاخیر بین کلمات یا حروف را تنظیم می‌کند. مقدار مثبت درصدی از مدت اثر است؛ مقدار منفی تاخیر برحسب ثانیه.

مثال مستقل زیر کلمات داخل یک جعبه متن را انیمیشن می‌کند. BuildType.AsOneObject ساختن به‌صورت پاراگراف به پاراگراف را غیرفعال می‌کند تا تنظیم کلمه برای تمام قاب متن اعمال شود.

import com.aspose.slides.*;

public class AnimateTextByWord {
    public static void main(String[] args) {
        Presentation presentation = new Presentation();
        try {
            ISlide slide = presentation.getSlides().get_Item(0);
            IAutoShape textBox = slide.getShapes().addAutoShape(ShapeType.Rectangle, 80, 80, 560, 100);
            textBox.addTextFrame("Aspose.Slides animates this sentence word by word.");

            IEffect effect = slide.getTimeline().getMainSequence().addEffect(textBox, EffectType.Fade, EffectSubtype.None, EffectTriggerType.OnClick);
            effect.getTextAnimation().setBuildType(BuildType.AsOneObject);
            effect.setAnimateTextType(AnimateTextType.ByWord);
            effect.setDelayBetweenTextParts(20.0f);

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

برای ساختن یک جعبه متن به‌صورت پاراگراف، BuildType.ByLevelParagraphs1 (یا سطح پاراگراف دیگری) را تنظیم کنید. برای هدف‌گیری یک پاراگراف واحد با اثر خاص خود، از overload متد ISequence.addEffect که یک IParagraph می‌پذیرد استفاده کنید. برای مثال‌های سطح پاراگراف به Animated Text مراجعه کنید.

نکات خروجی و سازگاری

  • ذخیره به‌صورت PPT یا PPTX مدل انیمیشن را حفظ می‌کند، اما پخش نهایی توسط نرم‌افزار نمایش‌دهنده ارائه کنترل می‌شود.
  • PDF و تصاویر ثابت انیمیشن‌ها را پخش نمی‌کنند. هنگامی که خروجی باید حرکت را نشان دهد، از HTML5 export، GIF متحرک یا video conversion استفاده کنید.
  • برای HTML5، Html5Options.setAnimateShapes را فعال کنید و در صورت نیاز Html5Options.setAnimateTransitions را نیز فعال کنید.
  • رندر ویدئو از بسیاری از اثرهای ورودی، تأکیدی، خروجی و مسیر حرکت معمول پشتیبانی می‌کند، اما همه اثرهای PowerPoint پشتیبانی نمی‌شوند. supported animations and effects فعلی را بررسی کنید و ارائه‌های حیاتی را با نسخه هدف Aspose.Slides خود تست کنید.
  • اثرهای سفارشی پیشرفته و اثرهایی که از قالب‌های ارائه دیگر وارد شده‌اند ممکن است در فایل حفظ شوند اما در PowerPoint، HTML5 یا ویدئو به‌صورت متفاوتی رندر شوند. به‌جای تکیه صرف بر نام اثر، نتیجه خروجی را اعتبارسنجی کنید.

FAQ

چرا یک انیمیشن در PowerPoint ظاهر می‌شود اما در PDF نیست؟

PDF یک فرمت ثابت است، بنابراین انیمیشن‌ها و انتقال‌های اسلاید اجرا نمی‌شوند. هنگامی که نیاز به حفظ حرکت دارید، به HTML5، GIF متحرک یا ویدئو صادر کنید.

چرا یک اثر در ویدئو به‌طوری متفاوت اجرا می‌شود؟

صادرکردن به‌صورت ویدئو، انیمیشن‌ها را رندر می‌کند نه اینکه رفتار اصلی PowerPoint را ذخیره کند. برخی اثرهای پیشرفته پشتیبانی نمی‌شوند یا به‌صورت تخمینی اعمال می‌شوند. جدول اثرهای پشتیبانی‌شده را بررسی کنید و ارائه واقعی را پیش از استفاده در تولید تست نمایید.

آیا جابجایی یک شکل به جلو یا عقب ترتیب انیمیشن آن را تغییر می‌دهد؟

خیر. ترتیب z-order شکل فقط نحوه هم‌پوشانی را کنترل می‌کند، در حالی که ترتیب توالی و محرک‌ها پخش انیمیشن را تعیین می‌کنند. اگر نیاز به ترتیب پخش متفاوت دارید، جدول زمانی را تغییر دهید.