Rendre les diapositives de présentation en images SVG en JavaScript

Vue d’ensemble

SVG est un format d’image évolutif basé sur XML qui fonctionne bien pour la publication web, les visionneuses de diapositives, les flux de travail d’accessibilité et le post‑traitement automatisé. Aspose.Slides for Node.js via Java exporte chaque diapositive vers un fichier SVG distinct et vous permet de contrôler la façon dont le texte, les polices, les images et les éléments SVG sont écrits.

Utilisez SVGOptions lorsque le SVG exporté doit être compact, prévisible sur tous les navigateurs ou prêt à être utilisé de façon interactive.

Exporter une diapositive en SVG

Créez une Presentation, sélectionnez une diapositive et écrivez‑la dans un flux avec Slide.writeAsSvg. L’exemple suivant exporte chaque diapositive d’une présentation comme fichier SVG séparé.

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();
}

Le nom de fichier utilise Slide.getSlideNumber plutôt que l’indice de boucle. Vous pouvez également exporter une forme individuelle avec Shape.writeAsSvg lorsqu’une visionneuse de diapositives ou une page web n’a besoin que de cette forme.

Configurer la sortie SVG

SVGOptions contrôle le rendu SVG. Pour les cadres de texte, SVGOptions.setUseFrameSize inclut le cadre de texte dans la zone de rendu, et SVGOptions.setUseFrameRotation détermine si la rotation du cadre est appliquée. Définissez SVGOptions.setDisableFontLigatures sur true lorsque le texte doit être rendu sans ligatures.

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();
}

Contrôler le rognage des extrémités de ligne aux pointes de flèche

SVG 1.1 ne possède aucun paramètre d’insertion de marqueur pour spécifier où une ligne doit s’arrêter sous une pointe de flèche. Par défaut, Aspose.Slides raccourcit la ligne exportée afin que son tracé ne dépasse pas le marqueur. Appelez SVGOptions.setDisableLineEndCropping avec true pour tracer le trait jusqu’au point d’extrémité d’origine de la ligne. Ce paramètre n’affecte que la sortie SVG. La ligne conserve sa position et sa longueur sur la diapositive.

L’exemple dessine des pointes de flèche triangulaires et en forme de losange sur des lignes de 2 pt et de 10 pt d’épaisseur. Il exporte la même diapositive deux fois, en ne modifiant que l’option de rognage.

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();
}

La comparaison montre la pointe triangulaire sur la ligne de 10 pt. Avec le rognage activé, la pointe est nette. Avec le rognage désactivé, le tracé dépasse les côtés inclinés du marqueur et laisse une extrémité plate.

Triangle de 10 points agrandi avec une pointe aiguë lorsque le rognage est activé et une extrémité plate lorsqu’il est désactivé

Dans les autres lignes de l’exemple, le tracé qui dépasse est moins visible sur le triangle de 2 pt. Le losange rempli couvre l’extrémité du tracé à les deux largeurs.

Contrôler le texte et les polices

Lors de l’exportation de diapositives en SVG, vous pouvez contrôler si le texte reste du texte ou est converti en graphiques vectoriels, ainsi que la manière dont les polices externes sont incluses ou référencées. Les options suivantes vous aident à concilier cohérence visuelle, sélection du texte et dépendances de polices dans le SVG exporté.

Vectoriser tout le texte

Définissez SVGOptions.setVectorizeText sur true pour écrire tout le texte de la diapositive sous forme de graphiques vectoriels. Cela élimine les dépendances aux polices et rend le rendu visuel plus homogène sur les navigateurs, mais le texte n’est plus sélectionnable ni recherchable en tant que texte 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();
}

Choisir la manière dont les polices externes sont gérées

SVGOptions.setExternalFontsHandling utilise une valeur SvgExternalFontsHandling pour les polices chargées extérieurement. Choisissez AddLinksToFontFiles pour référencer des fichiers de polices séparés, Embed pour inclure les données de police dans le SVG, ou Vectorize pour rendre uniquement le texte qui utilise des polices externes sous forme de graphiques. Vérifiez les licences de police avant d’incorporer des polices.

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();
}

Réduire la taille des images incorporées

Utilisez SVGOptions.setPicturesCompression pour réduire la résolution des images incorporées, SVGOptions.setDeletePicturesCroppedAreas pour omettre les zones sources recadrées, et SVGOptions.setJpegQuality pour contrôler la qualité d’encodage JPEG. Ces paramètres réduisent la taille du fichier au prix d’une perte de fidélité d’image ou de données d’image conservées.

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();
}

Contrôler la résolution de rasterisation des métafichiers

SVGOptions.setMetafileRasterizationDpi définit la limite inférieure de résolution pour la rasterisation des métafichiers lors de l’exportation SVG. Utilisez‑la pour équilibrer le niveau de détail et la taille du fichier lorsqu’une image EMF ou WMF est rasterisée. Elle ne définit pas un DPI global pour le SVG ni ne force chaque objet de la diapositive à devenir une image raster.

Téléchargez metafile-rasterization.pptx, qui contient une image EMF avec des lignes diagonales très rapprochées. L’exemple suivant exporte la première diapositive à trois résolutions de rasterisation via Slide.writeAsSvg. Tous les autres paramètres d’exportation restent identiques afin que les résultats puissent être comparés.

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();
}

Dans la sortie, l’EMF est devenu un PNG incorporé dans chaque SVG. Les mesures suivantes concernent la présentation fournie ; elles ne constituent pas une formule générale de conversion DPI → dimensions en pixels.

DPI de rasterisation du métafichier Dimensions du PNG intégré Taille du fichier SVG (octets)
72 1196 × 596 170 221
150 2492 × 1242 423 149
300 4983 × 2483 1 027 169

La comparaison ci‑dessous montre la même zone du raster incorporé à la même taille d’affichage agrandie. Les lignes diagonales affichent une pixellisation visible à 72 DPI et des contours plus lisses à des résolutions supérieures, tandis que le fichier SVG augmente. Augmenter la valeur n’améliore pas nécessairement chaque détail ni ne change chaque image exportée.

Détail agrandi des lignes diagonales à 72, 150 et 300 DPI

SVGOptions.setPicturesCompression contrôle la réduction de résolution des images et peut masquer l’effet du changement de résolution de rasterisation du métafichier. SVGOptions.setJpegQuality contrôle la qualité d’encodage JPEG, pas la résolution de rasterisation du métafichier.

Attribuer des ID stables aux formes et au texte

Passez un contrôleur de formatage à SVGOptions.setShapeFormattingController pour définir SvgShape.setId pour chaque forme SVG. Un contrôleur qui gère également les spans de texte peut définir les valeurs SvgTSpan.setId sur les éléments tspan du texte.

Le contrôleur suivant utilise Shape.getOfficeInteropShapeId, qui est stable pendant toute la durée de vie de la forme, et un compteur répétable pour ses spans de texte. Cela rend les ID générés adaptés au post‑traitement d’une présentation non modifiée.

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();
}

Ajouter des gestionnaires d’événements SVG

Dans un contrôleur de formatage, appelez SvgShape.setEventHandler avec une valeur SvgEvent pour ajouter un gestionnaire d’événement JavaScript à une forme exportée. Assignez le contrôleur avec SVGOptions.setShapeFormattingController et définissez la fonction JavaScript dans la page ou le document SVG qui héberge le résultat.

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();
}

La page hôte peut définir la fonction JavaScript référencée par le gestionnaire. L’attribution d’ID et de gestionnaires d’événements permet aux visionneuses de diapositives, aux améliorations d’accessibilité et à d’autres flux de travail SVG interactifs.

FAQ

Quand devrais-je utiliser SVGOptions.setVectorizeText au lieu de SvgExternalFontsHandling.Vectorize?

Utilisez SVGOptions.setVectorizeText lorsque tout le texte doit être indépendant des polices. Utilisez SvgExternalFontsHandling.Vectorize lorsque seul le texte qui utilise des polices externes doit être converti en graphiques.

Quelle est la meilleure façon de réduire la taille d’un SVG ?

Commencez par compresser les images incorporées, supprimer les zones recadrées et choisir des fichiers de polices liés lorsque l’environnement cible peut les servir. Testez le résultat car une résolution d’image moindre, une qualité JPEG plus basse et un texte vectorisé entraînent chacun des compromis différents en termes de qualité et de taille.

Puis-je modifier les éléments SVG exportés après l’exportation ?

Oui. Attribuez des ID via un contrôleur de formatage, puis sélectionnez les éléments SVG correspondants dans votre outil de post‑traitement ou script de navigateur.