Áp dụng hoạt ảnh hình dạng trong các bản trình chiếu bằng Java
Tổng quan
Để làm việc với các hành vi riêng lẻ bên trong một hiệu ứng hoặc chỉnh sửa các đoạn đường chuyển động, xem Tùy chỉnh hoạt ảnh.
Aspose.Slides for Java biểu diễn hoạt ảnh slide dưới dạng các hiệu ứng trong một dòng thời gian slide. Một hiệu ứng có hình dạng mục tiêu, kiểu và phụ hiệu ứng, trình kích hoạt, cài đặt thời gian, và các thuộc tính tùy chọn như âm thanh hoặc hành vi sau hoạt ảnh.
Dòng thời gian chứa hai loại chuỗi:
- Chuỗi chính phát khi slide tiến lên.
- Chuỗi tương tác bắt đầu khi hình dạng kích hoạt của nó được nhấn.
Vì các hộp văn bản, hình ảnh, biểu đồ, bảng và các đối tượng slide khác thực hiện IShape, bạn sử dụng cùng một phương thức ISequence.addEffect cho hầu hết nội dung slide. Các hiệu ứng khả dụng được liệt kê trong lớp EffectType.
Thêm hoạt ảnh cho hình dạng
Để thêm một hoạt ảnh, lấy chuỗi chính của slide và gọi ISequence.addEffect với hình dạng mục tiêu, kiểu hiệu ứng, phụ hiệu ứng và trình kích hoạt. Đối với hiệu ứng bắt đầu khi một hình dạng khác được nhấn, tạo một chuỗi tương tác mà trình kích hoạt là hình dạng khác đó.
Ví dụ sau tạo cả hai loại hoạt ảnh và lưu kết quả vào 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();
}
}
}
Trình kích hoạt điều khiển thời điểm một hiệu ứng bắt đầu:
- EffectTriggerType.OnClick chờ một cú nhấp trong chuỗi chính, hoặc chờ một cú nhấp vào hình dạng kích hoạt trong chuỗi tương tác.
- EffectTriggerType.WithPrevious bắt đầu cùng với hiệu ứng trước đó.
- EffectTriggerType.AfterPrevious bắt đầu khi hiệu ứng trước kết thúc.
Để tạo hoạt ảnh cho hình ảnh, biểu đồ hoặc loại hình dạng khác, truyền đối tượng đó vào ISequence.addEffect thay vì targetShape. Đối với các tùy chọn nhóm riêng cho biểu đồ, xem Biểu đồ động.
Đọc hoạt ảnh hình dạng
Sử dụng ISequence.getEffectsByShape khi bạn biết hình dạng mục tiêu. Để kiểm tra mọi hiệu ứng, duyệt chuỗi chính và mọi chuỗi tương tác. Việc duyệt tránh giả định rằng một chuỗi chứa hiệu ứng tại chỉ mục 0.
Ví dụ sau tạo một hình dạng có hiệu ứng chuỗi chính và chuỗi tương tác, lấy các hiệu ứng nhắm vào hình dạng đó, rồi duyệt mọi chuỗi trên slide.
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);
}
}
}
Nếu bạn chỉ cần các hiệu ứng cho một hình dạng, trước hết xác định hình dạng bằng tên, kiểu trình giữ chỗ, hoặc thuộc tính ổn định khác; sau đó gọi ISequence.getEffectsByShape. Không giả định rằng IShapeCollection.get_Item tại chỉ mục 0 luôn là đối tượng mong muốn.
Làm việc với hiệu ứng trình giữ chỗ kế thừa
Một trình giữ chỗ trên slide bình thường có thể kế thừa hành vi hoạt ảnh từ trình giữ chỗ tương ứng trên slide bố cục và slide mẹ. IShape.getBasePlaceholder trả về trình giữ chỗ cha đó, hoặc null khi không có cha.
Trong bản trình bày mẫu dưới đây, phần chân trang có Random Bars trên slide bình thường, Split trên slide bố cục, và Fly In trên slide mẹ.



Ví dụ tiếp theo sử dụng một cây trình giữ chỗ từ một bản trình bày mới. Nó thêm hiệu ứng vào một trình giữ chỗ mẹ, một trình giữ chỗ bố cục, và trình giữ chỗ tương ứng trên slide bình thường. Mọi lời gọi tới IShape.getBasePlaceholder đều được kiểm tra trước khi sử dụng hình dạng trả về.
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);
}
}
}
Thay đổi thời gian hoạt ảnh
Hộp thoại Timing của PowerPoint ánh xạ tới các thuộc tính của ITiming.

- Start ánh xạ tới ITiming.getTriggerType.
- Duration ánh xạ tới ITiming.getDuration, tính bằng giây.
- Delay ánh xạ tới ITiming.getTriggerDelayTime, tính bằng giây.
- Repeat ánh xạ tới ITiming.getRepeatCount, ITiming.getRepeatUntilNextClick, hoặc ITiming.getRepeatUntilEndSlide.
- Rewind when done playing ánh xạ tới ITiming.getRewind.
Ví dụ độc lập này thêm một hiệu ứng, thay đổi thời gian của nó thông qua đối tượng trả về bởi ISequence.addEffect, và lưu kết quả. Giữ tham chiếu tới IEffect trả về tránh một chỉ mục bộ sưu tập không cần thiết.
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();
}
}
}
Sử dụng một chế độ lặp duy nhất. Kết hợp số lần lặp với cờ “until” có thể gây ra kết quả khó hiểu trên các trình xem khác nhau. Khi thay đổi chế độ lặp, đặt ITiming.setRepeatUntilNextClick và ITiming.setRepeatUntilEndSlide trước khi gọi ITiming.setRepeatCount, vì việc đặt bất kỳ cờ nào cũng sẽ thay đổi chế độ lặp đang hoạt động.
Thêm và trích xuất âm thanh hoạt ảnh
Một hiệu ứng hoạt ảnh có thể tham chiếu âm thanh nhúng thông qua IEffect.getSound. IEffect.setStopPreviousSound yêu cầu hiệu ứng dừng âm thanh đã được khởi động bởi một hiệu ứng trước đó.
Thêm âm thanh vào hiệu ứng
Ví dụ sau yêu cầu một file âm thanh cục bộ có tên animation-sound.wav. Nó tạo hai hiệu ứng, nhúng file đó làm âm thanh cho hiệu ứng đầu tiên, và cấu hình hiệu ứng thứ hai để dừng âm thanh. Nó sử dụng các đối tượng trả về bởi ISequence.addEffect, vì vậy không cần chỉ mục chuỗi.
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();
}
}
}
Trích xuất âm thanh hiệu ứng đã nhúng
Ví dụ sau yêu cầu một bản trình bày cục bộ có tên presentation-with-animation-sounds.pptx. Nó quét cả chuỗi chính và chuỗi tương tác và ghi mỗi âm thanh hiệu ứng đã nhúng vào thư mục extracted-animation-sounds. Phần mở rộng được chọn dựa trên loại MIME âm thanh được cung cấp bởi 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";
}
}
Đối với các đối tượng âm thanh lớn, sử dụng IAudio.getStream và sao chép luồng vào file thay vì tải toàn bộ đối tượng vào mảng byte.
Đặt hành vi sau hoạt ảnh
Tùy chọn After animation điều khiển gì xảy ra với một hình dạng sau khi hiệu ứng của nó kết thúc.

Lớp AfterAnimationType hỗ trợ để lại hình dạng không thay đổi, đổi màu, ẩn nó sau hoạt ảnh, hoặc ẩn nó khi cú nhấp tiếp theo. Khi kiểu là AfterAnimationType.Color, cũng đặt IEffect.getAfterAnimationColor.
Ví dụ độc lập này tạo một hiệu ứng, đặt hành vi sau hoạt ảnh thông qua đối tượng hiệu ứng trả về, và lưu kết quả.
import com.aspose.slides.*;
import java.awt.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.LIGHT_GRAY);
presentation.save("shape-animation-after-effect.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
}
}
Thay đổi kiểu khỏi AfterAnimationType.Color sẽ xóa cài đặt màu sau hoạt ảnh.
Hoạt ảnh văn bản
Hoạt ảnh văn bản có hai điều khiển liên quan:
- ITextAnimation.getBuildType kiểm soát việc các đoạn văn xuất hiện cùng nhau hay theo mức đoạn văn.
- IEffect.getAnimateTextType kiểm soát việc văn bản xuất hiện một lúc, theo từ hoặc theo ký tự. IEffect.getDelayBetweenTextParts đặt độ trễ giữa các từ hoặc ký tự. Giá trị dương là phần trăm của thời lượng hiệu ứng; giá trị âm là độ trễ tính bằng giây.
Ví dụ độc lập sau hoạt ảnh các từ trong một hộp văn bản. BuildType.AsOneObject tắt việc xây dựng đoạn văn theo đoạn, vì vậy cài đặt từ áp dụng cho toàn bộ khung văn bản.
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();
}
}
}
Để xây dựng một hộp văn bản theo đoạn, đặt BuildType.ByLevelParagraphs1 (hoặc mức đoạn khác). Để nhắm tới một đoạn riêng với hiệu ứng riêng, sử dụng phương thức overload ISequence.addEffect chấp nhận một IParagraph. Xem Văn bản động để biết các ví dụ mức đoạn.
Ghi chú xuất và tính tương thích
- Lưu dưới dạng PPT hoặc PPTX giữ nguyên mô hình hoạt ảnh, nhưng việc phát cuối cùng do trình xem bản trình bày điều khiển.
- PDF và hình ảnh tĩnh không phát hoạt ảnh. Sử dụng HTML5 export, GIF hoạt ảnh, hoặc chuyển đổi video khi đầu ra phải hiển thị chuyển động.
- Đối với HTML5, bật Html5Options.setAnimateShapes và, khi cần, Html5Options.setAnimateTransitions.
- Kết xuất video hỗ trợ nhiều hiệu ứng vào, nhấn mạnh, thoát và đường chuyển động phổ biến, nhưng không phải mọi hiệu ứng PowerPoint đều được hỗ trợ. Kiểm tra bảng các hoạt ảnh và hiệu ứng được hỗ trợ hiện tại và thử nghiệm các bản trình bày quan trọng với phiên bản Aspose.Slides mục tiêu của bạn.
- Các hiệu ứng tùy chỉnh nâng cao và các hiệu ứng được nhập từ các định dạng bản trình bày khác có thể được giữ trong file nhưng hiển thị khác nhau trong PowerPoint, HTML5 hoặc video. Xác thực kết quả xuất thay vì chỉ dựa vào tên hiệu ứng.
Câu hỏi thường gặp
Tại sao một hoạt ảnh xuất hiện trong PowerPoint mà không xuất hiện trong PDF?
PDF là định dạng tĩnh, vì vậy hoạt ảnh và chuyển đổi slide không được phát. Xuất sang HTML5, GIF động, hoặc video khi cần bảo lưu chuyển động.
Tại sao một hiệu ứng hoạt động khác nhau trong video?
Xuất video render hoạt ảnh thay vì lưu nguyên hành vi PowerPoint. Một số hiệu ứng nâng cao không được hỗ trợ hoặc chỉ được xấp xỉ. Kiểm tra bảng hiệu ứng được hỗ trợ và thử nghiệm bản trình bày thực tế trước khi sử dụng trong sản xuất.
Việc di chuyển một hình dạng lên trước hoặc xuống sau có thay đổi thứ tự hoạt ảnh không?
Không. Thứ tự z-order của hình dạng chỉ điều khiển chồng lấn, trong khi thứ tự chuỗi và trình kích hoạt quyết định thứ tự phát hoạt ảnh. Thay đổi dòng thời gian nếu bạn cần một thứ tự phát khác.