如何在画布上使用 Konva 显示丰富的 HTML
如何显示复杂样式(如粗体)并启用富文本编辑功能?
Canvas 的文本 API 非常有限。Konva.Text 允许您添加多种不同的样式,支持多行文本等。但目前它存在一些限制。您无法为 Konva.Text
的不同部分使用不同的样式。在这种情况下,您必须使用多个 Konva.Text
实例。
如果您想在画布上显示复杂样式,我们可以使用一种 hacky 的变通方法。这个想法很简单:
- 创建一个 DOM 元素并在其中放入样式化文本
- 使用 html2canvas 将 DOM 元素转换为图像。
- 使用该图像作为
Konva.Image
。
说明:尝试在上面的编辑器中输入和格式化文本。格式化后的文本将作为图像呈现在下面的画布上。您可以拖动渲染的文本。
import Konva from 'konva'; // 首先我们需要加载 Quill 和 html2canvas const loadScript = (src) => { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = src; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); }; const loadCSS = (href) => { const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = href; document.head.appendChild(link); }; // 创建编辑器容器 const editorContainer = document.createElement('div'); editorContainer.id = 'editor-container'; editorContainer.style.height = '80px'; editorContainer.innerHTML = ` 那是 <u>一些</u> <span style="color: red"> 样式化文本</span> 在 <strong>画布</strong>上! <h2>你觉得怎么样?</h2> `; document.body.appendChild(editorContainer); // 加载依赖 Promise.all([ loadScript('https://cdn.quilljs.com/1.3.6/quill.js'), loadScript('https://html2canvas.hertzen.com/dist/html2canvas.min.js'), ]).then(() => { loadCSS('https://cdn.quilljs.com/1.3.6/quill.snow.css'); const quill = new Quill('#editor-container', { modules: { toolbar: [ [{ header: [1, 2, false] }], ['bold', 'italic', 'underline'], ['image', 'code-block'], ], }, placeholder: '撰写一篇史诗...', theme: 'snow', }); const stage = new Konva.Stage({ container: 'container', width: window.innerWidth, height: 200, }); const layer = new Konva.Layer(); stage.add(layer); const shape = new Konva.Image({ x: 10, y: 10, draggable: true, stroke: 'red', scaleX: 1 / window.devicePixelRatio, scaleY: 1 / window.devicePixelRatio, }); layer.add(shape); function renderText() { // 将 DOM 转换为图像 html2canvas(document.querySelector('.ql-editor'), { backgroundColor: 'rgba(0,0,0,0)', }).then((canvas) => { // 在 Konva.Image 中显示它 shape.image(canvas); }); } // 批量更新,以便我们不会频繁渲染文本 let timeout = null; function requestTextUpdate() { if (timeout) { return; } timeout = setTimeout(function () { timeout = null; renderText(); }, 500); } // 在所有更改上渲染文本 quill.on('text-change', requestTextUpdate); // 进行初始渲染 renderText(); });