使用 MAUI 在 Windows 和 Linux 上绘制 PPT 的图表

本文介绍了如何使用MAUI在Windows和Linux上解析PPT图表并进行绘制。通过OpenXML解析PPT内容,然后利用MAUI的WPF和GTKSharp在不同平台上进行渲染。文章详细阐述了Windows下的WPF应用和Linux上的GTKSharp应用的实现,展示了从PPT图表数据解析到Skia图形库的对接过程。
摘要由CSDN通过智能技术生成

🚀 优质资源分享 🚀

学习路线指引(点击解锁) 知识定位 人群定位
🧡 Python实战微信订餐小程序 🧡 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

我在做一个图表工具软件,这个软件使用 MAUI 开发。我的需求是图表的内容需要和 PPT 的图表对接,需要用到 OpenXML 解析 PPT 内容,读取到 PPT 图表元素的内容,接着使用 MAUI 渲染层绘制图表元素。图表工具软件需要在 Windows 平台和 Linux 平台上运行。在 Windows 下,我采用 WPF 应用,用来辟谣说 MAUI 不支持 WPF 应用。 在 Linux 选用 Ubuntu 系统,采用 GTKSharp 应用加上 Skia 渲染对接 MAUI 框架

图表工具软件的开发架构如下,可以看到只有和具体平台对接的一层不相同

本文将包含两个部分,一个是解析渲染面积图图表,另一个是使用 MAUI 开发跨平台应用。解析面积图图表是用到 OpenXML 解析 PPT 的知识,本文只包含很少量的 OpenXML 的知识,我将详细的使用 OpenXML 解析 PPT 的面积图的方法放在了 dotnet OpenXML 解析 PPT 图表 面积图入门 博客里。本文的用到的解析 PPT 的代码也是从此博客里面抄的,这部分代码将不会在本文上贴出。 如对 OpenXML 解析 PPT 毫无概念的伙伴,阅读本文也不会存在问题,只需要假定本文的解析 PPT 的代码是通过某个方式获取到了图表的相关信息即可,请将重点放在图表的绘制渲染,以及如何做跨平台对接上

本文使用的代码只能用来做例子,本文的解析 PPT 图表的代码只能支持本文例子里的测试文件,本文的测试文件和代码可以从本文最后获取

在开始之前,先看一下本文实现的效果

效果

这是在 PPT 的图表:

在 Windows 下,使用 Skia 绘制为图片文件,然后使用 Image 控件显示图片,界面效果如下:

以上只是将 MAUI 接入 WPF 的一个方法。不代表只能通过图片文件的方式接入,其他绘制方法请看 WPF 使用 MAUI 的自绘制逻辑

在 Linux 下,使用 Skia 对接 Gtk 框架,界面效果如下:

动态运行效果如下

接下来将告诉大家如何实现

解析绘制面积图图表

开始实现绘制 PPT 的图表之前,需要先解析图表的内容

图表的解析部分需要用到 OpenXML 知识,这部分解析的内容,在 dotnet OpenXML 解析 PPT 图表 面积图入门 博客里面有详细说明。使用 dotnet OpenXML 解析 PPT 图表 面积图入门 的方法解析出图表的内容将获取到的内容放入到 AreaChartRenderContext 类型,此类型用来提供渲染绘制使用的上下文,包括以下属性

/// 
/// 用来提供图表 面积图 渲染的上下文信息
/// 
public class AreaChartRenderContext
{
    // 忽略代码

    public ChartSpace ChartSpace { get; }
    public SlideContext SlideContext { get; }
    public Pixel Width { get; }
    public Pixel Height { get; }

    /// 
    /// 类别轴上的数据 横坐标轴上的数据
    /// 
    public ChartValueList CategoryAxisValueList { get; } = null!;

    /// 
    /// 面积图的系列信息集合
    /// 
    public AreaChartSeriesInfoList AreaChartSeriesInfoList { get; } = new();
}

上面代码的 ChartSpace 属性是图表元素,通过 dotnet OpenXML 解析 PPT 图表 面积图入门 博客可以了解到里面包含图表的信息。上面代码的 SlideContext 属性是我所在的团队开源的 OpenXml 解析辅助库提供的包含元素所在页面的类型,详细请看: https://github.com/dotnet-campus/DocumentFormat.OpenXml.Extensions

图表关键的信息包含类别轴上的数据,也称为横坐标轴上的数据,放在 CategoryAxisValueList 属性。系列信息集合,放在 AreaChartSeriesInfoList 属性。这两个属性是从 ChartSpace 读取,读取的方法请看 dotnet OpenXML 解析 PPT 图表 面积图入门 博客或者阅读本文用到的代码

在获取到了图表的各个信息之后,即可进行绘制图表。开始进行绘制之前,还请先了解图表的各个组成部分

  • 横坐标轴 类别坐标轴数据:

  • 纵坐标轴:

  • 数据系列:

在图表里面有数据系列的概念,每个系列的数据组成一个个的数据系列。对于大部分图表来说,数据层都是由一个个数据系列组成的

每个数据系列可以有自己的系列名称

系列名称大部分时候都放在图例里面,也就是图例里面的内容就是由系列名称提供的

在图表里面,核心就是对数据的处理,系列的数据内容就是核心的

如图,面积图有两个数据系列,通过上面的 Excel 内容可以了解到两个系列的数据分别如下

系列 1:32,32,28,12,15
系列 2:12,12,12,21,28

为了让绘制逻辑更方便阅读,定义 AreaChartRender 类用来绘制图表

图表绘制 AreaChartRender 需要两个参数,一个是 AreaChartRenderContext 用来提供信息,一个是 Microsoft.Maui.Graphics.ICanvas 用来提供渲染绘制方法。在各个平台上,可以使用不同的实现对接 MAUI 的渲染,也就是 Microsoft.Maui.Graphics.ICanvas 接口可以对应不同的实现。在解析渲染模块里不耦合具体的平台渲染实现,只使用抽象的接口,定义的类型如下

public class AreaChartRender
{
    public AreaChartRender(AreaChartRenderContext context)
    {
        Context = context;
    }

    public AreaChartRenderContext Context { get; }

    public void Render(ICanvas canvas)
    {
        // 忽略代码
    }

图表绘制 AreaChartRender 基础的使用方法是在和 OpenXML 解析 PPT 的图表这一层对接,通过 AreaChartRenderContext 类型拿到图表的内容,创建出 AreaChartRender 对象,传递给具体的渲染层。在渲染层里,将区分平台进行渲染,各个平台定义 Microsoft.Maui.Graphics.ICanvas 的实现,传入到 AreaChartRender 的 Render 方法。在 Render 方法将绘制图表内容,即可通过抽象的 Microsoft.Maui.Graphics.ICanvas 接口,调用各个平台具体的绘制实现

使用以下代码即可使用 OpenXML 解析 PPT 的图表,获取图表内容,关于以下代码的细节逻辑,请看 dotnet OpenXML 解析 PPT 图表 面积图入门

public class ModelReader
{
    /// 
    /// 构建出面积图上下文
    /// 
    /// 这里是例子,要求只能传入 Test.pptx 文件。其他文件没有支持
    /// 
    public AreaChartRender BuildAreaChartRender(FileInfo file)
    {
        using var presentationDocument = PresentationDocument.Open(file.FullName, false);
        var slide = presentationDocument.PresentationPart!.SlideParts.First().Slide;

        /*
 
 
 
 ...
 
 
 
 */
        // 获取图表元素,在这份课件里,有一个面积图。以下使用 First 忽略细节,获取图表
        var graphicFrame = slide.Descendants().First();

 /*
 
 
 
 
 
 
 
 */
 // 获取到对应的图表信息,图表是引用的,内容不是放在 Slide 页面里面,而是放在独立的图表 xml 文件里
 var graphic = graphicFrame.Graphic;
 var graphicData = graphic?.GraphicData;
 var chartReference = graphicData?.GetFirstChild();

 // 获取到 id 也就是 `r:id="rId2"` 根据 Relationship 的描述,可以知道去 rels 文件里面获取关联的内容。在 OpenXml SDK 里,封装好了获取方法,获取时需要有两个参数,一个是 id 另一个是去哪里获取的 Part 内容
 var id = chartReference?.Id?.Value;

 // 这里需要告诉 OpenXml SDK 去哪里获取资源。详细请看 https://blog.lindexi.com/post/dotnet-OpenXML-%E4%B8%BA%E4%BB%80%E4%B9%88%E8%B5%84%E6%BA%90%E4%BD%BF%E7%94%A8-Relationship-%E5%BC%95%E7%94%A8.html 
 // 如果是放在模版里面,记得要用模版的 Part 去获取
 var currentPart = slide.SlidePart!;

 if (!currentPart.TryGetPartById(id!, out var openXmlPart))
 {
 // 在这份课件里,一定不会进入此分支
 // 一定能从页面找到对应的资源内容也就是图表
 }

 var chartPart = (ChartPart) openXmlPart!;

 // 这里的 ChartPart 对应的就是 charts\chartN.xml 文件。这里的 chartN.xml 表示的是 chart1.xml 或 chart2.xml 等文件
 var chartSpace = chartPart.ChartSpace;

 var slideContext = new SlideContext(slide, presentationDocument);

 var transformData = graphicFrame.GetOrCreateTransformData(slideContext);

 return new AreaChartRender(new AreaChartRenderContex
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值