Kết xuất các slide trình chiếu thành hình ảnh SVG trong PHP

Tổng quan

SVG là định dạng hình ảnh dựa trên XML có khả năng mở rộng, hoạt động tốt cho xuất bản web, trình xem slide, quy trình tiếp cận, và xử lý hậu kỳ tự động. Aspose.Slides xuất mỗi slide thành một tệp SVG riêng và cho phép bạn kiểm soát cách văn bản, phông chữ, hình ảnh và các phần tử SVG được ghi.

Sử dụng SVGOptions khi SVG được xuất cần gọn nhẹ, dự đoán được trên các trình duyệt, hoặc sẵn sàng cho việc sử dụng tương tác.

Xuất một Slide dưới dạng SVG

Tạo một Presentation, chọn một slide và ghi nó vào luồng bằng Slide.writeAsSvg. Ví dụ sau xuất mỗi slide trong một bản trình chiếu thành một tệp SVG riêng.

$presentation = new Presentation("presentation.pptx");
try {
    $slideCount = java_values($presentation->getSlides()->size());

    for ($slideIndex = 0; $slideIndex < $slideCount; $slideIndex++) {
        $slide = $presentation->getSlides()->get_Item($slideIndex);
        $slideNumber = java_values($slide->getSlideNumber());
        $outputFileName = sprintf("slide-%d.svg", $slideNumber);

        $svgStream = new Java("java.io.FileOutputStream", $outputFileName);
        $slide->writeAsSvg($svgStream);
        $svgStream->close();
    }
} finally {
    $presentation->dispose();
}

Tên tệp sử dụng Slide.getSlideNumber thay vì chỉ số vòng lặp. Bạn cũng có thể xuất một hình dạng riêng lẻ bằng Shape.writeAsSvg khi trình xem slide hoặc trang web chỉ cần hình dạng đó.

Cấu hình đầu ra SVG

SVGOptions kiểm soát việc render SVG. Đối với khung văn bản, SVGOptions.setUseFrameSize bao gồm khung văn bản trong khu vực render, và SVGOptions.setUseFrameRotation xác định liệu việc xoay khung có được áp dụng hay không. Đặt SVGOptions.setDisableFontLigatures thành true khi văn bản phải được render mà không có ligature.

$presentation = new Presentation("presentation.pptx");
$svgStream = null;
try {
    $svgOptions = new SVGOptions();
    $svgOptions->setDisableFontLigatures(true);
    $svgOptions->setUseFrameSize(true);
    $svgOptions->setUseFrameRotation(false);

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

Kiểm soát cắt đầu cuối đường ở mũi tên

SVG 1.1 không có cài đặt chèn marker để chỉ định nơi một đường nên dừng lại dưới mũi tên. Mặc định, Aspose.Slides rút ngắn đường được xuất để nét vẽ không vượt ra ngoài marker. Gọi SVGOptions::setDisableLineEndCropping với true để vẽ nét vẽ suốt đến điểm cuối gốc của đường. Cài đặt này chỉ ảnh hưởng đến đầu ra SVG. Đường vẫn giữ vị trí và độ dài trên slide.

Ví dụ vẽ các mũi tên hình tam giác và hình kim cương trên các đường có độ rộng 2 và 10 điểm. Nó xuất cùng một slide hai lần, chỉ thay đổi tùy chọn cắt.

use aspose\slides\FillType;
use aspose\slides\LineArrowheadStyle;
use aspose\slides\Presentation;
use aspose\slides\ShapeType;
use aspose\slides\SVGOptions;

$presentation = new Presentation();
try {
    $slide = $presentation->getSlides()->get_Item(0);
    $y = 40;

    foreach ([LineArrowheadStyle::Triangle, LineArrowheadStyle::Diamond] as $style) {
        foreach ([2, 10] as $width) {
            $line = $slide->getShapes()->addAutoShape(ShapeType::Line, 40, $y, 200, 0);
            $format = $line->getLineFormat();
            $format->getFillFormat()->setFillType(FillType::Solid);
            $color = new Java("java.awt.Color", 0, 0, 139);
            $format->getFillFormat()->getSolidFillColor()->setColor($color);
            $format->setWidth($width);
            $format->setEndArrowheadStyle($style);
            $y += 50;
        }
    }

    $options = new SVGOptions();
    $options->setDisableLineEndCropping(false);
    $cropped = new Java("java.io.FileOutputStream", "cropped.svg");
    try {
        $slide->writeAsSvg($cropped, $options);
    } finally {
        $cropped->close();
    }

    $options->setDisableLineEndCropping(true);
    $uncropped = new Java("java.io.FileOutputStream", "uncropped.svg");
    try {
        $slide->writeAsSvg($uncropped, $options);
    } finally {
        $uncropped->close();
    }
} finally {
    $presentation->dispose();
}

So sánh cho thấy mũi tên tam giác trên đường 10 điểm. Khi cắt được bật, đầu mũi tên sắc. Khi cắt bị tắt, nét vẽ vượt ra qua các cạnh nghiêng của marker và để lại một đầu phẳng.

Tam giác 10 điểm được phóng to với đầu nhọn khi bật cắt và đầu phẳng khi tắt cắt

Ở các đường khác trong ví dụ, nét vẽ vượt ra ít thấy hơn trên tam giác 2 điểm. Hình kim cương đầy màu che phủ đầu nét ở cả hai độ rộng.

Kiểm soát Văn bản và Phông chữ

Khi xuất slide sang SVG, bạn có thể kiểm soát liệu văn bản vẫn là văn bản hay được chuyển thành đồ họa vector, và cách các phông chữ bên ngoài được bao gồm hoặc tham chiếu. Các tùy chọn sau giúp bạn cân bằng độ nhất quán hình ảnh, khả năng chọn văn bản và phụ thuộc phông chữ trong SVG được xuất.

Vector hoá toàn bộ văn bản

Đặt SVGOptions.setVectorizeText thành true để ghi toàn bộ văn bản slide dưới dạng đồ họa vector. Điều này loại bỏ phụ thuộc phông chữ và làm cho kết quả hình ảnh đồng nhất hơn trên các trình duyệt, nhưng văn bản sẽ không còn có thể chọn hoặc tìm kiếm được dưới dạng văn bản SVG.

$presentation = new Presentation("presentation.pptx");
$svgStream = null;
try {
    $svgOptions = new SVGOptions();
    $svgOptions->setVectorizeText(true);

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

Chọn Cách Xử lý Phông chữ Ngoài

SVGOptions.setExternalFontsHandling sử dụng một giá trị SvgExternalFontsHandling cho các phông chữ được tải từ bên ngoài. Chọn AddLinksToFontFiles để tham chiếu các tệp phông chữ riêng biệt, Embed để bao gồm dữ liệu phông chữ trong SVG, hoặc Vectorize để render chỉ những văn bản sử dụng phông chữ bên ngoài dưới dạng đồ họa. Kiểm tra giấy phép phông chữ trước khi nhúng phông.

$presentation = new Presentation("presentation.pptx");
try {
    $slide = $presentation->getSlides()->get_Item(0);

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

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

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

Giảm kích thước ảnh nhúng

Sử dụng SVGOptions.setPicturesCompression để giảm độ phân giải của ảnh nhúng, SVGOptions.setDeletePicturesCroppedAreas để bỏ qua các khu vực đã cắt của nguồn, và SVGOptions.setJpegQuality để kiểm soát chất lượng mã hoá JPEG. Các cài đặt này giảm kích thước tệp nhưng có thể ảnh hưởng đến độ trung thực hoặc dữ liệu ảnh được giữ lại.

$presentation = new Presentation("presentation.pptx");
$svgStream = null;
try {
    $svgOptions = new SVGOptions();
    $svgOptions->setPicturesCompression(PicturesCompression::Dpi150);
    $svgOptions->setDeletePicturesCroppedAreas(true);
    $svgOptions->setJpegQuality(80);

    $slide = $presentation->getSlides()->get_Item(0);
    $svgStream = new Java("java.io.FileOutputStream", "compressed-slide.svg");
    $slide->writeAsSvg($svgStream, $svgOptions);
} finally {
    $svgStream->close();
    $presentation->dispose();
}

Kiểm soát Độ phân giải Raster hóa Metafile

SVGOptions.setMetafileRasterizationDpi đặt giới hạn độ phân giải thấp hơn cho việc raster hóa metafile trong quá trình xuất SVG. Sử dụng nó để cân bằng chi tiết và kích thước tệp khi một ảnh EMF hoặc WMF được raster hóa. Nó không xác định DPI toàn cục cho SVG hoặc buộc mọi đối tượng trên slide trở thành ảnh raster.

Tải về metafile-rasterization.pptx, chứa một ảnh EMF với các đường chéo gần nhau. Ví dụ sau xuất slide đầu tiên của nó với ba độ phân giải raster khác nhau bằng Slide.writeAsSvg. Tất cả các cài đặt xuất khác giữ nguyên để có thể so sánh kết quả.

$presentation = new Presentation("metafile-rasterization.pptx");

try {
    foreach ([72, 150, 300] as $dpi) {
        $svgOptions = new SVGOptions();
        $svgOptions->setMetafileRasterizationDpi($dpi);
        $svgOptions->setPicturesCompression(PicturesCompression::Dpi330);
        $svgOptions->setJpegQuality(90);

        $outputFileName = sprintf("slide-%d.svg", $dpi);
        $svgStream = new Java("java.io.FileOutputStream", $outputFileName);

        try {
            $presentation->getSlides()->get_Item(0)->writeAsSvg($svgStream, $svgOptions);
        } finally {
            $svgStream->close();
        }
    }
} finally {
    $presentation->dispose();
}

Trong đầu ra, EMF đã trở thành một PNG nhúng trong mỗi SVG. Các đo lường sau dành cho bản trình chiếu được cung cấp; chúng không phải là công thức chung để chuyển DPI thành kích thước pixel.

DPI raster hóa Metafile Kích thước PNG nhúng Kích thước tệp SVG (byte)
72 1196 × 596 170,221
150 2492 × 1242 423,149
300 4983 × 2483 1,027,169

So sánh dưới đây hiển thị cùng một khu vực raster nhúng ở cùng kích thước hiển thị đã phóng to. Các đường chéo cho thấy hiện tượng pixel hoá rõ ràng ở 72 DPI và các cạnh mượt hơn ở độ phân giải cao hơn, trong khi tệp SVG tăng kích thước. Tăng giá trị không nhất thiết cải thiện mọi chi tiết hoặc thay đổi mọi ảnh đã xuất.

Chi tiết đường chéo được phóng to ở 72, 150 và 300 DPI

SVGOptions.setPicturesCompression kiểm soát việc giảm độ phân giải ảnh và có thể che đi ảnh hưởng của việc thay đổi độ phân giải raster hóa metafile. SVGOptions.setJpegQuality kiểm soát chất lượng mã hoá JPEG, không phải độ phân giải raster hóa metafile.

Gán ID ổn định cho Hình dạng và Văn bản

Cung cấp một callback định dạng cho SVGOptions.setShapeFormattingController để đặt SvgShape.setId cho mỗi hình dạng SVG. Callback cũng có thể đặt giá trị SvgTSpan.setId cho các phần tử tspan văn bản.

PhpJavaBridge không thể gọi một callback PHP từ writeAsSvg khi chạy ở chế độ stream. Đặt logic định dạng vào một lớp trợ giúp Java nhỏ, biên dịch nó và thêm tệp JAR kết quả vào classpath của bridge. Trợ giúp có thể sử dụng Shape.getOfficeInteropShapeId, ổn định trong suốt vòng đời của hình dạng, và một bộ đếm lặp lại cho các đoạn văn bản của nó. Xem Java implementation of StableSvgIdController để có mã trợ giúp.

Sau khi thêm lớp đã biên dịch com.example.slides.StableSvgIdController vào classpath của bridge, khởi tạo nó từ PHP và gán cho SVGOptions:

$presentation = new Presentation("presentation.pptx");
$svgStream = null;
try {
    $shapeFormattingController = new Java("com.example.slides.StableSvgIdController");

    $svgOptions = new SVGOptions();
    $svgOptions->setShapeFormattingController($shapeFormattingController);

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

Thêm Trình xử lý Sự kiện SVG

Trong một callback định dạng, gọi SvgShape.setEventHandler với một giá trị SvgEvent để thêm trình xử lý sự kiện JavaScript vào một hình dạng đã xuất. Gán callback bằng SVGOptions.setShapeFormattingController và định nghĩa hàm JavaScript trong trang hoặc tài liệu SVG chứa kết quả.

Tương tự như ID ổn định, triển khai callback trong một trợ giúp Java khi PhpJavaBridge sử dụng chế độ stream. Java implementation of SvgEventController gán một ID và một trình xử lý OnClick cho một hình dạng có tên ActionButton. Biên dịch trợ giúp đó, thêm nó vào classpath của bridge dưới tên com.example.slides.SvgEventController, và sử dụng nó từ PHP như sau:

$presentation = new Presentation("presentation.pptx");
$svgStream = null;
try {
    $shapeFormattingController = new Java("com.example.slides.SvgEventController");

    $svgOptions = new SVGOptions();
    $svgOptions->setShapeFormattingController($shapeFormattingController);

    $slide = $presentation->getSlides()->get_Item(0);
    $svgStream = new Java("java.io.FileOutputStream", "interactive-slide.svg");
    $slide->writeAsSvg($svgStream, $svgOptions);
} finally {
    $svgStream->close();
    $presentation->dispose();
}

Trang chủ có thể định nghĩa hàm JavaScript mà trình xử lý tham chiếu. Gán ID và trình xử lý sự kiện cho phép các trình xem slide, cải thiện khả năng tiếp cận và các quy trình làm việc SVG tương tác khác.

Câu hỏi thường gặp

Khi nào tôi nên sử dụng SVGOptions.setVectorizeText thay vì SvgExternalFontsHandling.Vectorize?

Sử dụng SVGOptions.setVectorizeText khi mọi văn bản phải độc lập với phông chữ. Sử dụng SvgExternalFontsHandling.Vectorize khi chỉ những văn bản sử dụng phông chữ bên ngoài cần được chuyển thành đồ họa.

Cách tốt nhất để làm giảm kích thước SVG là gì?

Bắt đầu bằng việc nén các ảnh nhúng, xóa các khu vực ảnh đã cắt, và chọn các tệp phông chữ được liên kết khi môi trường đích có thể phục vụ chúng. Kiểm tra kết quả vì giảm độ phân giải ảnh, giảm chất lượng JPEG và vector hoá văn bản mỗi đều có sự đánh đổi về chất lượng và kích thước.

Tôi có thể sửa đổi các phần tử SVG đã xuất sau khi xuất không?

Có. Gán ID thông qua một callback định dạng, sau đó chọn các phần tử SVG phù hợp trong công cụ hậu xử lý hoặc script trình duyệt của bạn.