Appearance
使用MathJax展示LaTeX数学公式
引入MathJax库
由于MathJax库体积较大,我们采用CDN的方式引入:
html
<script type="text/javascript" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML"></script>
MathJax配置文件
javascript
// MathJax.js
let isMathjaxConfig = false; // 用于标识是否配置
const initMathjaxConfig = () => {
if (!window.MathJax) {
return;
}
window.MathJax.Hub.Config({
showProcessingMessages: false, // 关闭js加载过程信息
messageStyle: 'none', // 不显示信息
jax: ['input/TeX', 'output/HTML-CSS'],
tex2jax: {
inlineMath: [['$', '$'], ['\\(', '\\)']], // 行内公式选择符
displayMath: [['$$', '$$'], ['\\[', '\\]']], // 段内公式选择符
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code', 'a'] // 避开某些标签
},
'HTML-CSS': {
availableFonts: ['STIX', 'TeX'], // 可选字体
showMathMenu: false // 关闭右击菜单显示
}
});
isMathjaxConfig = true; // 配置完成,改为true
};
const MathQueue = function (elementId) {
if (!window.MathJax) {
return;
}
window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, document.getElementsByClassName(elementId)]); // 根据class
// window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, document.getElementById(elementId)]); // 根据id
};
export default {
isMathjaxConfig,
initMathjaxConfig,
MathQueue
};
在VUE中局部使用
javascript
import MathJax from '../util/MathJax';
this.$nextTick(function () { // Vue的DOM渲染是异步的
if (!MathJax.isMathjaxConfig) { // 是否配置MathJax
console.log('是否配置MathJax');
MathJax.initMathjaxConfig();
}
MathJax.MathQueue('latexId'); // 渲染对应的id/class
});
实现ChatGPT打字机效果
打字机队列实现
javascript
// Typer.js
class Typewriter {
constructor(onConsume) {
this.queue = [];
this.consuming = false;
this.timmer = null;
this.onConsume = onConsume;
}
// 输出速度动态控制
dynamicSpeed() {
const speed = 2000 / this.queue.length;
return speed > 200 ? 200 : speed;
}
// 添加字符串到队列
add(str) {
if (!str) return;
this.queue.push(...str.split(''));
}
// 消费
consume() {
if (this.queue.length > 0) {
const str = this.queue.shift();
str && this.onConsume(str);
}
}
// 消费下一个
next() {
this.consume();
this.timmer = setTimeout(() => {
this.consume();
if (this.consuming) {
this.next();
}
}, this.dynamicSpeed());
}
// 开始消费队列
start() {
this.consuming = true;
this.next();
}
// 结束消费队列
done() {
this.consuming = false;
clearTimeout(this.timmer);
this.onConsume(this.queue.join(''), true);
this.queue = [];
}
}
export default Typewriter;
在VUE中使用打字机效果
javascript
import Typewriter from '../util/Typer';
const typewriter = new Typewriter(this.writing);
// 开始打字
typewriter.start();
// 数据填充
typewriter.add(msg.data);
// 结束打字
typewriter.done();
打字机样式
css
.typering::after {
content: '_';
animation: blink 1s infinite;
}
@keyframes blink {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
输出字符处理
javascript
writing(chatData, done = false) {
const dom = document.querySelector('.chat-show');
dom.innerHTML += chatData;
if (done) {
dom.classList.remove('typering');
this.$nextTick(function () { // Vue的DOM渲染是异步的
if (!MathJax.isMathjaxConfig) { // 是否配置MathJax
console.log('是否配置MathJax');
MathJax.initMathjaxConfig();
}
MathJax.MathQueue('latexId'); // 渲染对应的id/class
});
}
}