HarmonyOS 鸿蒙Next中LaTex公式解析

HarmonyOS 鸿蒙Next中LaTex公式解析 在HarmonyOS开发中,有没有什么好的方法可以高效解析渲染markdown中的LaTex公式代码?

6 回复

楼主可以使用ArkWeb,在本地用 WebView 渲染 HTML,把 Markdown 转换成 HTML,并在 HTML 中引入 KaTeX 或 MathJax,这样就能像网页上一样直接渲染公式。

实现效果:

cke_3941.png

使用示例: html代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>KaTeX Demo</title>
    <!-- 从官方 CDN 引入 CSS 和 JS -->
    <link href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" rel="stylesheet">
    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
    <script defer onload="renderMathInElement(document.body, {
            delimiters: [
              { left: '$$', right: '$$', display: true },
              { left: '$', right: '$', display: false }
            ]
          });"
            src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
</head>
<body>
<p>这是行内公式:$E=mc^2$</p>
<p>这是块级公式:</p>
<p>$$ \int_0^\infty x^2 dx $$</p>
</body>
</html>

鸿蒙代码:

import { webview } from '@kit.ArkWeb'
import { webCommonPermissionHelper } from '../common/util/WebCommonPermissionHelper'

@Entry
@Component
struct WebTestPage {
  @State maskOpacity: number | Resource = 1
  @State controller: webview.WebviewController = new webview.WebviewController()
  @State url: string | Resource = $rawfile('quanxian.html')

  build() {
    /*    Stack() {
          Video({ */
    /* your video params */
    /* })
           .width('100%')
           .height('100%')

         // 遮罩
         Rect()
           .width('100%')
           .height('100%')
           .backgroundColor(Color.Blue) // 或你想要的色
           .opacity(this.maskOpacity)
       }
       .onAppear(() => {
         this.maskOpacity = 1
         this.getUIContext()?.animateTo({
           duration: 1500,
           curve: Curve.Linear
         }, () => {
           this.maskOpacity = 0
         })
       })*/

    Scroll() {
      Column() {
        Button('滚动测试').onClick((event: ClickEvent) => {
          this.controller.scrollTo(0, 0, 500);
        })
        Web({
          src: this.url,
          controller: this.controller,
        })
          .layoutWeight(1)
          .javaScriptAccess(true)
          .multiWindowAccess(false)
          .allowWindowOpenMethod(false)
          .onlineImageAccess(true)
          .domStorageAccess(true)
          .databaseAccess(true)
          .width('100%')
          .height('100%')
          .onPermissionRequest((request: OnPermissionRequestEvent) => {
            webCommonPermissionHelper.onWebPermissionRequest(request)
          })
          .onGeolocationShow(async (event: OnGeolocationShowEvent) => {
            AlertDialog.show({ message: JSON.stringify(event, null, 2) })
          })
      }
      // .height('100%')
      .width('100%')
    }
    .height('100%')
    .width('100%')
  }
}

参考文档:本地文件/在线文件加载-行业常见问题-新闻阅读类行业实践-行业实践 - 华为HarmonyOS开发者

更多关于HarmonyOS 鸿蒙Next中LaTex公式解析的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


可以使用WebView组件加载支持数学公式渲染的网页或者三方库的方式实现,在使用三方库时注意三方库版本与DevEco Studio及SDK版本对应。

HarmonyOS目前没有提供专门的数学公式渲染组件,可以使用WebView组件来加载支持数学公式渲染的网页。

Web代码示例代码如下:

import { webview } from '@kit.ArkWeb';

@Component
export struct CourseLearning {
  private webviewController: webview.WebviewController = new webview.WebviewController();

  build() {
    Column() {
      Web({ src: $rawfile('course_learning/index.html'), controller: this.webviewController })
        .domStorageAccess(true)
        .javaScriptAccess(true)
    }
  }
}

方案一:使用KaTeX渲染数学公式的html代码如下:

<!--index.html-->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>数学公式</title>
    <!-- 使用 KaTeX 渲染数学公式 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
    <style>
        body { padding: 20px; font-size: 18px; }
        .math { margin: 15px 0; }
    </style>
</head>
<body>
<h2>数学公式示例</h2>

<div class="math">勾股定理: \( a^2 + b^2 = c^2 \)</div>
<div class="math">二次方程: \[ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} \]</div>

<script>
    document.addEventListener("DOMContentLoaded", function() {
        renderMathInElement(document.body, {
            delimiters: [
                {left: "\\(", right: "\\)", display: false},
                {left: "\\[", right: "\\]", display: true}
            ]
        });
    });
</script>
</body>
</html>

方案二:使用MathJax.js渲染公式,并将个别符号修改成特殊颜色的示例代码如下:

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8" />
  <title>MathJax 颜色公式示例</title>
  <meta name="viewport" content="initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
  <!-- 加载 MathJax CDN -->
  <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
  <style>
      body {
        font-family: Arial, sans-serif;
        margin: 40px;
        line-height: 1.6;
      }
      .formula {
        background-color: #f4f4f4;
        padding: 10px;
        border-radius: 5px;
        margin: 10px 0;
        text-align: center;
      }
  </style>
</head>
<body>
<h3>MathJax 使用 \color 改变变量颜色</h3>
<p>用法:`\color{颜色名}{变量}`,例如:<code>\color{red}{x}</code></p>
<div class="formula">
  <!-- 某个符号变绿色 -->
  $$
  \color{black}{x}^2 \color{red}{+} \color{black}{y}^2 = r^2
  $$
</div>

<div class="formula">
  <!-- 混合颜色 + 文字 -->
  $$
  \text{当 } \color{purple}{a > 0} \text{ 时,方程有两个实根。}
  $$
</div>

<div class="formula">
  <!-- 更多颜色支持(CSS 颜色名或十六进制) -->
  $$
  \color{orange}{\sin \theta} + \color{#FF69B4}{\cos \theta} = \color{darkgreen}{1}
  $$
</div>

<div class="formula">
  <!-- 只改变一个符号的颜色 -->
  $$
  \sum_{i=1}^{n} \color{yellow}{a_i} = \frac{n(n+1)}{2}
  $$
</div>
</body>
</html>

三方库formula中的latexStringToImage接口可将LaTeX转换为ArrayBuffer,在经过image转换成PixelMap后进行展示。 示例代码(示例中三方库版本为1.0.0,使用其他版本注意接口传参不同):

import { LatexMathColorFormat, latexStringToImage } from '@cangjie-tpc/formula';
import { image } from '@kit.ImageKit';

@Entry
@Component
struct Index {
  str: string = "(a \\pm b)^2 = a^2 \\pm 2ab + b^2"
  @State pixelMap: image.PixelMap = undefined!;

  build() {
    Scroll() {
      Column() {
        Button("展示公式")
          .margin({left:5, top:10})
          .onClick(() => {
            this.getLatexImage()
          })
        Image(this.pixelMap)
          .objectFit(ImageFit.Contain)
          .width("80%")
          .margin({ left: 10, top: 10, bottom: 10 })
      }
      .width('100%')
      .alignItems(HorizontalAlign.Start)
    }
    .scrollBar(BarState.Off)
  }

  async getLatexImage(): Promise<void> {
    // 通过接口解析数学公式获取数学公式图片数组数据
    let buf: ArrayBuffer = await latexStringToImage(this.str, this.str.length, 200, 0xFF0000FF, 0xFFFFFFFF,
      LatexMathColorFormat.COLOR_FORMAT_BGRA_8888)
    let imageSource = image.createImageSource(buf)
    // 图片pixelMap
    this.pixelMap = imageSource.createPixelMapSync()
  }
}

推荐使用仓颇社区提供的formula-ffi库,支持将LaTeX公式转换为图片格式–PixelMap,通过ArkUI的Image组件渲染。

混合渲染流程:

// 分离Markdown文本与公式内容

import { formula } from '@cangjie-tpc/formula-ffi';  // 仓颇公式库

import { markdown } from '@cangjie-tpc/commonmark4cj';  // 仓颇Markdown解析库

async function renderMixedContent(mdText: string) {

  // 解析Markdown为AST

  const ast = markdown.parse(mdText);

  // 提取LaTeX公式节点

  const latexNodes = extractLatexNodes(ast);

  

  for (const node of latexNodes) {

    // 生成公式图片

    const buffer = await formula.latexToImage(node.content, { 

      format: 'rgba8888', 

      dpi: 300 

    });

    const imageSource = image.createImageSource(buffer);

    const pixelMap = await imageSource.createPixelMap();

    // 替换AST节点为Image组件描述

    replaceNodeWithImage(node, pixelMap);

  }

  // 渲染最终AST

  return markdown.render(ast);

}

HarmonyOS 原生并没有直接提供类似 Markdown + LaTeX 一站式渲染的官方组件

推荐使用WebView

最成熟、兼容性最好、渲染效果最佳 的方案

html 代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>KaTeX + Markdown 公式渲染示例</title>

  <!-- 引入 KaTeX 样式 -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" />

  <style>
    /* 可选:让页面整体更美观,适应移动端或 WebView */
    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      padding: 16px;
      line-height: 1.6;
      margin: 0;
      background-color: #fff;
    }
    p {
      margin: 10px 0;
    }
    /* 你可以自定义容器样式,比如用于嵌入 Markdown 内容 */
    #content {
      margin-top: 20px;
    }
  </style>
</head>
<body>

  <h1>Markdown + LaTeX 公式渲染示例</h1>

  <!-- 这里是你的 Markdown 渲染后的内容区域 -->
  <!-- 支持 $行内公式$ 和 $$块级公式$$ -->
  <div id="content">
    <p>这是一个 <strong>行内公式</strong>:$E = mc^2$,非常简洁。</p>

    <p>这是一个 <strong>块级公式(居中显示)</strong>:</p>
    <p>$$
      \int_a^b f(x)dx = F(b) - F(a)
    $$</p>

    <p>另一个块级公式:</p>
    <p>$$
      a^2 + b^2 = c^2
    $$</p>

    <p>你也可以写更复杂的公式,比如矩阵:</p>
    <p>$$
      \begin{pmatrix}
        a & b \\
        c & d
      \end{pmatrix}
    $$</p>
  </div>

  <!-- 引入 KaTeX 核心 JS -->
  <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js"></script>
  <!-- 引入自动渲染插件:自动识别页面中的 $...$ 和 $$...$$ 并渲染 -->
  <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/contrib/auto-render.min.js"
          onload="renderMathInElement(document.body, {
            delimiters: [
              {left: '$$', right: '$$', display: true},   // 块级公式
              {left: '$', right: '$', display: false}     // 行内公式
            ]
          });">
  </script>

</body>
</html>
import { webview } from '@kit.ArkWeb';

@Component
export struct CourseLearning {
  private webviewController: webview.WebviewController = new webview.WebviewController();

  build() {
    Column() {
      Web({ src: $rawfile('index.html'), controller: this.webviewController })
        .domStorageAccess(true)
        .javaScriptAccess(true)
    }
  }
}

鸿蒙Next中LaTex公式解析通过内置的数学渲染引擎实现。系统提供Math组件支持LaTex语法解析,可直接在应用界面显示数学公式。开发者需使用鸿蒙SDK提供的声明式UI语法,通过Text组件结合MathExtension能力实现公式渲染。解析过程基于鸿蒙自研的图形框架,无需依赖第三方库。具体实现涉及MathML规范转换和矢量图形绘制,支持常用数学符号与公式结构。

目前HarmonyOS Next原生暂未提供LaTeX公式解析的专用组件,但可以通过以下方式实现:

  1. Web组件加载渲染方案
    使用<Web>组件嵌入支持LaTeX的JavaScript库(如MathJax或KaTeX),通过HTML页面实时渲染公式。优势是兼容性强,但性能受Web引擎限制。

  2. 原生+C++库混合开发
    通过NAPI调用C/C++的数学公式渲染库(如LaTeX2img),将公式转换为图片后通过<Image>组件显示。适合对性能要求较高的场景。

  3. 服务端渲染+本地显示
    将LaTeX代码发送至服务端(如使用MathJax Node API)生成SVG/PNG,客户端下载后渲染。减少设备计算压力,但依赖网络。

建议根据实际场景选择方案,若需复杂公式交互可优先考虑Web方案,追求性能则推荐原生混合开发。

回到顶部