Zastosowanie animacji kształtów w prezentacjach przy użyciu JavaScript
Przegląd
Aby pracować z poszczególnymi zachowaniami wewnątrz efektu lub edytować segmenty ścieżki ruchu, zobacz Niestandardowa animacja.
Aspose.Slides for Node.js via Java przedstawia animacje slajdów jako efekty w osi czasu slajdu. Efekt ma docelowy kształt, typ i podtyp animacji, wyzwalacz, ustawienia czasowe oraz opcjonalne właściwości, takie jak dźwięk lub zachowanie po zakończeniu animacji.
Oś czasu zawiera dwa rodzaje sekwencji:
- główna sekwencja odtwarzana jest w miarę postępu slajdu.
- interaktywna sekwencja rozpoczyna się po kliknięciu w jej kształt wyzwalający.
Ponieważ pola tekstowe, obrazy, wykresy, tabele i inne obiekty slajdu są obiektami Shape, używasz tej samej metody Sequence.addEffect dla większości treści slajdu. Dostępne efekty są wymienione w wyliczeniu EffectType.
Dodawanie animacji kształtów
Aby dodać animację, pobierz główną sekwencję slajdu i wywołaj Sequence.addEffect z docelowym kształtem, typem efektu, podtypem i wyzwalaczem. Dla efektu, który zaczyna się po kliknięciu innego kształtu, utwórz interaktywną sekwencję, której wyzwalaczem jest ten inny kształt.
Poniższy przykład tworzy oba typy animacji i zapisuje wynik do shape-animations.pptx.
const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const presentation = new aspose.slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const targetShape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.RoundCornerRectangle, 120, 100, 320, 80);
targetShape.addTextFrame("Click to animate this shape");
const mainSequence = slide.getTimeline().getMainSequence();
const entranceEffect = mainSequence.addEffect(targetShape, aspose.slides.EffectType.Fade, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
entranceEffect.getTiming().setDuration(java.newFloat(1.5));
const triggerShape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Bevel, 20, 20, 100, 40);
triggerShape.addTextFrame("Move");
const interactiveSequence = slide.getTimeline().getInteractiveSequences().add(triggerShape);
interactiveSequence.addEffect(targetShape, aspose.slides.EffectType.PathFootball, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
presentation.save("shape-animations.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Wyzwalacz określa, kiedy efekt się rozpoczyna:
- EffectTriggerType.OnClick czeka na kliknięcie w głównej sekwencji lub na kliknięcie w kształt wyzwalający w interaktywnej sekwencji.
- EffectTriggerType.WithPrevious rozpoczyna się razem z poprzedzającym efektem.
- EffectTriggerType.AfterPrevious rozpoczyna się po zakończeniu poprzedzającego efektu.
Aby animować obraz, wykres lub inny typ kształtu, przekaż ten obiekt do Sequence.addEffect zamiast targetShape. Opcje grupowania specyficzne dla wykresów znajdziesz w sekcji Animated Charts.
Odczytywanie animacji kształtów
Użyj Sequence.getEffectsByShape, gdy znasz docelowy kształt. Aby przejrzeć każdy efekt, wyliczaj główną sekwencję oraz wszystkie interaktywne sekwencje. Wyliczanie zapobiega przyjmowaniu, że w sekwencji znajduje się efekt pod indeksem 0.
Poniższy przykład tworzy kształt z efektami w głównej i interaktywnej sekwencji, pobiera efekty skierowane do tego kształtu, a następnie wylicza wszystkie sekwencje na slajdzie.
const aspose = { slides: require("aspose.slides.via.java") };
function getEnumName(enumType, value) {
for (const [name, enumValue] of Object.entries(enumType)) {
if (enumValue === value) {
return name;
}
}
return String(value);
}
function printSequence(label, sequence) {
console.log(` ${label}: ${sequence.getCount()} effect(s)`);
for (let i = 0; i < sequence.getCount(); i++) {
const effect = sequence.get_Item(i);
const targetName = effect.getTargetShape() == null ? "unknown" : effect.getTargetShape().getName();
const typeName = getEnumName(aspose.slides.EffectType, effect.getType());
const subtypeName = getEnumName(aspose.slides.EffectSubtype, effect.getSubtype());
const triggerName = getEnumName(aspose.slides.EffectTriggerType, effect.getTiming().getTriggerType());
console.log(` ${typeName} ${subtypeName}; target: ${targetName}; trigger: ${triggerName}`);
}
}
const presentation = new aspose.slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const targetShape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 120, 100, 320, 80);
targetShape.addTextFrame("Animated shape");
const mainSequence = slide.getTimeline().getMainSequence();
mainSequence.addEffect(targetShape, aspose.slides.EffectType.Fade, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
const triggerShape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Bevel, 20, 20, 100, 40);
triggerShape.addTextFrame("Move");
const interactiveSequence = slide.getTimeline().getInteractiveSequences().add(triggerShape);
interactiveSequence.addEffect(targetShape, aspose.slides.EffectType.PathFootball, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
const targetEffects = mainSequence.getEffectsByShape(targetShape);
console.log(`The main sequence contains ${targetEffects.length} effect(s) for ${targetShape.getName()}.`);
printSequence("Main sequence", mainSequence);
const interactiveSequences = slide.getTimeline().getInteractiveSequences();
for (let i = 0; i < interactiveSequences.getCount(); i++) {
const sequence = interactiveSequences.get_Item(i);
const triggerName = sequence.getTriggerShape() == null ? "unknown" : sequence.getTriggerShape().getName();
printSequence(`Interactive sequence ${i + 1}, trigger: ${triggerName}`, sequence);
}
} finally {
presentation.dispose();
}
Jeśli potrzebujesz efektów tylko dla jednego kształtu, najpierw zidentyfikuj kształt po nazwie, typie placeholdera lub innej stabilnej właściwości; następnie wywołaj Sequence.getEffectsByShape. Nie zakładaj, że ShapeCollection.get_Item pod indeksem 0 zawsze jest pożądanym obiektem.
Praca z dziedziczonymi efektami placeholderów
Placeholder na normalnym slajdzie może dziedziczyć zachowanie animacji z odpowiadającego mu placeholdera na slajdzie układu i slajdzie głównym. Shape.getBasePlaceholder zwraca tego rodzica lub null, gdy nie istnieje.
W poniższej prezentacji stopka ma Random Bars na normalnym slajdzie, Split na slajdzie układu i Fly In na slajdzie głównym.



Kolejny przykład używa hierarchii placeholderów z nowej prezentacji. Dodaje efekty do placeholdera głównego, placeholdera układu i odpowiadającego mu placeholdera na normalnym slajdzie. Każde wywołanie Shape.getBasePlaceholder jest sprawdzane przed użyciem zwróconego kształtu.
const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
function findPlaceholderWithBase(baseSlide, expectedBase) {
const shapes = baseSlide.getShapes();
for (let i = 0; i < shapes.size(); i++) {
const shape = shapes.get_Item(i);
const basePlaceholder = shape.getBasePlaceholder();
if (basePlaceholder == null) {
continue;
}
if (expectedBase == null || basePlaceholder.getPlaceholder().getType() === expectedBase.getPlaceholder().getType()) {
return shape;
}
}
return null;
}
function getEnumName(enumType, value) {
for (const [name, enumValue] of Object.entries(enumType)) {
if (enumValue === value) {
return name;
}
}
return String(value);
}
function printEffects(source, effects) {
console.log(`${source}: ${effects.length} effect(s)`);
for (const effect of effects) {
const typeName = getEnumName(aspose.slides.EffectType, effect.getType());
const subtypeName = getEnumName(aspose.slides.EffectSubtype, effect.getSubtype());
console.log(` ${typeName} ${subtypeName}`);
}
}
const presentation = new aspose.slides.Presentation();
try {
const layoutSlide = presentation.getLayoutSlides().getByType(java.newByte(aspose.slides.SlideLayoutType.TitleAndObject));
const layoutPlaceholder = findPlaceholderWithBase(layoutSlide, null);
if (layoutPlaceholder == null) {
throw new Error("The layout slide does not contain a placeholder linked to its master slide.");
}
const masterPlaceholder = layoutPlaceholder.getBasePlaceholder();
layoutSlide.getMasterSlide().getTimeline().getMainSequence().addEffect(masterPlaceholder, aspose.slides.EffectType.Fly, aspose.slides.EffectSubtype.Bottom, aspose.slides.EffectTriggerType.OnClick);
layoutSlide.getTimeline().getMainSequence().addEffect(layoutPlaceholder, aspose.slides.EffectType.Split, aspose.slides.EffectSubtype.VerticalIn, aspose.slides.EffectTriggerType.OnClick);
const slide = presentation.getSlides().addEmptySlide(layoutSlide);
const slidePlaceholder = findPlaceholderWithBase(slide, layoutPlaceholder);
if (slidePlaceholder == null) {
throw new Error("The slide does not contain a placeholder linked to its layout slide.");
}
slide.getTimeline().getMainSequence().addEffect(slidePlaceholder, aspose.slides.EffectType.RandomBars, aspose.slides.EffectSubtype.Horizontal, aspose.slides.EffectTriggerType.OnClick);
printEffects("Normal slide", slide.getTimeline().getMainSequence().getEffectsByShape(slidePlaceholder));
const baseLayoutPlaceholder = slidePlaceholder.getBasePlaceholder();
if (baseLayoutPlaceholder != null) {
printEffects("Layout slide", layoutSlide.getTimeline().getMainSequence().getEffectsByShape(baseLayoutPlaceholder));
const baseMasterPlaceholder = baseLayoutPlaceholder.getBasePlaceholder();
if (baseMasterPlaceholder != null) {
printEffects("Master slide", layoutSlide.getMasterSlide().getTimeline().getMainSequence().getEffectsByShape(baseMasterPlaceholder));
}
}
presentation.save("placeholder-animations.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Zmiana czasu animacji
Dialog PowerPoint Timing mapuje się na właściwości Timing.

- Start mapuje się na Timing.getTriggerType.
- Duration mapuje się na Timing.getDuration, w sekundach.
- Delay mapuje się na Timing.getTriggerDelayTime, w sekundach.
- Repeat mapuje się na Timing.getRepeatCount, Timing.getRepeatUntilNextClick lub Timing.getRepeatUntilEndSlide.
- Rewind when done playing mapuje się na Timing.getRewind.
Ten niezależny przykład dodaje efekt, zmienia jego czas przy użyciu obiektu zwróconego przez Sequence.addEffect i zapisuje wynik. Przechowywanie zwróconego odwołania do Effect zapobiega niepotrzebnemu indeksowaniu kolekcji.
const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const presentation = new aspose.slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 120, 100, 320, 80);
shape.addTextFrame("Timed animation");
const effect = slide.getTimeline().getMainSequence().addEffect(shape, aspose.slides.EffectType.Fade, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
effect.getTiming().setTriggerType(aspose.slides.EffectTriggerType.OnClick);
effect.getTiming().setDuration(java.newFloat(2.0));
effect.getTiming().setTriggerDelayTime(java.newFloat(0.5));
effect.getTiming().setRepeatUntilNextClick(false);
effect.getTiming().setRepeatUntilEndSlide(false);
effect.getTiming().setRepeatCount(java.newFloat(2.0));
effect.getTiming().setRewind(true);
presentation.save("shape-animation-timing.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Używaj jednego trybu powtarzania celowo. Łączenie liczby powtórzeń z flagą „until” może prowadzić do mylących rezultatów w różnych odtwarzaczach. Przy zmianie trybu powtarzania najpierw ustaw Timing.setRepeatUntilNextClick i Timing.setRepeatUntilEndSlide, a dopiero potem Timing.setRepeatCount, ponieważ ustawienie którejkolwiek flagi zmienia również aktywny tryb powtarzania.
Dodawanie i wyodrębnianie dźwięków animacji
Efekt animacji może odwoływać się do wbudowanego audio za pomocą Effect.getSound. Effect.setStopPreviousSound instruuje efekt, aby zatrzymał dźwięk rozpoczęty przez wcześniejszy efekt.
Dodanie dźwięku do efektu
Poniższy przykład zakłada istnienie lokalnego pliku audio o nazwie animation-sound.wav. Tworzy dwa efekty, osadza ten plik jako dźwięk pierwszego efektu i konfiguruje drugi efekt, aby zatrzymał dźwięk. Używa obiektów zwróconych przez Sequence.addEffect, więc nie wymaga indeksu sekwencji.
const fs = require("fs");
const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const presentation = new aspose.slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const firstShape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 80, 100, 240, 80);
const secondShape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 400, 100, 240, 80);
firstShape.addTextFrame("Starts sound");
secondShape.addTextFrame("Stops sound");
const sequence = slide.getTimeline().getMainSequence();
const firstEffect = sequence.addEffect(firstShape, aspose.slides.EffectType.Fade, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
const secondEffect = sequence.addEffect(secondShape, aspose.slides.EffectType.Fade, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
const audioData = java.newArray("byte", Array.from(fs.readFileSync("animation-sound.wav")));
const effectSound = presentation.getAudios().addAudio(audioData);
firstEffect.setSound(effectSound);
secondEffect.setStopPreviousSound(true);
presentation.save("shape-animation-sound.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Wyodrębnianie osadzonych dźwięków efektów
Poniższy przykład zakłada istnienie lokalnej prezentacji o nazwie presentation-with-animation-sounds.pptx. Przeszukuje zarówno główne, jak i interaktywne sekwencje i zapisuje każdy osadzony dźwięk efektu do katalogu extracted-animation-sounds. Rozszerzenie jest wybierane na podstawie typu MIME audio zwracanego przez Audio.getContentType.
const fs = require("fs");
const path = require("path");
const aspose = { slides: require("aspose.slides.via.java") };
function getAudioExtension(contentType) {
const normalizedType = contentType == null ? "" : contentType.toLowerCase();
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) {
for (let i = 0; i < sequence.getCount(); i++) {
const effect = sequence.get_Item(i);
if (effect.getSound() == null) {
continue;
}
const extension = getAudioExtension(effect.getSound().getContentType());
const outputPath = path.join(outputDirectory, `effect-sound-${soundIndex}${extension}`);
fs.writeFileSync(outputPath, Buffer.from(effect.getSound().getBinaryData()));
soundIndex++;
}
return soundIndex;
}
const outputDirectory = "extracted-animation-sounds";
fs.mkdirSync(outputDirectory, { recursive: true });
const presentation = new aspose.slides.Presentation("presentation-with-animation-sounds.pptx");
try {
let soundIndex = 1;
for (let slideIndex = 0; slideIndex < presentation.getSlides().size(); slideIndex++) {
const slide = presentation.getSlides().get_Item(slideIndex);
soundIndex = saveSounds(slide.getTimeline().getMainSequence(), outputDirectory, soundIndex);
const interactiveSequences = slide.getTimeline().getInteractiveSequences();
for (let sequenceIndex = 0; sequenceIndex < interactiveSequences.getCount(); sequenceIndex++) {
soundIndex = saveSounds(interactiveSequences.get_Item(sequenceIndex), outputDirectory, soundIndex);
}
}
console.log(`Extracted ${soundIndex - 1} sound file(s) to ${path.resolve(outputDirectory)}.`);
} finally {
presentation.dispose();
}
Dla dużych obiektów audio użyj Audio.getStream i skopiuj strumień do pliku zamiast ładować cały obiekt do tablicy bajtów.
Ustawienie zachowania po animacji
Opcja After animation kontroluje, co się dzieje z kształtem po zakończeniu jego efektu.

Wyliczenie AfterAnimationType umożliwia pozostawienie kształtu niezmienionego, zmianę jego koloru, ukrycie go po animacji lub ukrycie przy następnym kliknięciu. Gdy typ to AfterAnimationType.Color, ustaw również Effect.getAfterAnimationColor.
Ten niezależny przykład tworzy efekt, ustawia jego zachowanie po animacji za pomocą zwróconego obiektu efektu i zapisuje wynik.
const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const presentation = new aspose.slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 120, 100, 320, 80);
shape.addTextFrame("Dim after animation");
const effect = slide.getTimeline().getMainSequence().addEffect(shape, aspose.slides.EffectType.Fade, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
effect.setAfterAnimationType(aspose.slides.AfterAnimationType.Color);
effect.getAfterAnimationColor().setColor(java.getStaticFieldValue("java.awt.Color", "LIGHT_GRAY"));
presentation.save("shape-animation-after-effect.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Zmiana typu z AfterAnimationType.Color usuwa ustawienie koloru po animacji.
Animowanie tekstu
Animacja tekstu ma dwa powiązane sterowania:
- TextAnimation.getBuildType kontroluje, czy akapity pojawiają się razem, czy poziomem akapitu.
- Effect.getAnimateTextType kontroluje, czy tekst pojawia się jednorazowo, słowem lub literą. Effect.getDelayBetweenTextParts ustawia opóźnienie między słowami lub literami. Wartość dodatnia oznacza procent czasu trwania efektu; wartość ujemna oznacza opóźnienie w sekundach.
Poniższy niezależny przykład animuje słowa w polu tekstowym. BuildType.AsOneObject wyłącza budowanie akapit po akapicie, więc ustawienie słowa dotyczy całej ramki tekstowej.
const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const presentation = new aspose.slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const textBox = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 80, 80, 560, 100);
textBox.addTextFrame("Aspose.Slides animates this sentence word by word.");
const effect = slide.getTimeline().getMainSequence().addEffect(textBox, aspose.slides.EffectType.Fade, aspose.slides.EffectSubtype.None, aspose.slides.EffectTriggerType.OnClick);
effect.getTextAnimation().setBuildType(aspose.slides.BuildType.AsOneObject);
effect.setAnimateTextType(aspose.slides.AnimateTextType.ByWord);
effect.setDelayBetweenTextParts(java.newFloat(20.0));
presentation.save("animated-text.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Aby budować pole tekstowe akapit po akapicie, ustaw BuildType.ByLevelParagraphs1 (lub inny poziom akapitu). Aby skierować pojedynczy akapit do własnego efektu, użyj przeciążenia Sequence.addEffect, które przyjmuje obiekt Paragraph. Zobacz Animated Text po przykłady na poziomie akapitu.
Eksport i uwagi dotyczące kompatybilności
- Zapis do PPT lub PPTX zachowuje model animacji, ale ostateczne odtwarzanie kontroluje przeglądarka prezentacji.
- PDF i obrazy statyczne nie odtwarzają animacji. Użyj HTML5 export, animowanego GIF lub konwersji wideo, gdy wyjście musi pokazywać ruch.
- Dla HTML5 włącz Html5Options.setAnimateShapes oraz, w razie potrzeby, Html5Options.setAnimateTransitions.
- Renderowanie wideo obsługuje wiele typowych efektów wejścia, podkreślenia, wyjścia i ścieżek ruchu, ale nie każdy efekt PowerPoint jest obsługiwany. Sprawdź aktualną listę obsługiwanych animacji i efektów i przetestuj krytyczne prezentacje z wersją Aspose.Slides, której używasz.
- Zaawansowane niestandardowe efekty i efekty importowane z innych formatów prezentacji mogą być zachowane w pliku, ale renderowane inaczej w PowerPoint, HTML5 lub wideo. Zweryfikuj wyeksportowany rezultat zamiast polegać wyłącznie na nazwie efektu.
FAQ
Dlaczego animacja pojawia się w PowerPoint, a nie w PDF?
PDF jest formatem statycznym, więc animacje i przejścia slajdów nie są odtwarzane. Eksportuj do HTML5, animowanego GIF lub wideo, gdy ruch musi zostać zachowany.
Dlaczego efekt odtwarza się inaczej w wideo?
Eksport wideo renderuje animacje zamiast przechowywać oryginalne zachowanie PowerPoint. Niektóre zaawansowane efekty nie są obsługiwane lub są przybliżane. Przejrzyj tabelę obsługiwanych efektów i przetestuj rzeczywistą prezentację przed użyciem w produkcji.
Czy przeniesienie kształtu do przodu lub do tyłu zmienia kolejność jego animacji?
Nie. Kolejność warstw (z‑order) kontroluje nakładanie się kształtów, natomiast kolejność sekwencji i wyzwalacze sterują odtwarzaniem animacji. Zmodyfikuj oś czasu, jeśli potrzebna jest inna kolejność odtwarzania.