Gestionar temas de presentación en JavaScript

Introducción

Un tema de presentación define un conjunto coordinado de colores, fuentes, estilos de fondo, rellenos, líneas y efectos. Los objetos conscientes del tema hacen referencia a estas definiciones compartidas en lugar de almacenar cada propiedad visual como un valor fijo, de modo que un cambio de tema puede actualizar muchos objetos a la vez.

En Aspose.Slides, el tema a nivel de presentación está disponible a través de Presentation.getMasterTheme. Una presentación también puede contener anulaciones de tema en niveles inferiores. Un máster puede anular el tema de la presentación mediante MasterThemeManager.getOverrideTheme, mientras que un diseño o una diapositiva individual pueden anular su tema heredado mediante BaseOverrideThemeManager.getOverrideTheme. En la práctica, el tema efectivo para una diapositiva se resuelve a través de esta cadena de herencia: tema de la presentación, anulación del máster, anulación del diseño y anulación de la diapositiva.

Componentes del tema: colores, fuentes, estilos de fondo y efectos

Las secciones siguientes muestran los flujos de trabajo de tema más comunes: inspeccionar un tema, cambiar colores y fuentes, copiar o aplicar un tema, actualizar estilos de fondo y efectos, y leer valores efectivos después de que se hayan resuelto la herencia y las anulaciones.

Inspeccionar un tema

El objeto MasterTheme expone el esquema de colores, el esquema de fuentes y el esquema de formato del tema mediante MasterTheme.getColorScheme, MasterTheme.getFontScheme y MasterTheme.getFormatScheme. Inspeccionar estas colecciones antes de modificarlas es especialmente útil cuando una presentación proviene de una fuente externa, ya que el número y el contenido de las entradas de estilo pueden variar.

El siguiente ejemplo lee las propiedades principales del tema e informa cuántos estilos de fondo, relleno, línea y efecto están almacenados en el tema:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation("input.pptx");
try {
    const theme = presentation.getMasterTheme();
    console.log("Theme name: " + theme.getName());
    console.log("Accent 1: " + theme.getColorScheme().getAccent1().getColor());
    console.log("Major Latin font: " + theme.getFontScheme().getMajor().getLatinFont().getFontName());
    console.log("Minor Latin font: " + theme.getFontScheme().getMinor().getLatinFont().getFontName());
    console.log("Background fill styles: " + theme.getFormatScheme().getBackgroundFillStyles().size());
    console.log("Fill styles: " + theme.getFormatScheme().getFillStyles().size());
    console.log("Line styles: " + theme.getFormatScheme().getLineStyles().size());
    console.log("Effect styles: " + theme.getFormatScheme().getEffectStyles().size());
} finally {
    presentation.dispose();
}

Si un archivo usa varios másters, no asuma que cada diapositiva tiene el mismo tema efectivo. Inspeccione el máster asociado a la diapositiva y utilice el flujo de trabajo de tema efectivo que se muestra más adelante en este artículo cuando puedan existir anulaciones a nivel de diseño o diapositiva.

Cambiar colores del tema

Los rellenos, líneas y textos conscientes del tema pueden hacer referencia a un color lógico de la enumeración SchemeColor. Cuando cambia la entrada correspondiente en el ColorScheme, todos los objetos que todavía hacen referencia a ese color del tema se resuelven contra el nuevo valor. Los objetos que utilizan un color RGB directo no se ven afectados por la actualización del color del tema.

El siguiente ejemplo de extremo a extremo crea una forma que usa Accent4, cambia el color Accent4 del tema a rojo, guarda la presentación, la vuelve a abrir y muestra el color de relleno efectivo:

const aspose = {};
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, 10, 10, 100, 100);
    shape.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    shape.getFillFormat().getSolidFillColor().setSchemeColor(aspose.slides.SchemeColor.Accent4);
    presentation.getMasterTheme().getColorScheme().getAccent4().setColor(java.getStaticFieldValue("java.awt.Color", "RED"));
    presentation.save("theme-color.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

const savedPresentation = new aspose.slides.Presentation("theme-color.pptx");
try {
    const savedSlide = savedPresentation.getSlides().get_Item(0);
    const savedShape = savedSlide.getShapes().get_Item(0);
    const effectiveFill = savedShape.getFillFormat().getEffective();
    console.log("Effective fill color: " + effectiveFill.getSolidFillColor());
} finally {
    savedPresentation.dispose();
}

Como el rectángulo sigue vinculado a Accent4, su color visible pasa a rojo tras el cambio de tema. Si reemplaza el color del esquema por un color directo en la forma, los cambios posteriores de Accent4 ya no afectarán a ese relleno.

Usar colores de la paleta adicional

PowerPoint genera variantes más claras y más oscuras a partir de un color del tema aplicando transformaciones de color. Aspose.Slides expone estas transformaciones mediante la enumeración ColorTransformOperation.

Colores principales del tema y colores más claros y más oscuros generados a partir de la paleta adicional

1 - Colores principales del tema.
2 - Variantes más claras y más oscuras generadas a partir de los colores principales del tema.

El siguiente ejemplo crea seis rectángulos basados en Accent4, aplica transformaciones de luminancia a cinco de ellos y guarda el resultado:

const aspose = {};
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 shape1 = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 10, 10, 50, 50);
    shape1.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    shape1.getFillFormat().getSolidFillColor().setSchemeColor(aspose.slides.SchemeColor.Accent4);

    const shape2 = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 10, 70, 50, 50);
    shape2.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    shape2.getFillFormat().getSolidFillColor().setSchemeColor(aspose.slides.SchemeColor.Accent4);
    shape2.getFillFormat().getSolidFillColor().getColorTransform().add(aspose.slides.ColorTransformOperation.MultiplyLuminance, java.newFloat(0.2));
    shape2.getFillFormat().getSolidFillColor().getColorTransform().add(aspose.slides.ColorTransformOperation.AddLuminance, java.newFloat(0.8));

    const shape3 = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 10, 130, 50, 50);
    shape3.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    shape3.getFillFormat().getSolidFillColor().setSchemeColor(aspose.slides.SchemeColor.Accent4);
    shape3.getFillFormat().getSolidFillColor().getColorTransform().add(aspose.slides.ColorTransformOperation.MultiplyLuminance, java.newFloat(0.4));
    shape3.getFillFormat().getSolidFillColor().getColorTransform().add(aspose.slides.ColorTransformOperation.AddLuminance, java.newFloat(0.6));

    const shape4 = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 10, 190, 50, 50);
    shape4.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    shape4.getFillFormat().getSolidFillColor().setSchemeColor(aspose.slides.SchemeColor.Accent4);
    shape4.getFillFormat().getSolidFillColor().getColorTransform().add(aspose.slides.ColorTransformOperation.MultiplyLuminance, java.newFloat(0.6));
    shape4.getFillFormat().getSolidFillColor().getColorTransform().add(aspose.slides.ColorTransformOperation.AddLuminance, java.newFloat(0.4));

    const shape5 = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 10, 250, 50, 50);
    shape5.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    shape5.getFillFormat().getSolidFillColor().setSchemeColor(aspose.slides.SchemeColor.Accent4);
    shape5.getFillFormat().getSolidFillColor().getColorTransform().add(aspose.slides.ColorTransformOperation.MultiplyLuminance, java.newFloat(0.75));

    const shape6 = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 10, 310, 50, 50);
    shape6.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    shape6.getFillFormat().getSolidFillColor().setSchemeColor(aspose.slides.SchemeColor.Accent4);
    shape6.getFillFormat().getSolidFillColor().getColorTransform().add(aspose.slides.ColorTransformOperation.MultiplyLuminance, java.newFloat(0.5));

    presentation.save("theme-color-palette.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Estas variantes siguen basadas en el color del tema. Si Accent4 cambia más tarde, los colores transformados se recalculan a partir del nuevo valor de Accent4.

Mapear valores de SchemeColor a ranuras de ColorScheme

La enumeración SchemeColor usa Text1, Background1, Text2 y Background2, mientras que el ColorScheme expone las mismas ranuras del tema como Dark1, Light1, Dark2 y Light2. La correspondencia es fija:

  • Text1 = Dark1
  • Background1 = Light1
  • Text2 = Dark2
  • Background2 = Light2

Estos son nombres alternativos para las mismas ranuras del tema; no son valores que se conviertan dinámicamente de una forma a otra.

Cambiar fuentes del tema

Un esquema de fuentes del tema contiene un conjunto de fuentes principal para encabezados y un conjunto secundario para el cuerpo del texto. Los métodos FontScheme.getMajor y FontScheme.getMinor exponen esos conjuntos.

Los identificadores de fuentes del tema compatibles con PowerPoint pueden usarse en el formato de texto:

  • +mn-lt - Fuente del cuerpo Latin (Minor Latin Font)
  • +mj-lt - Fuente del encabezado Latin (Major Latin Font)
  • +mn-ea - Fuente del cuerpo East Asian (Minor East Asian Font)
  • +mj-ea - Fuente del encabezado East Asian (Major East Asian Font)

El siguiente ejemplo crea un encabezado que usa la fuente del tema Latin principal y una línea de cuerpo que usa la fuente del tema Latin secundaria. Luego cambia las fuentes del tema y guarda el resultado:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation();
try {
    const slide = presentation.getSlides().get_Item(0);

    const heading = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 40, 40, 500, 60);
    heading.getTextFrame().setText("Theme heading");
    heading.getTextFrame().getParagraphs().get_Item(0).getPortions().get_Item(0).getPortionFormat().setLatinFont(new aspose.slides.FontData("+mj-lt"));

    const body = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 40, 120, 500, 60);
    body.getTextFrame().setText("Theme body text");
    body.getTextFrame().getParagraphs().get_Item(0).getPortions().get_Item(0).getPortionFormat().setLatinFont(new aspose.slides.FontData("+mn-lt"));

    presentation.getMasterTheme().getFontScheme().getMajor().setLatinFont(new aspose.slides.FontData("Aptos Display"));
    presentation.getMasterTheme().getFontScheme().getMinor().setLatinFont(new aspose.slides.FontData("Arial"));
    presentation.save("theme-fonts.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

El encabezado sigue la fuente principal y el texto del cuerpo sigue la fuente secundaria. El texto que tiene un nombre de fuente explícito en lugar de un identificador de tema no cambiará automáticamente cuando el esquema de fuentes del tema cambie.

Las colecciones de fuentes mayor y menor también pueden contener asignaciones de fuentes para sistemas de escritura individuales, como cirílico, árabe, japonés, georgiano y thaana. Para inspeccionar, añadir, reemplazar o eliminar estas asignaciones, consulte Script-Specific Theme Fonts.

Copiar o aplicar un tema

Los flujos de trabajo a continuación resuelven diferentes problemas relacionados con temas.

Aplicar un tema externo a las diapositivas dependientes de un máster

Utilice MasterSlide.applyExternalThemeToDependingSlides cuando tenga un archivo de tema de PowerPoint (.thmx) y desee reestilizar cada diapositiva que dependa de un máster concreto. Seleccione el máster de la colección Presentation.getMasters, representada por MasterSlideCollection, y pase la ruta del archivo de tema al método.

El método realiza las siguientes operaciones:

  1. Crea una nueva diapositiva máster basada en el máster seleccionado.
  2. Aplica el tema externo al nuevo máster.
  3. Asigna el nuevo máster a todas las diapositivas que previamente dependían del máster seleccionado.
  4. Devuelve el MasterSlide recién creado.

El siguiente ejemplo aplica un tema externo a las diapositivas que dependen del primer máster y guarda la presentación:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation("presentation.pptx");
try {
    const selectedMaster = presentation.getMasters().get_Item(0);
    const themedMaster = selectedMaster.applyExternalThemeToDependingSlides("corporate-theme.thmx");

    console.log("Created master: " + themedMaster.getName());
    presentation.save("presentation-with-external-theme.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Un tema no válido, dañado o no compatible puede provocar PptxReadException. Valide las rutas suministradas por los usuarios, gestione los fallos de acceso al sistema de archivos y guarde la presentación solo después de que el tema se haya aplicado correctamente.

Solo se reasignan las diapositivas que dependían del máster seleccionado. Las diapositivas asociadas a otros másters conservan sus másters y temas actuales. Los colores, fuentes, rellenos, líneas, fondos y efectos conscientes del tema se resuelven contra el tema externo. Los colores, fuentes, rellenos y demás formatos asignados directamente pueden permanecer sin cambios. Las anulaciones a nivel de diseño y diapositiva también pueden tener prioridad sobre los valores heredados del nuevo máster.

El tema puede hacer referencia a fuentes que no estén disponibles en el entorno de ejecución. Para una representación y exportación consistentes, instale las fuentes necesarias, proporciónelas mediante fuentes personalizadas o configure la sustitución de fuentes.

Este es un flujo de trabajo directo a nivel de máster: el método acepta una ruta de archivo .thmx y no requiere crear manualmente anulaciones de tema a nivel de diapositiva o diseño.

Aplicar diferentes temas externos en una presentación con varios másters

Cuando el máster relevante no se conoce de antemano, obténgalo a partir de una diapositiva representativa mediante Slide.getLayoutSlide y LayoutSlide.getMasterSlide. Guarde las referencias originales de los másters antes de aplicar cualquier tema, ya que cada llamada crea otro máster en la presentación.

El siguiente ejemplo usa diapositivas de dos secciones para localizar sus másters y aplica un tema externo diferente a cada grupo:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation("multi-master-presentation.pptx");
try {
    if (presentation.getSlides().size() < 5) {
        console.log("The presentation does not contain the expected representative slides.");
    } else {
        const firstGroupMaster = presentation.getSlides().get_Item(0).getLayoutSlide().getMasterSlide();
        const secondGroupMaster = presentation.getSlides().get_Item(4).getLayoutSlide().getMasterSlide();

        if (firstGroupMaster.getSlideId() === secondGroupMaster.getSlideId()) {
            console.log("The representative slides use the same master.");
        } else {
            const firstThemedMaster = firstGroupMaster.applyExternalThemeToDependingSlides("blue-theme.thmx");
            const secondThemedMaster = secondGroupMaster.applyExternalThemeToDependingSlides("green-theme.thmx");

            console.log("First themed master: " + firstThemedMaster.getName());
            console.log("Second themed master: " + secondThemedMaster.getName());
            presentation.save("multi-master-with-external-themes.pptx", aspose.slides.SaveFormat.Pptx);
        }
    }
} finally {
    presentation.dispose();
}

La primera llamada afecta solo a las diapositivas que dependían de firstGroupMaster, y la segunda llamada afecta solo a las que dependían de secondGroupMaster. Las diapositivas pertenecientes a cualquier otro máster no se reestilizan.

Conservar un tema de origen al mover diapositivas

Si desea mover una diapositiva a otra presentación y conservar su diseño original, clone el máster de origen en la presentación de destino con MasterSlideCollection.addClone, luego clone la diapositiva con SlideCollection.addClone y el máster clonado. Esto lleva el máster, sus diseños y el tema asociado juntos.

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const source = new aspose.slides.Presentation("source-theme.pptx");
try {
    const target = new aspose.slides.Presentation("target.pptx");
    try {
        const sourceSlide = source.getSlides().get_Item(0);
        const clonedMaster = target.getMasters().addClone(sourceSlide.getLayoutSlide().getMasterSlide());
        target.getSlides().addClone(sourceSlide, clonedMaster, true);
        target.save("theme-preserved.pptx", aspose.slides.SaveFormat.Pptx);
    } finally {
        target.dispose();
    }
} finally {
    source.dispose();
}

Este es el flujo de trabajo recomendado cuando la diapositiva de origen debe verse igual en el destino. Simplemente clonar contenido sobre un máster de destino no relacionado puede cambiar los colores, fuentes, fondos y efectos controlados por el tema.

Aplicar valores del tema a una diapositiva existente

Si la diapositiva de destino debe permanecer en su máster y diseño actuales, inicialice una anulación a nivel de diapositiva a partir del tema de origen. Los métodos OverrideTheme.initColorSchemeFrom, OverrideTheme.initFontSchemeFrom y OverrideTheme.initFormatSchemeFrom copian los tres componentes principales del tema en la anulación.

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const source = new aspose.slides.Presentation("source-theme.pptx");
try {
    const target = new aspose.slides.Presentation("target.pptx");
    try {
        const sourceTheme = source.getMasterTheme();
        const targetSlide = target.getSlides().get_Item(0);
        const overrideTheme = targetSlide.getThemeManager().getOverrideTheme();
        overrideTheme.initColorSchemeFrom(sourceTheme.getColorScheme());
        overrideTheme.initFontSchemeFrom(sourceTheme.getFontScheme());
        overrideTheme.initFormatSchemeFrom(sourceTheme.getFormatScheme());
        target.save("theme-applied-to-slide.pptx", aspose.slides.SaveFormat.Pptx);
    } finally {
        target.dispose();
    }
} finally {
    source.dispose();
}

Esto cambia el tema usado por esa diapositiva sin modificar el tema heredado por otras diapositivas. Para eliminar la anulación local y volver a los valores heredados, llame a OverrideTheme.clear.

Aplicar una anulación de tema a un diseño

Una anulación a nivel de diseño se aplica a las diapositivas que usan ese diseño, a menos que una diapositiva concreta tenga su propia anulación. Los mismos métodos de inicialización pueden usarse a través de LayoutSlideThemeManager:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const source = new aspose.slides.Presentation("source-theme.pptx");
try {
    const target = new aspose.slides.Presentation("target.pptx");
    try {
        const sourceTheme = source.getMasterTheme();
        const targetSlide = target.getSlides().get_Item(0);
        const overrideTheme = targetSlide.getLayoutSlide().getThemeManager().getOverrideTheme();
        overrideTheme.initColorSchemeFrom(sourceTheme.getColorScheme());
        overrideTheme.initFontSchemeFrom(sourceTheme.getFontScheme());
        overrideTheme.initFormatSchemeFrom(sourceTheme.getFormatScheme());
        target.save("theme-applied-to-layout.pptx", aspose.slides.SaveFormat.Pptx);
    } finally {
        target.dispose();
    }
} finally {
    source.dispose();
}

Use un tema a nivel de máster o presentación cuando muchos diseños y diapositivas deben compartir el mismo diseño base, una anulación de diseño cuando una familia de diseños necesita un estilo distinto, y una anulación de diapositiva solo para excepciones reales. Un exceso de anulaciones a nivel de diapositiva dificulta predecir cambios globales posteriores del tema.

Actualizar estilos de fondo del tema

Los rellenos de fondo del tema se almacenan en FormatScheme.getBackgroundFillStyles. PowerPoint puede presentar más opciones de fondo en su interfaz que el número de definiciones de relleno almacenadas físicamente en esta colección, porque la UI puede combinar rellenos de tema con colores de tema y otras referencias de estilo.

Galería de estilos de fondo de PowerPoint para un tema de presentación

Antes de usar un estilo de fondo, inspeccione la colección almacenada y el índice de estilo actual mediante Background.getStyleIndex. Un índice de estilo 0 significa que no hay relleno temático; los valores positivos son referencias a estilos de fondo temáticos. Esto difiere del índice de la colección JavaScript, donde el índice 0 representa el primer elemento almacenado. No asuma que toda presentación contiene el mismo número de estilos de relleno de fondo.

El siguiente ejemplo informa la cantidad de rellenos de fondo disponibles, asigna una referencia de fondo temático al primer máster y guarda la presentación:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");
const java = require("java");

const presentation = new aspose.slides.Presentation("input.pptx");
try {
    const backgroundStyles = presentation.getMasterTheme().getFormatScheme().getBackgroundFillStyles();
    console.log("Background fill styles: " + backgroundStyles.size());
    if (backgroundStyles.size() === 0) {
        throw new Error("The presentation theme does not contain background fill styles.");
    }

    const masterSlide = presentation.getMasters().get_Item(0);
    masterSlide.getBackground().setType(java.newByte(aspose.slides.BackgroundType.Themed));
    masterSlide.getBackground().setStyleIndex(1);
    presentation.save("theme-background.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

El resultado visible depende de la entrada del tema referenciada por el máster y de cualquier anulación de fondo a nivel de diseño o diapositiva. Si una diapositiva usa su propio fondo, cambiar solo el fondo del máster puede no afectar a esa diapositiva. Use Background.getEffective cuando necesite conocer el fondo final después de aplicar la herencia.

Actualizar efectos del tema

Un esquema de formato del tema contiene colecciones separadas de estilos de relleno, línea y efecto expuestas mediante FormatScheme.getFillStyles, FormatScheme.getLineStyles y FormatScheme.getEffectStyles. Los temas típicos de Office suelen contener tres entradas principales que corresponden visualmente a formatos sutiles, moderados e intensos, pero el código debe inspeccionar cada colección en lugar de asumir un recuento fijo.

Efectos temáticos sutiles, moderados e intensos aplicados a la misma forma

Al acceder a estas colecciones en JavaScript, el índice de la colección es cero basado: el índice 0 es el primer estilo almacenado y el índice 2 es el tercero. Los índices de referencia de estilo de una forma son un concepto separado, expuesto mediante ShapeStyle. Modificar un estilo del tema afecta a las formas que hacen referencia a ese estilo; las formas con formato directo pueden permanecer sin cambios.

El siguiente ejemplo verifica que existan las entradas de estilo requeridas, cambia el primer estilo de línea, cambia el tercer estilo de relleno, habilita una sombra exterior en el tercer estilo de efecto y guarda el resultado:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");
const java = require("java");

const presentation = new aspose.slides.Presentation("Subtle_Moderate_Intense.pptx");
try {
    const formatScheme = presentation.getMasterTheme().getFormatScheme();
    if (formatScheme.getLineStyles().size() < 1 || formatScheme.getFillStyles().size() < 3 || formatScheme.getEffectStyles().size() < 3) {
        throw new Error("The theme does not contain the style entries required by this example.");
    }

    formatScheme.getLineStyles().get_Item(0).getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    formatScheme.getLineStyles().get_Item(0).getFillFormat().getSolidFillColor().setColor(java.getStaticFieldValue("java.awt.Color", "RED"));
    formatScheme.getFillStyles().get_Item(2).setFillType(java.newByte(aspose.slides.FillType.Solid));
    formatScheme.getFillStyles().get_Item(2).getSolidFillColor().setColor(java.newInstanceSync("java.awt.Color", 34, 139, 34));
    const effectFormat = formatScheme.getEffectStyles().get_Item(2).getEffectFormat();
    effectFormat.enableOuterShadowEffect();
    effectFormat.getOuterShadowEffect().setDistance(10);
    presentation.save("theme-effects.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

Para las formas que hacen referencia a estas ranuras, el primer estilo de línea del tema se vuelve rojo, el tercer estilo de relleno del tema se vuelve verde bosque sólido y el tercer estilo de efecto obtiene una sombra exterior con una distancia de 10 puntos. El resultado visual exacto sigue dependiendo de qué ranuras de estilo referencia cada forma y de si el formato directo anula el tema.

Estilos de efecto del tema tras cambiar línea, relleno y sombra

Determinar si un relleno sólido efectivo usa un color del tema

Un relleno puede almacenarse directamente en un objeto o heredarse de un párrafo, diseño, máster, estilo de tema u otro nivel de formato. Llame a FillFormat.getEffective para resolver esa jerarquía en una instantánea inmutable del relleno efectivo. Primero compruebe su valor getFillType. Solo cuando sea FillType.Solid debe leer las propiedades del relleno sólido.

Para un relleno sólido, getSolidFillColor devuelve el valor RGB final renderizado después de aplicar la herencia, la búsqueda en el tema y las transformaciones de color. El método getSolidFillSchemeColor devuelve la ranura lógica correspondiente de SchemeColor, como Text1 o Accent6. Un valor de SchemeColor.NotDefined indica que el relleno sólido efectivo no se basa en un color de esquema. En un flujo de trabajo donde los rellenos son colores de tema o colores RGB directos, este valor identifica un relleno RGB directo.

No use solo el valor local de ColorFormat.getSchemeColor para clasificar un relleno. Por ejemplo, una porción de texto puede no tener un color de esquema definido localmente, por lo que su valor local es NotDefined, mientras que su relleno efectivo heredado proviene de un color del tema y se resuelve a Text1 o Accent6. Por el contrario, getSolidFillSchemeColor le indica qué ranura lógica del tema generó el color efectivo, pero no le dice si esa ranura proviene del objeto, párrafo, diseño, máster u otro nivel de la jerarquía de formato.

El siguiente ejemplo carga una presentación, audita los rellenos de forma y de porciones de texto, muestra cada valor RGB final y el color de esquema asociado, y marca los rellenos sólidos que no seguirán los cambios de color del tema:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");
const java = require("java");

function toHexColor(color) {
    const red = color.getRed().toString(16).padStart(2, "0");
    const green = color.getGreen().toString(16).padStart(2, "0");
    const blue = color.getBlue().toString(16).padStart(2, "0");
    return `#${red}${green}${blue}`.toUpperCase();
}

function auditFill(objectName, localFill) {
    const effectiveFill = localFill.getEffective();

    if (effectiveFill.getFillType() !== aspose.slides.FillType.Solid) {
        console.log(objectName + ": fill type = " + effectiveFill.getFillType() + "; not a solid fill.");
        return;
    }

    const rgb = effectiveFill.getSolidFillColor();
    const effectiveSchemeColor = effectiveFill.getSolidFillSchemeColor();
    const localSchemeColor = localFill.getSolidFillColor().getSchemeColor();

    console.log(objectName + ": RGB = " + toHexColor(rgb));
    console.log(objectName + ": local scheme = " + localSchemeColor + ", effective scheme = " + effectiveSchemeColor);

    if (effectiveSchemeColor === aspose.slides.SchemeColor.NotDefined) {
        console.log(objectName + ": direct RGB or another non-scheme fill; audit as theme-independent.");
    } else {
        console.log(objectName + ": theme-dependent through " + effectiveSchemeColor + ".");
    }
}

const presentation = new aspose.slides.Presentation("input.pptx");
try {
    const slideCount = presentation.getSlides().size();
    for (let slideIndex = 0; slideIndex < slideCount; slideIndex++) {
        const slide = presentation.getSlides().get_Item(slideIndex);

        const shapeCount = slide.getShapes().size();
        for (let shapeIndex = 0; shapeIndex < shapeCount; shapeIndex++) {
            const shape = slide.getShapes().get_Item(shapeIndex);
            const shapeName = "Slide " + (slideIndex + 1) + ", shape " + (shapeIndex + 1);
            auditFill(shapeName, shape.getFillFormat());

            if (java.instanceOf(shape, "com.aspose.slides.IAutoShape")) {
                const paragraphCount = shape.getTextFrame().getParagraphs().getCount();
                for (let paragraphIndex = 0; paragraphIndex < paragraphCount; paragraphIndex++) {
                    const paragraph = shape.getTextFrame().getParagraphs().get_Item(paragraphIndex);

                    const portionCount = paragraph.getPortions().getCount();
                    for (let portionIndex = 0; portionIndex < portionCount; portionIndex++) {
                        const portion = paragraph.getPortions().get_Item(portionIndex);
                        const portionName = shapeName + ", paragraph " + (paragraphIndex + 1) + ", portion " + (portionIndex + 1);
                        auditFill(portionName, portion.getPortionFormat().getFillFormat());
                    }
                }
            }
        }
    }
} finally {
    presentation.dispose();
}

La rama NotDefined proporciona una lista de auditoría de rellenos sólidos que no responderán a cambios en las ranuras de color del tema. Revise esos objetos cuando una presentación deba ajustarse a una nueva paleta de marca. El valor RGB informado sigue mostrando la apariencia actual, mientras que el valor de esquema explica si esa apariencia está conectada al tema.

Los objetos de formato efectivo son instantáneas. Después de cambiar el tema de la presentación, una anulación de tema o cualquier formato heredado, llame a getEffective nuevamente y lea un nuevo objeto de relleno efectivo antes de comparar o informar colores.

Leer valores efectivos del tema

Los objetos de tema sin procesar le indican qué está definido en un nivel determinado. Los valores efectivos le indican qué usa realmente una diapositiva o forma después de resolver la herencia y las anulaciones locales. Para una diapositiva, llame a BaseOverrideThemeManager.createThemeEffective. Para un fondo, use Background.getEffective, y para un relleno, use FillFormat.getEffective.

El siguiente ejemplo lee el tema efectivo, el fondo y el primer relleno de forma de una diapositiva:

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation("input.pptx");
try {
    const slide = presentation.getSlides().get_Item(0);
    const effectiveTheme = slide.getThemeManager().createThemeEffective();
    const effectiveBackground = slide.getBackground().getEffective();
    console.log("Effective major Latin font: " + effectiveTheme.getFontScheme().getMajor().getLatinFont().getFontName());
    console.log("Effective minor Latin font: " + effectiveTheme.getFontScheme().getMinor().getLatinFont().getFontName());
    console.log("Effective background fill type: " + effectiveBackground.getFillFormat().getFillType());
    if (slide.getShapes().size() > 0) {
        const effectiveFill = slide.getShapes().get_Item(0).getFillFormat().getEffective();
        console.log("First shape effective fill type: " + effectiveFill.getFillType());
        if (effectiveFill.getFillType() === aspose.slides.FillType.Solid) {
            console.log("First shape effective fill color: " + effectiveFill.getSolidFillColor());
        }
    }
} finally {
    presentation.dispose();
}

Use datos efectivos para diagnósticos de renderizado, validación y comparaciones. Si solo inspecciona Presentation.getMasterTheme, puede pasar por alto una anulación de máster, diseño, diapositiva o forma que cambie la apariencia final.

FAQ

¿Aplicar un tema externo afecta a todas las diapositivas de la presentación?

No. MasterSlide.applyExternalThemeToDependingSlides reasigna solo las diapositivas que dependen del máster seleccionado. Las diapositivas que usan otros másters conservan sus temas actuales.

¿Puedo aplicar un tema a una sola diapositiva sin cambiar el máster?

Sí. Utilice el SlideThemeManager de la diapositiva y inicialice su tema de anulación. El cambio permanece local a esa diapositiva; las demás continúan heredando sus temas actuales.

¿Cuál es la forma más segura de trasladar un tema de una presentación a otra?

Al mover una diapositiva y preservar su apariencia de origen, clone el máster de origen en el destino y clone la diapositiva con ese máster usando MasterSlideCollection.addClone y SlideCollection.addClone. Esto mantiene el máster, los diseños y el tema juntos.

¿Cómo puedo ver los valores efectivos después de la herencia y las anulaciones?

Use BaseOverrideThemeManager.createThemeEffective para un tema de diapositiva o diseño y los métodos de datos efectivos correspondientes para objetos de formato como Background.getEffective y FillFormat.getEffective. Estas API devuelven los valores resueltos tras aplicar la herencia y las anulaciones.