原文地址
前言
本站使用的是markdown
文档存储,将文档提交到前端后,前端使用marked.js做html
页面主渲染,由marked-highlight
和marked-gfm-heading-id
等插件包辅助渲染
我们在文档中常常需要插入图片,图片如果在网站页面上没有任何反馈,那么这个网站的交互就算不上理想,这里本来想看看marked
有没有现成的插件包以供使用,但是试了几个效果都不是很理想,需要调整,这个功能也不是特别麻烦,我们这里就自己实现了
实现
首先我们需要鼠标指到图片上给出可以点击的交互提示,这里比较简单,直接加个样式就可以了
.blogMarkDown img {
cursor: zoom-in;
}
然后我们需要在渲染完成后获取所有文档图片,增加一个点击事件,
<div>
<div v-html="markdownToHtml" class="blogMarkDown"></div>
</div>
本站使用的是vue
,使用computed
函数监控从后端获取的文章内容,获取成功后直接渲染,同时给img
注入事件
//init marked
marked.use(markedHighlight({
langPrefix: 'hljs language-',
highlight(code, lang) {
//convert
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
return hljs.highlight(code, {language}).value;
}
}));
marked.use(gfmHeadingId({}));
marked.use({
mangle: false,
headerIds: false
});
//compute blogContent
const markdownToHtml = computed(() => {
const html = marked.parse(blogContent.value)
buildImgFormat()
return html
})
//set img event
async function buildImgFormat() {
await sleep(1000);
let imgList = document.getElementsByTagName("img");
for (let i = 0; i < imgList.length; i++) {
if (imgList[i].classList.length > 0) {
continue
}
imgList[i].onclick = function () {
picSrc.value = imgList[i].src
const picWidthHeightRatio = imgList[i].width / imgList[i].height
let picH = 0.8 * document.documentElement.clientHeight;
let picW = picH * picWidthHeightRatio
if (picW > 0.8 * document.documentElement.clientWidth) {
picW = 0.8 * document.documentElement.clientWidth
picH = picW / picWidthHeightRatio
}
picHeight.value = Math.round(picH) + 'px'
picWidth.value = Math.round(picW) + 'px'
picShow.value = true
}
}
}
我们这里sleep
了一秒钟,因为如果直接获取,虽然html
已经生成,但此时document
的重新构建没有完成,我们这里是拿不到包含有文档的结构的,所以我们需要异步等待一秒然后再进行事件的注入
if (imgList[i].classList.length > 0) {
continue
}
这一段代码是为了区隔页面其他图片,页面正常图片在我的网站上是肯定有全局类的,所以我这里使用类数量判断,小伙伴们可以根据自己的实际情况筛选其他的判断条件,过滤非文档图片
最后附上源码地址