Renderizar Slides de Apresentação como Imagens SVG em JavaScript

Visão geral

SVG é um formato de imagem XML escalável que funciona bem para publicação na web, visualizadores de slides, fluxos de trabalho de acessibilidade e pós‑processamento automatizado. Aspose.Slides for Node.js via Java exporta cada slide para um arquivo SVG separado e permite controlar como texto, fontes, imagens e elementos SVG são gravados.

Use SVGOptions quando o SVG exportado precisar ser compacto, previsível entre navegadores ou pronto para uso interativo.

Exportar um Slide como SVG

Crie uma Presentation, selecione um slide e escreva‑o em um fluxo com Slide.writeAsSvg. O exemplo a seguir exporta cada slide de uma apresentação como um arquivo SVG separado.

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

const presentation = new slides.Presentation("presentation.pptx");
try {
    const slideCount = presentation.getSlides().size();
    for (let slideIndex = 0; slideIndex < slideCount; slideIndex++) {
        const slide = presentation.getSlides().get_Item(slideIndex);
        const outputFileName = `slide-${slide.getSlideNumber()}.svg`;
        const svgStream = java.newInstanceSync("java.io.FileOutputStream", outputFileName);
        try {
            slide.writeAsSvg(svgStream);
        } finally {
            svgStream.close();
        }
    }
} finally {
    presentation.dispose();
}

O nome do arquivo usa Slide.getSlideNumber em vez do índice do loop. Você também pode exportar uma forma individual com Shape.writeAsSvg quando um visualizador de slides ou página web precisa apenas dessa forma.

Configurar Saída SVG

SVGOptions controla a renderização de SVG. Para quadros de texto, SVGOptions.setUseFrameSize inclui o quadro de texto na área de renderização, e SVGOptions.setUseFrameRotation determina se a rotação do quadro é aplicada. Defina SVGOptions.setDisableFontLigatures como true quando o texto deve ser renderizado sem ligaduras.

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

const presentation = new slides.Presentation("presentation.pptx");
try {
    const svgOptions = new slides.SVGOptions();
    svgOptions.setDisableFontLigatures(true);
    svgOptions.setUseFrameSize(true);
    svgOptions.setUseFrameRotation(false);

    const slide = presentation.getSlides().get_Item(0);
    const svgStream = java.newInstanceSync(
        "java.io.FileOutputStream",
        "slide-with-custom-options.svg"
    );
    try {
        slide.writeAsSvg(svgStream, svgOptions);
    } finally {
        svgStream.close();
    }
} finally {
    presentation.dispose();
}

Controlar Corte de Extremidade de Linha em Pontas de Flecha

SVG 1.1 não possui configuração de inserção de marcador para especificar onde uma linha deve parar sob uma ponta de flecha. Por padrão, Aspose.Slides encurta a linha exportada para que seu traço não protrua através do marcador. Chame SVGOptions.setDisableLineEndCropping com true para desenhar o traço até o ponto final original da linha. Essa configuração afeta apenas a saída SVG. A linha mantém sua posição e comprimento no slide.

O exemplo desenha pontas de flecha triangulares e em forma de diamante em linhas de 2 e 10 pontos de espessura. Ele exporta o mesmo slide duas vezes, alterando apenas a opção de corte.

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

const presentation = new slides.Presentation();
try {
    const slide = presentation.getSlides().get_Item(0);
    const lineColor = java.newInstanceSync("java.awt.Color", 0, 0, 139);
    let y = 40;

    for (const style of [slides.LineArrowheadStyle.Triangle, slides.LineArrowheadStyle.Diamond]) {
        for (const width of [2, 10]) {
            const line = slide.getShapes().addAutoShape(slides.ShapeType.Line, 40, y, 200, 0);
            const format = line.getLineFormat();
            format.getFillFormat().setFillType(java.newByte(slides.FillType.Solid));
            format.getFillFormat().getSolidFillColor().setColor(lineColor);
            format.setWidth(width);
            format.setEndArrowheadStyle(java.newByte(style));
            y += 50;
        }
    }

    const options = new slides.SVGOptions();
    options.setDisableLineEndCropping(false);
    const cropped = java.newInstanceSync("java.io.FileOutputStream", "cropped.svg");
    try {
        slide.writeAsSvg(cropped, options);
    } finally {
        cropped.close();
    }

    options.setDisableLineEndCropping(true);
    const uncropped = java.newInstanceSync("java.io.FileOutputStream", "uncropped.svg");
    try {
        slide.writeAsSvg(uncropped, options);
    } finally {
        uncropped.close();
    }
} finally {
    presentation.dispose();
}

A comparação mostra a ponta de flecha triangular na linha de 10 pontos. Com o corte habilitado, a ponta está afiada. Com o corte desabilitado, o traço protrui através dos lados inclinados do marcador e deixa uma extremidade plana.

Triângulo de 10 pontos ampliado com ponta afiada quando o corte está habilitado e extremidade plana quando o corte está desabilitado

Nas outras linhas do exemplo, o traço que protrui é menos visível no triângulo de 2 pontos. O diamante preenchido cobre a extremidade do traço em ambas as espessuras.

Controlar Texto e Fontes

Ao exportar slides para SVG, você pode controlar se o texto permanece como texto ou é convertido em gráficos vetoriais, e como fontes externas são incluídas ou referenciadas. As opções a seguir ajudam a equilibrar consistência visual, seleção de texto e dependências de fontes no SVG exportado.

Vetorização de Todo o Texto

Defina SVGOptions.setVectorizeText como true para gravar todo o texto do slide como gráficos vetoriais. Isso elimina dependências de fontes e torna o resultado visual mais consistente entre navegadores, mas o texto deixa de ser selecionável ou pesquisável como texto SVG.

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

const presentation = new slides.Presentation("presentation.pptx");
try {
    const svgOptions = new slides.SVGOptions();
    svgOptions.setVectorizeText(true);

    const slide = presentation.getSlides().get_Item(0);
    const svgStream = java.newInstanceSync(
        "java.io.FileOutputStream",
        "slide-with-vectorized-text.svg"
    );
    try {
        slide.writeAsSvg(svgStream, svgOptions);
    } finally {
        svgStream.close();
    }
} finally {
    presentation.dispose();
}

Escolher Como as Fontes Externas São Tratadas

SVGOptions.setExternalFontsHandling usa um valor SvgExternalFontsHandling para fontes carregadas externamente. Escolha AddLinksToFontFiles para referenciar arquivos de fonte separados, Embed para incluir os dados da fonte no SVG, ou Vectorize para renderizar apenas o texto que usa fontes externas como gráficos. Verifique a licença da fonte antes de incorporá‑la.

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

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

    const linkedFontsOptions = new slides.SVGOptions();
    linkedFontsOptions.setExternalFontsHandling(
        slides.SvgExternalFontsHandling.AddLinksToFontFiles
    );
    const linkedFontsStream = java.newInstanceSync(
        "java.io.FileOutputStream",
        "slide-with-font-links.svg"
    );
    try {
        slide.writeAsSvg(linkedFontsStream, linkedFontsOptions);
    } finally {
        linkedFontsStream.close();
    }

    const embeddedFontsOptions = new slides.SVGOptions();
    embeddedFontsOptions.setExternalFontsHandling(
        slides.SvgExternalFontsHandling.Embed
    );
    const embeddedFontsStream = java.newInstanceSync(
        "java.io.FileOutputStream",
        "slide-with-embedded-fonts.svg"
    );
    try {
        slide.writeAsSvg(embeddedFontsStream, embeddedFontsOptions);
    } finally {
        embeddedFontsStream.close();
    }

    const vectorizedExternalFontsOptions = new slides.SVGOptions();
    vectorizedExternalFontsOptions.setExternalFontsHandling(
        slides.SvgExternalFontsHandling.Vectorize
    );
    const vectorizedExternalFontsStream = java.newInstanceSync(
        "java.io.FileOutputStream",
        "slide-with-vectorized-external-fonts.svg"
    );
    try {
        slide.writeAsSvg(vectorizedExternalFontsStream, vectorizedExternalFontsOptions);
    } finally {
        vectorizedExternalFontsStream.close();
    }
} finally {
    presentation.dispose();
}

Reduzir Tamanho de Imagens Incorporadas

Use SVGOptions.setPicturesCompression para reduzir a resolução das imagens incorporadas, SVGOptions.setDeletePicturesCroppedAreas para omitir áreas recortadas da fonte e SVGOptions.setJpegQuality para controlar a qualidade da codificação JPEG. Essas configurações reduzem o tamanho do arquivo ao custo da fidelidade da imagem ou dos dados de imagem retidos.

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

const presentation = new slides.Presentation("presentation.pptx");
try {
    const svgOptions = new slides.SVGOptions();
    svgOptions.setPicturesCompression(slides.PicturesCompression.Dpi150);
    svgOptions.setDeletePicturesCroppedAreas(true);
    svgOptions.setJpegQuality(80);

    const slide = presentation.getSlides().get_Item(0);
    const svgStream = java.newInstanceSync("java.io.FileOutputStream", "compressed-slide.svg");
    try {
        slide.writeAsSvg(svgStream, svgOptions);
    } finally {
        svgStream.close();
    }
} finally {
    presentation.dispose();
}

Controlar Resolução de Rasterização de Metarquivo

SVGOptions.setMetafileRasterizationDpi define o limite inferior de resolução para rasterizar metafiles durante a exportação SVG. Use‑a para equilibrar detalhes e tamanho do arquivo quando uma imagem EMF ou WMF é rasterizada. Ela não define um DPI global para o SVG nem força que todo objeto no slide se torne uma imagem raster.

Baixe metafile-rasterization.pptx, que contém uma imagem EMF com linhas diagonais próximas. O exemplo a seguir exporta seu primeiro slide em três resoluções de rasterização via Slide.writeAsSvg. Todas as demais configurações de exportação permanecem idênticas para que os resultados possam ser comparados.

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

const presentation = new slides.Presentation("metafile-rasterization.pptx");
try {
    for (const dpi of [72, 150, 300]) {
        const svgOptions = new slides.SVGOptions();
        svgOptions.setMetafileRasterizationDpi(dpi);
        svgOptions.setPicturesCompression(slides.PicturesCompression.Dpi330);
        svgOptions.setJpegQuality(90);

        const outputFileName = `slide-${dpi}.svg`;
        const svgStream = java.newInstanceSync("java.io.FileOutputStream", outputFileName);
        try {
            presentation.getSlides().get_Item(0).writeAsSvg(svgStream, svgOptions);
        } finally {
            svgStream.close();
        }
    }
} finally {
    presentation.dispose();
}
Rasterização de Metarquivo DPI Dimensões do PNG incorporado Tamanho do arquivo SVG (bytes)
72 1196 × 596 170,221
150 2492 × 1242 423,149
300 4983 × 2483 1,027,169

A comparação abaixo mostra a mesma área do raster incorporado no mesmo tamanho de exibição ampliado. As linhas diagonais exibem pixelização visível em 72 DPI e bordas mais suaves em resoluções maiores, enquanto o arquivo SVG cresce. Aumentar o valor não melhora necessariamente cada detalhe ou altera cada imagem exportada.

Detalhe de linha diagonal ampliado em 72, 150 e 300 DPI

SVGOptions.setPicturesCompression controla a redução da resolução da imagem e pode mascarar o efeito de mudar a resolução de rasterização do metafile. SVGOptions.setJpegQuality controla a qualidade da codificação JPEG, não a resolução de rasterização do metafile.

Atribuir IDs Estáveis a Formas e Texto

Passe um controlador de formatação para SVGOptions.setShapeFormattingController a fim de definir SvgShape.setId para cada forma SVG. Um controlador que também manipula spans de texto pode definir valores SvgTSpan.setId nos elementos tspan de texto.

O controlador a seguir usa Shape.getOfficeInteropShapeId, que é estável durante a vida útil da forma, e um contador repetível para seus spans de texto. Isso torna os IDs gerados adequados para pós‑processamento de uma apresentação inalterada.

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

class StableSvgIdController {
    constructor() {
        this.currentShapeId = "";
        this.textSpanIndex = 0;
    }

    formatShape(svgShape, shape) {
        this.currentShapeId = `shape-${shape.getOfficeInteropShapeId()}`;
        this.textSpanIndex = 0;
        svgShape.setId(this.currentShapeId);
    }

    formatText(svgTSpan, portion, textFrame) {
        const textSpanId = `${this.currentShapeId}-text-${this.textSpanIndex++}`;
        svgTSpan.setId(textSpanId);
    }

    createProxy() {
        const controller = this;
        const interfaceName = "com.aspose.slides.ISvgShapeAndTextFormattingController";
        const proxyMethods = {
            formatShape(svgShape, shape) {
                controller.formatShape(svgShape, shape);
            },
            formatText(svgTSpan, portion, textFrame) {
                controller.formatText(svgTSpan, portion, textFrame);
            }
        };
        return java.newProxy(interfaceName, proxyMethods);
    }
}

const presentation = new slides.Presentation("presentation.pptx");
try {
    const svgOptions = new slides.SVGOptions();
    const stableSvgIdController = new StableSvgIdController();
    const controllerProxy = stableSvgIdController.createProxy();
    svgOptions.setShapeFormattingController(controllerProxy);

    const slide = presentation.getSlides().get_Item(0);
    const svgStream = java.newInstanceSync(
        "java.io.FileOutputStream",
        "slide-with-stable-ids.svg"
    );
    try {
        slide.writeAsSvg(svgStream, svgOptions);
    } finally {
        svgStream.close();
    }
} finally {
    presentation.dispose();
}

Adicionar Manipuladores de Eventos SVG

Em um controlador de formatação, chame SvgShape.setEventHandler com um valor SvgEvent para adicionar um manipulador de evento JavaScript a uma forma exportada. Atribua o controlador com SVGOptions.setShapeFormattingController e defina a função JavaScript na página ou documento SVG que hospeda o resultado.

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

class SvgEventController {
    formatShape(svgShape, shape) {
        if (shape.getName() === "ActionButton") {
            svgShape.setId("action-button");
            svgShape.setEventHandler(
                slides.SvgEvent.OnClick,
                "handleShapeClick(event)"
            );
        }
    }

    createProxy() {
        const controller = this;
        const interfaceName = "com.aspose.slides.ISvgShapeFormattingController";
        const proxyMethods = {
            formatShape(svgShape, shape) {
                controller.formatShape(svgShape, shape);
            }
        };
        return java.newProxy(interfaceName, proxyMethods);
    }
}

const presentation = new slides.Presentation("presentation.pptx");
try {
    const svgOptions = new slides.SVGOptions();
    const svgEventController = new SvgEventController();
    const controllerProxy = svgEventController.createProxy();
    svgOptions.setShapeFormattingController(controllerProxy);

    const slide = presentation.getSlides().get_Item(0);
    const svgStream = java.newInstanceSync("java.io.FileOutputStream", "interactive-slide.svg");
    try {
        slide.writeAsSvg(svgStream, svgOptions);
    } finally {
        svgStream.close();
    }
} finally {
    presentation.dispose();
}

A página host pode definir a função JavaScript referenciada pelo manipulador. Atribuir IDs e manipuladores de eventos habilita visualizadores de slide, aprimoramentos de acessibilidade e outros fluxos de trabalho interativos com SVG.

Perguntas Frequentes

Quando devo usar SVGOptions.setVectorizeText em vez de SvgExternalFontsHandling.Vectorize?

Use SVGOptions.setVectorizeText quando todo o texto deve ser independente de fontes. Use SvgExternalFontsHandling.Vectorize quando somente o texto que usa fontes externas deve ser convertido em gráficos.

Qual é a melhor forma de tornar um SVG menor?

Comece comprimindo as imagens incorporadas, excluindo áreas recortadas da imagem e escolhendo arquivos de fonte vinculados quando o ambiente de destino puder servi‑los. Teste o resultado, pois resolução de imagem menor, qualidade JPEG reduzida e texto vetorizado têm diferentes compromissos de qualidade e tamanho.

Posso modificar os elementos SVG exportados após a exportação?

Sim. Atribua IDs através de um controlador de formatação e, em seguida, selecione os elementos SVG correspondentes em sua ferramenta de pós‑processamento ou script de navegador.