Applicare animazioni di forme nelle presentazioni con Python

Panoramica

Per lavorare con i comportamenti individuali all’interno di un effetto o modificare i segmenti del percorso di animazione, vedere Animazione personalizzata.

Aspose.Slides for Python via .NET rappresenta le animazioni delle diapositive come effetti nella timeline di una diapositiva. Un effetto ha una forma di destinazione, un tipo e sottotipo di animazione, un trigger, impostazioni di temporizzazione e proprietà opzionali come suono o comportamento dopo l’animazione.

La timeline contiene due tipi di sequenze:

  • La sequenza principale viene riprodotta mentre la diapositiva avanza.
  • Una sequenza interattiva inizia quando la forma trigger viene cliccata.

Poiché caselle di testo, immagini, grafici, tabelle e altri oggetti della diapositiva implementano IShape, si utilizza lo stesso metodo Sequence.add_effect per la maggior parte del contenuto della diapositiva. Gli effetti disponibili sono elencati nella enumerazione EffectType.

Aggiungere animazioni alle forme

Per aggiungere un’animazione, ottieni la sequenza principale della diapositiva e chiama Sequence.add_effect con la forma di destinazione, il tipo di effetto, il sottotipo e il trigger. Per un effetto che inizia quando un’altra forma viene cliccata, crea una sequenza interattiva il cui trigger è quella altra forma.

L’esempio seguente crea entrambi i tipi di animazione e salva il risultato in shape-animations.pptx.

import aspose.slides as slides


with slides.Presentation() as presentation:
    slide = presentation.slides[0]

    target_shape = slide.shapes.add_auto_shape(slides.ShapeType.ROUND_CORNER_RECTANGLE, 120, 100, 320, 80)
    target_shape.text_frame.text = "Click to animate this shape"

    main_sequence = slide.timeline.main_sequence
    entrance_effect = main_sequence.add_effect(target_shape, slides.animation.EffectType.FADE, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)
    entrance_effect.timing.duration = 1.5

    trigger_shape = slide.shapes.add_auto_shape(slides.ShapeType.BEVEL, 20, 20, 100, 40)
    trigger_shape.text_frame.text = "Move"

    interactive_sequence = slide.timeline.interactive_sequences.add(trigger_shape)
    interactive_sequence.add_effect(target_shape, slides.animation.EffectType.PATH_FOOTBALL, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)

    presentation.save("shape-animations.pptx", slides.export.SaveFormat.PPTX)

Il trigger controlla quando inizia un effetto:

Per animare un’immagine, un grafico o un altro tipo di forma, passa quell’oggetto a Sequence.add_effect anziché a target_shape. Per le opzioni di raggruppamento specifiche dei grafici, vedere Grafici animati.

Leggere le animazioni delle forme

Usa Sequence.get_effects_by_shape quando conosci la forma di destinazione. Per ispezionare ogni effetto, itera attraverso la sequenza principale e ogni sequenza interattiva. L’iterazione evita di presumere che una sequenza contenga un effetto all’indice 0.

L’esempio seguente crea una forma con effetti nella sequenza principale e interattiva, ottiene gli effetti che hanno come destinazione la forma, e poi itera su ogni sequenza della diapositiva.

import aspose.slides as slides


def print_sequence(label, sequence):
    print(f"  {label}: {sequence.count} effect(s)")

    for effect in sequence:
        target_name = "unknown" if effect.target_shape is None else effect.target_shape.name
        effect_description = f"{effect.type.name} {effect.subtype.name}; target: {target_name}; trigger: {effect.timing.trigger_type.name}"
        print(f"    {effect_description}")


with slides.Presentation() as presentation:
    slide = presentation.slides[0]
    target_shape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 120, 100, 320, 80)
    target_shape.text_frame.text = "Animated shape"

    main_sequence = slide.timeline.main_sequence
    main_sequence.add_effect(target_shape, slides.animation.EffectType.FADE, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)

    trigger_shape = slide.shapes.add_auto_shape(slides.ShapeType.BEVEL, 20, 20, 100, 40)
    trigger_shape.text_frame.text = "Move"

    interactive_sequence = slide.timeline.interactive_sequences.add(trigger_shape)
    interactive_sequence.add_effect(target_shape, slides.animation.EffectType.PATH_FOOTBALL, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)

    target_effects = main_sequence.get_effects_by_shape(target_shape)
    print(f"The main sequence contains {len(target_effects)} effect(s) for {target_shape.name}.")

    print_sequence("Main sequence", main_sequence)

    for interactive_index, sequence in enumerate(slide.timeline.interactive_sequences, start=1):
        trigger_name = "unknown" if sequence.trigger_shape is None else sequence.trigger_shape.name
        sequence_label = f"Interactive sequence {interactive_index}, trigger: {trigger_name}"
        print_sequence(sequence_label, sequence)

Se ti servono solo gli effetti per una singola forma, individua prima la forma per nome, tipo di segnaposto o un’altra proprietà stabile; quindi chiama Sequence.get_effects_by_shape. Non presumere che la forma all’indice 0 sia sempre l’oggetto desiderato.

Lavorare con gli effetti dei segnaposto ereditati

Un segnaposto su una diapositiva normale può ereditare il comportamento di animazione dal corrispondente segnaposto sulla diapositiva layout e master. Shape.get_base_placeholder restituisce quel segnaposto padre, o None quando non esiste alcun padre.

Nella presentazione di esempio seguente, il piè di pagina ha Random Bars sulla diapositiva normale, Split sulla diapositiva layout e Fly In sulla diapositiva master.

Animazione del segnaposto piè di pagina sulla diapositiva normale

Animazione del segnaposto piè di pagina sulla diapositiva layout

Animazione del segnaposto piè di pagina sulla diapositiva master

L’esempio successivo costruisce autonomamente la gerarchia dei segnaposto. Aggiunge effetti a un segnaposto master, a un segnaposto layout e al corrispondente segnaposto su una diapositiva normale. Ogni chiamata a Shape.get_base_placeholder è verificata prima di utilizzare la forma restituita.

import aspose.slides as slides


def find_placeholder_with_base(slide):
    for shape in slide.shapes:
        if shape.get_base_placeholder() is not None:
            return shape

    return None


def print_effects(source, effects):
    print(f"{source}: {len(effects)} effect(s)")

    for effect in effects:
        print(f"  {effect.type.name} {effect.subtype.name}")


with slides.Presentation() as presentation:
    layout_slide = presentation.layout_slides.get_by_type(slides.SlideLayoutType.BLANK)
    layout_placeholder = layout_slide.placeholder_manager.add_text_placeholder(100, 100, 400, 80)
    layout_slide.timeline.main_sequence.add_effect(layout_placeholder, slides.animation.EffectType.SPLIT, slides.animation.EffectSubtype.VERTICAL_IN, slides.animation.EffectTriggerType.ON_CLICK)

    master_placeholder = layout_placeholder.get_base_placeholder()
    if master_placeholder is not None:
        master_sequence = layout_slide.master_slide.timeline.main_sequence
        master_sequence.add_effect(master_placeholder, slides.animation.EffectType.FLY, slides.animation.EffectSubtype.BOTTOM, slides.animation.EffectTriggerType.ON_CLICK)

    slide = presentation.slides.add_empty_slide(layout_slide)
    slide_placeholder = find_placeholder_with_base(slide)

    if slide_placeholder is None:
        raise RuntimeError("The slide does not contain a placeholder linked to its layout slide.")

    slide.timeline.main_sequence.add_effect(slide_placeholder, slides.animation.EffectType.RANDOM_BARS, slides.animation.EffectSubtype.HORIZONTAL, slides.animation.EffectTriggerType.ON_CLICK)
    print_effects("Normal slide", slide.timeline.main_sequence.get_effects_by_shape(slide_placeholder))

    base_layout_placeholder = slide_placeholder.get_base_placeholder()
    if base_layout_placeholder is not None:
        print_effects("Layout slide", layout_slide.timeline.main_sequence.get_effects_by_shape(base_layout_placeholder))

        base_master_placeholder = base_layout_placeholder.get_base_placeholder()
        if base_master_placeholder is not None:
            print_effects("Master slide", layout_slide.master_slide.timeline.main_sequence.get_effects_by_shape(base_master_placeholder))

    presentation.save("placeholder-animations.pptx", slides.export.SaveFormat.PPTX)

Modificare la temporizzazione dell’animazione

La finestra di dialogo Timing di PowerPoint corrisponde alle proprietà di Timing.

Finestra di dialogo Timing di PowerPoint per un effetto di animazione

Questo esempio autonomo aggiunge un effetto, ne modifica la temporizzazione tramite l’oggetto restituito da Sequence.add_effect, e salva il risultato. Conservare il riferimento all'Effect restituito evita un indice di raccolta non necessario.

import aspose.slides as slides


with slides.Presentation() as presentation:
    slide = presentation.slides[0]
    shape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 120, 100, 320, 80)
    shape.text_frame.text = "Timed animation"

    effect = slide.timeline.main_sequence.add_effect(shape, slides.animation.EffectType.FADE, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)
    effect.timing.trigger_type = slides.animation.EffectTriggerType.ON_CLICK
    effect.timing.duration = 2.0
    effect.timing.trigger_delay_time = 0.5
    effect.timing.repeat_until_next_click = False
    effect.timing.repeat_until_end_slide = False
    effect.timing.repeat_count = 2.0
    effect.timing.rewind = True

    presentation.save("shape-animation-timing.pptx", slides.export.SaveFormat.PPTX)

Utilizza un solo metodo di ripetizione intenzionalmente. Combinare un conteggio di ripetizioni con un flag “until” può produrre risultati confusi in diversi visualizzatori. Quando si cambiano i metodi di ripetizione, impostare Timing.repeat_until_next_click e Timing.repeat_until_end_slide prima di Timing.repeat_count, perché l’impostazione di uno dei due flag cambia anche la modalità di ripetizione attiva.

Aggiungere ed estrarre suoni delle animazioni

Un effetto di animazione può fare riferimento a audio incorporato tramite Effect.sound. Effect.stop_previous_sound indica a un effetto di fermare l’audio avviato da un effetto precedente.

Aggiungere un suono a un effetto

L’esempio seguente prevede un file audio locale denominato animation-sound.wav. Crea due effetti, incorpora quel file come suono per il primo effetto e configura il secondo effetto per fermare il suono. Utilizza gli oggetti restituiti da Sequence.add_effect, quindi non è necessario alcun indice di sequenza.

import aspose.slides as slides


with slides.Presentation() as presentation:
    slide = presentation.slides[0]
    first_shape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 80, 100, 240, 80)
    second_shape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 400, 100, 240, 80)
    first_shape.text_frame.text = "Starts sound"
    second_shape.text_frame.text = "Stops sound"

    sequence = slide.timeline.main_sequence
    first_effect = sequence.add_effect(first_shape, slides.animation.EffectType.FADE, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)
    second_effect = sequence.add_effect(second_shape, slides.animation.EffectType.FADE, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)

    with open("animation-sound.wav", "rb") as audio_file:
        effect_sound = presentation.audios.add_audio(audio_file.read())

    first_effect.sound = effect_sound
    second_effect.stop_previous_sound = True

    presentation.save("shape-animation-sound.pptx", slides.export.SaveFormat.PPTX)

Estrarre suoni incorporati negli effetti

L’esempio seguente prevede una presentazione locale denominata presentation-with-animation-sounds.pptx. Analizza sia le sequenze principali sia quelle interattive e scrive ogni suono di effetto incorporato nella cartella extracted-animation-sounds. L’estensione è selezionata dal tipo MIME audio esposto da Audio.content_type.

import os

import aspose.slides as slides


def get_audio_extension(content_type):
    normalized_type = "" if content_type is None else content_type.lower()

    if normalized_type == "audio/mpeg":
        return ".mp3"
    if normalized_type == "audio/mp4":
        return ".m4a"
    if normalized_type == "audio/ogg":
        return ".ogg"
    if normalized_type in ("audio/wav", "audio/x-wav"):
        return ".wav"

    return ".bin"


def save_sounds(sequence, output_directory, sound_index):
    for effect in sequence:
        if effect.sound is None:
            continue

        extension = get_audio_extension(effect.sound.content_type)
        output_path = os.path.join(output_directory, f"effect-sound-{sound_index}{extension}")
        with open(output_path, "wb") as output_file:
            output_file.write(bytes(effect.sound.binary_data))
        sound_index += 1

    return sound_index


input_path = "presentation-with-animation-sounds.pptx"
output_directory = "extracted-animation-sounds"

os.makedirs(output_directory, exist_ok=True)

with slides.Presentation(input_path) as presentation:
    sound_index = 1

    for slide in presentation.slides:
        sound_index = save_sounds(slide.timeline.main_sequence, output_directory, sound_index)

        for sequence in slide.timeline.interactive_sequences:
            sound_index = save_sounds(sequence, output_directory, sound_index)

print(f"Extracted {sound_index - 1} sound file(s) to {os.path.abspath(output_directory)}.")

Per oggetti audio di grandi dimensioni, usa Audio.get_stream e copia lo stream in un file invece di caricare l’intero oggetto in un array di byte.

Impostare il comportamento dopo l’animazione

L’opzione After animation controlla cosa succede a una forma dopo che il suo effetto è terminato.

Finestra di dialogo Opzioni effetto di PowerPoint che mostra le impostazioni After animation

L’enumerazione AfterAnimationType supporta il mantenimento della forma invariata, il cambiamento del colore, la nasconditura dopo l’animazione o la nasconditura al click successivo. Quando il tipo è AfterAnimationType.COLOR, impostare anche Effect.after_animation_color.

Questo esempio autonomo crea un effetto, ne imposta il comportamento dopo l’animazione tramite l’oggetto effetto restituito, e salva il risultato.

import aspose.pydrawing as draw
import aspose.slides as slides


with slides.Presentation() as presentation:
    slide = presentation.slides[0]
    shape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 120, 100, 320, 80)
    shape.text_frame.text = "Dim after animation"

    effect = slide.timeline.main_sequence.add_effect(shape, slides.animation.EffectType.FADE, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)
    effect.after_animation_type = slides.animation.AfterAnimationType.COLOR
    effect.after_animation_color.color = draw.Color.light_gray

    presentation.save("shape-animation-after-effect.pptx", slides.export.SaveFormat.PPTX)

Cambiare il tipo da AfterAnimationType.COLOR cancella l’impostazione del colore after-animation.

Animare il testo

L’animazione del testo ha due controlli correlati:

  • TextAnimation.build_type controlla se i paragrafi compaiono tutti insieme o livello per livello.
  • Effect.animate_text_type controlla se il testo compare tutto in una volta, parola per parola o lettera per lettera. Effect.delay_between_text_parts imposta il ritardo tra parole o lettere. Un valore positivo è una percentuale della durata dell’effetto; un valore negativo è un ritardo in secondi.

L’esempio autonomo seguente anima le parole in una casella di testo. BuildType.AS_ONE_OBJECT disabilita la costruzione paragrafo per paragrafo in modo che l’impostazione parola si applichi all’intero riquadro di testo.

import aspose.slides as slides


with slides.Presentation() as presentation:
    slide = presentation.slides[0]
    text_box = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 80, 80, 560, 100)
    text_box.text_frame.text = "Aspose.Slides animates this sentence word by word."

    effect = slide.timeline.main_sequence.add_effect(text_box, slides.animation.EffectType.FADE, slides.animation.EffectSubtype.NONE, slides.animation.EffectTriggerType.ON_CLICK)
    effect.text_animation.build_type = slides.animation.BuildType.AS_ONE_OBJECT
    effect.animate_text_type = slides.animation.AnimateTextType.BY_WORD
    effect.delay_between_text_parts = 20.0

    presentation.save("animated-text.pptx", slides.export.SaveFormat.PPTX)

Per costruire una casella di testo per paragrafo, impostare BuildType.BY_LEVEL_PARAGRAPHS1 (o un altro livello di paragrafo). Per indirizzare un singolo paragrafo con il proprio effetto, usa il sovraccarico di Sequence.add_effect che accetta un IParagraph. Vedi Testo animato per esempi a livello di paragrafo.

Esportazione e note di compatibilità

  • Il salvataggio in PPT o PPTX conserva il modello di animazione, ma la riproduzione finale è controllata dal visualizzatore della presentazione.
  • PDF e immagini statiche non riproducono le animazioni. Usa esportazione HTML5, GIF animata o conversione video quando l’output deve mostrare il movimento.
  • Per HTML5, abilita Html5Options.animate_shapes e, se necessario, Html5Options.animate_transitions.
  • Il rendering video supporta molti effetti di ingresso, enfasi, uscita e percorso di movimento comuni, ma non tutti gli effetti di PowerPoint sono supportati. Controlla le animazioni ed effetti supportati attuali e testa presentazioni critiche con la versione di Aspose.Slides in uso.
  • Effetti personalizzati avanzati e effetti importati da altri formati di presentazione possono essere conservati nel file ma renderizzati diversamente in PowerPoint, HTML5 o video. Convalida il risultato esportato invece di fare affidamento solo sul nome dell’effetto.

FAQ

Perché un’animazione appare in PowerPoint ma non in un PDF?

Il PDF è un formato statico, quindi le animazioni e le transizioni delle diapositive non vengono riprodotte. Esporta in HTML5, GIF animata o video quando il movimento deve essere preservato.

Perché un effetto viene riprodotto diversamente in un video?

L’esportazione video rende le animazioni invece di memorizzare il comportamento originale di PowerPoint. Alcuni effetti avanzati non sono supportati o sono approssimati. Consulta la tabella degli effetti supportati e testa la presentazione reale prima dell’uso in produzione.

Spostare una forma in avanti o indietro cambia l’ordine di animazione?

No. Lo z-order della forma controlla la sovrapposizione, mentre l’ordine della sequenza e i trigger controllano la riproduzione dell’animazione. Modifica la timeline se necessiti di un ordine di riproduzione differente.