不幸的是,关于这个库的信息非常少。安装完成后我还不完全清楚我需要导入到app.module.ts以及是否有东西要导入?我在index.html中规定了以下代码:
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']]
}
});
</script>
<script type="text/javascript" async
src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?
config=TeX-MML-AM_CHTML'>
</script>
如果我没有简单的文本,那么如何应用MathJax,但是在某些列中会出现带有公式的文本的表格?也许你可以以某种方式将整个表转移到MathJax.Hub.Queue?
我在两个星期前看到了同样的问题,今天我终于设法让它发挥作用。我不是角度专家所以它可能需要一些优化,但核心功能正在发挥作用。
将@types/mathjax
依赖项添加到您的package.json
文件中。
将新添加的类型添加到tsconfig.app.json
,如下所示:
{
"compilerOptions": {
"types": ["mathjax"]
}
}
这将允许您使用MathJax.Callback.Queue
等构造,您的IDE不会抱怨未知类型等。
我在Mathml中遇到了一些问题,所以我创建了数学包装,如下所示:
export interface MathContent {
latex?: string;
mathml?: string;
}
现在我们需要定义哪些模块可以通过配置注入MathJax脚本标记。因为它将动态加载async
,我们需要确保在MathJax完全加载之前不会启动排版。最简单的方法是将Observer<any>
存储到window
对象中。 Observer
和渲染功能可以包装成服务。
// see https://stackoverflow.com/a/12709880/1203690
declare global {
interface Window {
hubReady: Observer<boolean>;
}
}
@Injectable()
export class MathServiceImpl {
private readonly notifier: ReplaySubject<boolean>;
constructor() {
this.notifier = new ReplaySubject<boolean>();
window.hubReady = this.notifier; // as said, bind to window object
}
ready(): Observable<boolean> {
return this.notifier;
}
render(element: HTMLElement, math?: MathContent): void {
if (math) {
if (math.latex) {
element.innerText = math.latex;
} else {
element.innerHTML = math.mathml;
}
}
MathJax.Hub.Queue(['Typeset', MathJax.Hub, element]);
}
}
现在我们将创建指令,该指令将在加载MathJax后触发渲染。该指令可能如下所示:
@Directive({
selector: '[appMath]'
})
export class MathDirective implements OnInit, OnChanges, OnDestroy {
private alive$ = new Subject<boolean>();
@Input()
private appMath: MathContent;
private readonly _el: HTMLElement;
constructor(private service: MathServiceImpl,
private el: ElementRef) {
this._el = el.nativeElement as HTMLElement;
}
ngOnInit(): void {
this.service
.ready()
.pipe(
take(1),
takeUntil(this.alive$)
).subscribe(res => {
this.service.render(this._el, this.appMath);
});
}
ngOnChanges(changes: SimpleChanges): void {
console.log(changes);
}
ngOnDestroy(): void {
this.alive$.next(false);
}
}
在第四步我提到async
装载。根据onMathJax的文档,这是使用document.createElement
完成的。角度模块是这种逻辑的理想之选。要在我们的.ready()
上触发MathService
方法,我们将使用MathJax.Hub.Register.StartupHook
并从MathService
传递observable所以我们的模块将如下所示:
@NgModule({
declarations: [MathDirective],
exports: [MathDirective]
})
export class MathModule {
constructor(mathService: MathServiceImpl) {
// see https://docs.mathjax.org/en/latest/advanced/dynamic.html
const script = document.createElement('script') as HTMLScriptElement;
script.type = 'text/javascript';
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML';
script.async = true;
document.getElementsByTagName('head')[0].appendChild(script);
const config = document.createElement('script') as HTMLScriptElement;
config.type = 'text/x-mathjax-config';
// register notifier to StartupHook and trigger .next() for all subscribers
config.text = `
MathJax.Hub.Config({
skipStartupTypeset: true,
tex2jax: { inlineMath: [["$", "$"]],displayMath:[["$$", "$$"]] }
});
MathJax.Hub.Register.StartupHook('End', () => {
window.hubReady.next();
window.hubReady.complete();
});
`;
document.getElementsByTagName('head')[0].appendChild(config);
}
// this is needed so service constructor which will bind
// notifier to window object before module constructor is called
public static forRoot(): ModuleWithProviders {
return {
ngModule: MathModule,
providers: [{provide: MathServiceImpl, useClass: MathServiceImpl}]
};
}
}
现在一切准备就绪,只需在你要渲染数学的模块中导入MathModule.forRoot()
。该组件将如下所示:
export class AppComponent {
mathLatex: MathContent = {
latex: 'When $a \\ne 0$, there are two solutions to $\\frac{5}{9}$'
};
mathMl: MathContent = {
mathml: `<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mover>
<munder>
<mo>∫</mo>
<mn>0</mn>
</munder>
<mi>∞</mi>
</mover>
<mtext> versus </mtext>
<munderover>
<mo>∫</mo>
<mn>0</mn>
<mi>∞</mi>
</munderover>
</mrow>
</math>`
};
}
和模板
<div [appMath]="mathLatex"></div>
<div [appMath]="mathMl"></div>
<!-- will render inline element math -->
<div [appMath]>
$E = mc^2$
</div>
哪个应该呈现给你
这是工作stackblitz示例https://stackblitz.com/edit/mathjax-example所以你可以检查你的进度与实现