image與video在Quill formats中屬於Embeds,要在富文字中插入圖片或者視訊需要使用insertEmbed api。
insertEmbed
insertEmbed(index: Number, type: String, value: any, source: String = `api`): Delta
插入圖片需要位置,內容型別以及圖片的url:
quill.insertEmbed(10, `image`, `https://quilljs.com/images/cloud.png`)
獲取位置:
const range = quill.getSelection();
上傳圖片
首先toolbar中新增image,還需要一個隱藏input元素用來上傳圖片:
<template> <div> <div id="toolbar"> <span class="ql-formats"> <button class="ql-image"></button> <button class="ql-video"></button> </span> </div> <div id="editor"> <p>Hello World!</p> <p>Some initial <strong>bold</strong> text</p> <p><br></p> </div> <input id="uploadImg" type="file" style="display:none" accept="image/png, image/jpeg, image/gif" @change="uploadImage"> </div> </template>
為image新增handler,點選時上傳圖片:
this.quill.getModule("toolbar").addHandler("image", this.uploadImageHandler)
handler:
uploadImageHandler () { const input = document.querySelector(`#uploadImg`) input.value = `` input.click() },
為input元素新增onchange事件,獲取上傳圖片,上傳伺服器,獲取圖片地址,將地址插入到編輯器中:
async uploadImage (event) { const form = new FormData() form.append(`upload_file`, event.target.files[0]) const url = await $.ajax(...) #上傳圖片 獲取地址 const addImageRange = this.quill.getSelection() const newRange = 0 + (addImageRange !== null ? addImageRange.index : 0) this.quill.insertEmbed(newRange, `image`, url) this.quill.setSelection(1 + newRange) }
全部程式碼:
<template> <div> <div id="toolbar"> <span class="ql-formats"> <button class="ql-image"></button> <button class="ql-video"></button> </span> </div> <div id="editor"> <p>Hello World!</p> <p>Some initial <strong>bold</strong> text</p> <p><br></p> </div> <input id="uploadImg" type="file" style="display:none" accept="image/png, image/jpeg, image/gif" @change="uploadImage"> </div> </template> <script> import Quill from `quill` export default { name: "QuillEditor", mounted () { this.initQuill() }, beforeDestroy () { this.quill = null delete this.quill }, methods: { initQuill () { const quill = new Quill(`#editor`, { theme: `snow`, modules: { toolbar: `#toolbar` } }) this.quill = quill this.quill.getModule("toolbar").addHandler("image", this.uploadImageHandler) }, uploadImageHandler () { const input = document.querySelector(`#uploadImg`) input.value = `` input.click() }, async uploadImage (event) { const form = new FormData() form.append(`upload_file`, event.target.files[0]) const url = await $.ajax(...) const addImageRange = this.quill.getSelection() const newRange = 0 + (addImageRange !== null ? addImageRange.index : 0) this.quill.insertEmbed(newRange, `image`, url) this.quill.setSelection(1 + newRange) } } } </script>
上傳視訊做些少許修改就可以了:
<input id="uploadVideo" type="file" style="display:none" accept="video/*" @change="uploadVideo">
this.quill.getModule("toolbar").addHandler("video", this.uploadVideoHandler)
uploadVideoHandler () {...}
async uploadVideo (event) {...}
定製Video
預設的video上傳會存在一個問題,上傳後video是放在iframe中的,一般情況下是沒有問題的,但在小程式中使用h5頁面時,iframe中的域名需要新增到小程式業務域名中,否則會禁止訪問。
更好的解決方法是簡單的新增一個video元素,而不是iframe,我們需要定製一個Video Embed。
const BlockEmbed = Quill.import(`blots/block/embed`) class VideoBlot extends BlockEmbed { static create (value) { let node = super.create() node.setAttribute(`src`, value.url) node.setAttribute(`controls`, value.controls) node.setAttribute(`width`, value.width) node.setAttribute(`height`, value.height) node.setAttribute(`webkit-playsinline`, true) node.setAttribute(`playsinline`, true) node.setAttribute(`x5-playsinline`, true) return node; } static value (node) { return { url: node.getAttribute(`src`), controls: node.getAttribute(`controls`), width: node.getAttribute(`width`), height: node.getAttribute(`height`) }; } }
註冊:
VideoBlot.blotName = `simpleVideo` VideoBlot.tagName = `video` Quill.register(VideoBlot)
插入Embed:
this.quill.insertEmbed(newRange, `simpleVideo`, { url, controls: `controls`, width: `100%`, height: `100%` })
新增效果:
<video src="...mp4" controls="controls" width="100%" height="100%" webkit-playsinline="true" playsinline="true" x5-playsinline="true"></video>