mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-17 22:08:25 +08:00
Merge branch 'feature' into main
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -298,7 +298,11 @@ class MindMap {
|
||||
this.execCommand('CLEAR_ACTIVE_NODE')
|
||||
this.command.clearHistory()
|
||||
this.command.addHistory()
|
||||
this.renderer.renderTree = data
|
||||
if (this.richText) {
|
||||
this.renderer.renderTree = this.richText.handleSetData(data)
|
||||
} else {
|
||||
this.renderer.renderTree = data
|
||||
}
|
||||
this.reRender()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-mind-map",
|
||||
"version": "0.5.6",
|
||||
"version": "0.5.7",
|
||||
"description": "一个简单的web在线思维导图",
|
||||
"authors": [
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ class Export {
|
||||
}
|
||||
|
||||
// 获取svg数据
|
||||
async getSvgData(domToImage) {
|
||||
async getSvgData() {
|
||||
let { exportPaddingX, exportPaddingY } = this.mindMap.opt
|
||||
let { svg, svgHTML } = this.mindMap.getSvgData({
|
||||
paddingX: exportPaddingX,
|
||||
@@ -44,24 +44,14 @@ class Export {
|
||||
if (imageList.length > 0) {
|
||||
svgHTML = svg.svg()
|
||||
}
|
||||
// 如果开启了富文本编辑,需要把svg中的dom元素转换成图片
|
||||
let nodeWithDomToImg = null
|
||||
if (domToImage && this.mindMap.richText) {
|
||||
let res = await this.mindMap.richText.handleSvgDomElements(svg)
|
||||
if (res) {
|
||||
nodeWithDomToImg = res.svg
|
||||
svgHTML = res.svgHTML
|
||||
}
|
||||
}
|
||||
return {
|
||||
node: svg,
|
||||
str: svgHTML,
|
||||
nodeWithDomToImg
|
||||
str: svgHTML
|
||||
}
|
||||
}
|
||||
|
||||
// svg转png
|
||||
svgToPng(svgSrc) {
|
||||
svgToPng(svgSrc, transparent) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
// 跨域图片需要添加这个属性,否则画布被污染了无法导出图片
|
||||
@@ -73,7 +63,9 @@ class Export {
|
||||
canvas.height = img.height + this.exportPadding * 2
|
||||
let ctx = canvas.getContext('2d')
|
||||
// 绘制背景
|
||||
await this.drawBackgroundToCanvas(ctx, canvas.width, canvas.height)
|
||||
if (!transparent) {
|
||||
await this.drawBackgroundToCanvas(ctx, canvas.width, canvas.height)
|
||||
}
|
||||
// 图片绘制到canvas里
|
||||
ctx.drawImage(
|
||||
img,
|
||||
@@ -140,8 +132,14 @@ class Export {
|
||||
* 方法1.把svg的图片都转化成data:url格式,再转换
|
||||
* 方法2.把svg的图片提取出来再挨个绘制到canvas里,最后一起转换
|
||||
*/
|
||||
async png() {
|
||||
let { str } = await this.getSvgData(true)
|
||||
async png(name, transparent = false) {
|
||||
let { node, str } = await this.getSvgData()
|
||||
// 如果开启了富文本,则使用htmltocanvas转换为图片
|
||||
if (this.mindMap.richText) {
|
||||
let res = await this.mindMap.richText.handleExportPng(node.node)
|
||||
let imgDataUrl = await this.svgToPng(res, transparent)
|
||||
return imgDataUrl
|
||||
}
|
||||
// 转换成blob数据
|
||||
let blob = new Blob([str], {
|
||||
type: 'image/svg+xml'
|
||||
@@ -149,7 +147,7 @@ class Export {
|
||||
// 转换成data:url数据
|
||||
let svgUrl = URL.createObjectURL(blob)
|
||||
// 绘制到canvas上
|
||||
let imgDataUrl = await this.svgToPng(svgUrl)
|
||||
let imgDataUrl = await this.svgToPng(svgUrl, transparent)
|
||||
URL.revokeObjectURL(svgUrl)
|
||||
return imgDataUrl
|
||||
}
|
||||
@@ -209,15 +207,12 @@ class Export {
|
||||
}
|
||||
|
||||
// 导出为svg
|
||||
// domToImage:是否将svg中的dom节点转换成图片的形式
|
||||
// plusCssText:附加的css样式,如果svg中存在dom节点,想要设置一些针对节点的样式可以通过这个参数传入
|
||||
async svg(name, domToImage = false, plusCssText) {
|
||||
let { node, nodeWithDomToImg } = await this.getSvgData(domToImage)
|
||||
async svg(name, plusCssText) {
|
||||
let { node } = await this.getSvgData()
|
||||
// 开启了节点富文本编辑
|
||||
if (this.mindMap.richText) {
|
||||
if (domToImage) {
|
||||
node = nodeWithDomToImg
|
||||
} else if (plusCssText) {
|
||||
if (plusCssText) {
|
||||
let foreignObjectList = node.find('foreignObject')
|
||||
if (foreignObjectList.length > 0) {
|
||||
foreignObjectList[0].add(SVG(`<style>${plusCssText}</style>`))
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import Quill from 'quill'
|
||||
import 'quill/dist/quill.snow.css'
|
||||
import html2canvas from 'html2canvas'
|
||||
import { Image as SvgImage } from '@svgdotjs/svg.js'
|
||||
import { walk } from './utils'
|
||||
import { walk, getTextFromHtml } from './utils'
|
||||
import { CONSTANTS } from './utils/constant'
|
||||
|
||||
let extended = false
|
||||
@@ -45,6 +44,11 @@ class RichText {
|
||||
this.initOpt()
|
||||
this.extendQuill()
|
||||
this.appendCss()
|
||||
|
||||
// 处理数据,转成富文本格式
|
||||
if (this.mindMap.opt.data) {
|
||||
this.mindMap.opt.data = this.handleSetData(this.mindMap.opt.data)
|
||||
}
|
||||
}
|
||||
|
||||
// 插入样式
|
||||
@@ -65,14 +69,15 @@ class RichText {
|
||||
.ql-container.ql-snow {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.smm-richtext-node-wrap p {
|
||||
font-family: auto;
|
||||
}
|
||||
|
||||
.smm-richtext-node-edit-wrap p {
|
||||
font-family: auto;
|
||||
}
|
||||
`
|
||||
// .smm-richtext-node-wrap p {
|
||||
// display: flex;
|
||||
// }
|
||||
|
||||
// .smm-richtext-node-edit-wrap p {
|
||||
// display: flex;
|
||||
// }
|
||||
this.styleEl = document.createElement('style')
|
||||
this.styleEl.type = 'text/css'
|
||||
this.styleEl.innerHTML = cssText
|
||||
@@ -130,36 +135,39 @@ class RichText {
|
||||
if (!rect) rect = node._textData.node.node.getBoundingClientRect()
|
||||
this.mindMap.emit('before_show_text_edit')
|
||||
this.mindMap.renderer.textEdit.registerTmpShortcut()
|
||||
const paddingX = 5
|
||||
const paddingY = 3
|
||||
// 原始宽高
|
||||
let g = node._textData.node
|
||||
let originWidth = g.attr('data-width')
|
||||
let originHeight = g.attr('data-height')
|
||||
// 缩放值
|
||||
let scaleX = rect.width / originWidth
|
||||
let scaleY = rect.height / originHeight
|
||||
// 内边距
|
||||
const paddingX = 6
|
||||
const paddingY = 4
|
||||
if (!this.textEditNode) {
|
||||
this.textEditNode = document.createElement('div')
|
||||
this.textEditNode.classList.add('smm-richtext-node-edit-wrap')
|
||||
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;box-shadow: 0 0 20px rgba(0,0,0,.5);outline: none; word-break: break-all;padding: ${paddingY}px ${paddingX}px;margin-left: -${paddingX}px;margin-top: -${paddingY}px;`
|
||||
this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;box-shadow: 0 0 20px rgba(0,0,0,.5);outline: none; word-break: break-all;padding: ${paddingY}px ${paddingX}px;`
|
||||
this.textEditNode.addEventListener('click', e => {
|
||||
e.stopPropagation()
|
||||
})
|
||||
document.body.appendChild(this.textEditNode)
|
||||
}
|
||||
// 原始宽高
|
||||
let g = node._textData.node
|
||||
let originWidth = g.attr('data-width')
|
||||
let originHeight = g.attr('data-height')
|
||||
// 使用节点的填充色,否则如果节点颜色是白色的话编辑时看不见
|
||||
let bgColor = node.style.merge('fillColor')
|
||||
this.textEditNode.style.marginLeft = `-${paddingX * scaleX}px`
|
||||
this.textEditNode.style.marginTop = `-${paddingY * scaleY}px`
|
||||
this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex
|
||||
this.textEditNode.style.backgroundColor = bgColor === 'transparent' ? '#fff' : bgColor
|
||||
this.textEditNode.style.minWidth = originWidth + paddingX * 2 + 'px'
|
||||
this.textEditNode.style.minHeight = originHeight + 'px'
|
||||
this.textEditNode.style.left =
|
||||
rect.left + (rect.width - originWidth) / 2 + 'px'
|
||||
this.textEditNode.style.top =
|
||||
rect.top + (rect.height - originHeight) / 2 + 'px'
|
||||
this.textEditNode.style.left = rect.left + 'px'
|
||||
this.textEditNode.style.top = rect.top + 'px'
|
||||
this.textEditNode.style.display = 'block'
|
||||
this.textEditNode.style.maxWidth = this.mindMap.opt.textAutoWrapWidth + paddingX * 2 + 'px'
|
||||
this.textEditNode.style.transform = `scale(${rect.width / originWidth}, ${
|
||||
rect.height / originHeight
|
||||
})`
|
||||
this.textEditNode.style.transform = `scale(${scaleX}, ${scaleY})`
|
||||
this.textEditNode.style.transformOrigin = 'left top'
|
||||
if (!node.nodeData.data.richText) {
|
||||
// 还不是富文本的情况
|
||||
let text = node.nodeData.data.text.split(/\n/gim).join('<br>')
|
||||
@@ -396,94 +404,40 @@ class RichText {
|
||||
return data
|
||||
}
|
||||
|
||||
// 将svg中嵌入的dom元素转换成图片
|
||||
async _handleSvgDomElements(svg) {
|
||||
svg = svg.clone()
|
||||
let foreignObjectList = svg.find('foreignObject')
|
||||
let task = foreignObjectList.map(async item => {
|
||||
let clone = item.first().node.cloneNode(true)
|
||||
let div = document.createElement('div')
|
||||
div.style.cssText = `position: fixed; left: -999999px;`
|
||||
div.appendChild(clone)
|
||||
this.mindMap.el.appendChild(div)
|
||||
let canvas = await html2canvas(clone, {
|
||||
backgroundColor: null
|
||||
})
|
||||
this.mindMap.el.removeChild(div)
|
||||
let imgNode = new SvgImage()
|
||||
.load(canvas.toDataURL())
|
||||
.size(canvas.width, canvas.height)
|
||||
item.replace(imgNode)
|
||||
})
|
||||
await Promise.all(task)
|
||||
return {
|
||||
svg: svg,
|
||||
svgHTML: svg.svg()
|
||||
// 处理导出为图片
|
||||
async handleExportPng(node) {
|
||||
let el = document.createElement('div')
|
||||
el.style.position = 'absolute'
|
||||
el.style.left = '-9999999px'
|
||||
el.appendChild(node)
|
||||
this.mindMap.el.appendChild(el)
|
||||
// 遍历所有节点,将它们的margin和padding设为0
|
||||
let walk = (root) => {
|
||||
root.style.margin = 0
|
||||
root.style.padding = 0
|
||||
if (root.hasChildNodes()) {
|
||||
Array.from(root.children).forEach((item) => {
|
||||
walk(item)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将svg中嵌入的dom元素转换成图片
|
||||
handleSvgDomElements(svg) {
|
||||
return new Promise((resolve, reject) => {
|
||||
svg = svg.clone()
|
||||
let foreignObjectList = svg.find('foreignObject')
|
||||
let index = 0
|
||||
let len = foreignObjectList.length
|
||||
let transform = async () => {
|
||||
this.mindMap.emit('transforming-dom-to-images', index, len)
|
||||
try {
|
||||
let item = foreignObjectList[index++]
|
||||
let parent = item.parent()
|
||||
let clone = item.first().node.cloneNode(true)
|
||||
let div = document.createElement('div')
|
||||
div.style.cssText = `position: fixed; left: -999999px;`
|
||||
div.appendChild(clone)
|
||||
this.mindMap.el.appendChild(div)
|
||||
let canvas = await html2canvas(clone, {
|
||||
backgroundColor: null
|
||||
})
|
||||
// 优先使用原始宽高,因为当设备的window.devicePixelRatio不为1时,html2canvas输出的图片会更大
|
||||
let imgNodeWidth = parent.attr('data-width') || canvas.width
|
||||
let imgNodeHeight = parent.attr('data-height') || canvas.height
|
||||
this.mindMap.el.removeChild(div)
|
||||
let imgNode = new SvgImage()
|
||||
.load(canvas.toDataURL())
|
||||
.size(imgNodeWidth, imgNodeHeight)
|
||||
.x((parent ? parent.attr('data-offsetx') : 0) || 0)
|
||||
item.replace(imgNode)
|
||||
if (index <= len - 1) {
|
||||
setTimeout(() => {
|
||||
transform()
|
||||
}, 0)
|
||||
} else {
|
||||
resolve({
|
||||
svg: svg,
|
||||
svgHTML: svg.svg()
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
}
|
||||
if (len > 0) {
|
||||
transform()
|
||||
} else {
|
||||
resolve(null)
|
||||
}
|
||||
walk(node)
|
||||
let canvas = await html2canvas(el, {
|
||||
backgroundColor: null
|
||||
})
|
||||
this.mindMap.el.removeChild(el)
|
||||
return canvas.toDataURL()
|
||||
}
|
||||
|
||||
// 将所有节点转换成非富文本节点
|
||||
transformAllNodesToNormalNode() {
|
||||
let div = document.createElement('div')
|
||||
walk(
|
||||
this.mindMap.renderer.renderTree,
|
||||
null,
|
||||
node => {
|
||||
if (node.data.richText) {
|
||||
node.data.richText = false
|
||||
div.innerHTML = node.data.text
|
||||
node.data.text = div.textContent
|
||||
node.data.text = getTextFromHtml(node.data.text)
|
||||
// delete node.data.uid
|
||||
}
|
||||
},
|
||||
@@ -498,6 +452,23 @@ class RichText {
|
||||
this.mindMap.render(null, CONSTANTS.TRANSFORM_TO_NORMAL_NODE)
|
||||
}
|
||||
|
||||
// 处理导入数据
|
||||
handleSetData(data) {
|
||||
let walk = (root) => {
|
||||
if (!root.data.richText) {
|
||||
root.data.richText = true
|
||||
root.data.resetRichText = true
|
||||
}
|
||||
if (root.children && root.children.length > 0) {
|
||||
Array.from(root.children).forEach((item) => {
|
||||
walk(item)
|
||||
})
|
||||
}
|
||||
}
|
||||
walk(data)
|
||||
return data
|
||||
}
|
||||
|
||||
// 插件被移除前做的事情
|
||||
beforePluginRemove() {
|
||||
this.transformAllNodesToNormalNode()
|
||||
|
||||
@@ -109,6 +109,18 @@ class Style {
|
||||
})
|
||||
}
|
||||
|
||||
// 生成内联样式
|
||||
createStyleText() {
|
||||
return `
|
||||
color: ${this.merge('color')};
|
||||
font-family: ${this.merge('fontFamily')};
|
||||
font-size: ${this.merge('fontSize') + 'px'};
|
||||
font-weight: ${this.merge('fontWeight')};
|
||||
font-style: ${this.merge('fontStyle')};
|
||||
text-decoration: ${this.merge('textDecoration')}
|
||||
`
|
||||
}
|
||||
|
||||
// 获取文本样式
|
||||
getTextFontStyle() {
|
||||
return {
|
||||
@@ -120,11 +132,11 @@ class Style {
|
||||
}
|
||||
|
||||
// html文字节点
|
||||
domText(node, fontSizeScale = 1, textLines) {
|
||||
domText(node, fontSizeScale = 1, isMultiLine) {
|
||||
node.style.fontFamily = this.merge('fontFamily')
|
||||
node.style.fontSize = this.merge('fontSize') * fontSizeScale + 'px'
|
||||
node.style.fontWeight = this.merge('fontWeight') || 'normal'
|
||||
node.style.lineHeight = textLines === 1 ? 'normal' : this.merge('lineHeight')
|
||||
node.style.lineHeight = !isMultiLine ? 'normal' : this.merge('lineHeight')
|
||||
node.style.fontStyle = this.merge('fontStyle')
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,8 @@ export default class TextEdit {
|
||||
let lineHeight = node.style.merge('lineHeight')
|
||||
let fontSize = node.style.merge('fontSize')
|
||||
let textLines = (this.cacheEditingText || node.nodeData.data.text).split(/\n/gim)
|
||||
node.style.domText(this.textEditNode, scale, textLines.length)
|
||||
let isMultiLine = node._textData.node.attr('data-ismultiLine') === 'true'
|
||||
node.style.domText(this.textEditNode, scale, isMultiLine)
|
||||
this.textEditNode.style.zIndex = this.mindMap.opt.nodeTextEditZIndex
|
||||
this.textEditNode.innerHTML = textLines.join('<br>')
|
||||
this.textEditNode.style.minWidth = rect.width + 10 + 'px'
|
||||
@@ -119,8 +120,8 @@ export default class TextEdit {
|
||||
this.textEditNode.style.top = rect.top + 'px'
|
||||
this.textEditNode.style.display = 'block'
|
||||
this.textEditNode.style.maxWidth = this.mindMap.opt.textAutoWrapWidth * scale + 'px'
|
||||
if (textLines.length > 1 && lineHeight !== 1) {
|
||||
this.textEditNode.style.transform = `translateY(${-((lineHeight * fontSize - fontSize) / 2 - 2) * scale}px)`
|
||||
if (isMultiLine && lineHeight !== 1) {
|
||||
this.textEditNode.style.transform = `translateY(${-((lineHeight * fontSize - fontSize) / 2) * scale}px)`
|
||||
}
|
||||
this.showTextEdit = true
|
||||
// 选中文本
|
||||
|
||||
@@ -332,4 +332,14 @@ export const checkNodeOuter = (mindMap, node) => {
|
||||
offsetLeft,
|
||||
offsetTop
|
||||
}
|
||||
}
|
||||
|
||||
// 提取html字符串里的纯文本
|
||||
let getTextFromHtmlEl = null
|
||||
export const getTextFromHtml = (html) => {
|
||||
if (!getTextFromHtmlEl) {
|
||||
getTextFromHtmlEl = document.createElement('div')
|
||||
}
|
||||
getTextFromHtmlEl.innerHTML = html
|
||||
return getTextFromHtmlEl.textContent
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { measureText, resizeImgSize } from '../utils'
|
||||
import { measureText, resizeImgSize, getTextFromHtml } from '../utils'
|
||||
import { Image, SVG, A, G, Rect, Text, ForeignObject } from '@svgdotjs/svg.js'
|
||||
import iconsSvg from '../svg/icons'
|
||||
import { CONSTANTS } from './constant'
|
||||
|
||||
// 创建图片节点
|
||||
function createImgNode() {
|
||||
@@ -52,6 +53,12 @@ function createIconNode() {
|
||||
// 创建富文本节点
|
||||
function createRichTextNode() {
|
||||
let g = new G()
|
||||
// 重新设置富文本节点内容
|
||||
if (this.nodeData.data.resetRichText || [CONSTANTS.CHANGE_THEME].includes(this.mindMap.renderer.renderSource)) {
|
||||
delete this.nodeData.data.resetRichText
|
||||
let text = getTextFromHtml(this.nodeData.data.text)
|
||||
this.nodeData.data.text = `<p><span style="${this.style.createStyleText()}">${text}</span></p>`
|
||||
}
|
||||
let html = `<div>${this.nodeData.data.text}</div>`
|
||||
let div = document.createElement('div')
|
||||
div.innerHTML = html
|
||||
@@ -96,6 +103,7 @@ function createTextNode() {
|
||||
let textStyle = this.style.getTextFontStyle()
|
||||
let textArr = this.nodeData.data.text.split(/\n/gim)
|
||||
let maxWidth = this.mindMap.opt.textAutoWrapWidth
|
||||
let isMultiLine = false
|
||||
textArr.forEach((item, index) => {
|
||||
let arr = item.split('')
|
||||
let lines = []
|
||||
@@ -113,6 +121,9 @@ function createTextNode() {
|
||||
if (line.length > 0) {
|
||||
lines.push(line.join(''))
|
||||
}
|
||||
if (lines.length > 1) {
|
||||
isMultiLine = true
|
||||
}
|
||||
textArr[index] = lines.join('\n')
|
||||
})
|
||||
textArr = textArr.join('\n').split(/\n/gim)
|
||||
@@ -127,6 +138,7 @@ function createTextNode() {
|
||||
height = Math.ceil(height)
|
||||
g.attr('data-width', width)
|
||||
g.attr('data-height', height)
|
||||
g.attr('data-ismultiLine', isMultiLine || textArr.length > 1)
|
||||
return {
|
||||
node: g,
|
||||
width,
|
||||
|
||||
@@ -90,7 +90,7 @@ export default {
|
||||
pdfFile: 'pdf file',
|
||||
markdownFile: 'markdown file',
|
||||
tips: 'tips: .smm and .json file can be import',
|
||||
domToImage: 'Whether to convert rich text nodes in svg into pictures',
|
||||
isTransparent: 'Background is transparent',
|
||||
pngTips: 'tips: Exporting pictures in rich text mode is time-consuming. It is recommended to export to svg format',
|
||||
svgTips: 'tips: Exporting pictures in rich text mode is time-consuming',
|
||||
transformingDomToImages: 'Converting nodes: ',
|
||||
|
||||
@@ -90,7 +90,7 @@ export default {
|
||||
pdfFile: 'pdf文件',
|
||||
markdownFile: 'markdown文件',
|
||||
tips: 'tips:.smm和.json文件可用于导入',
|
||||
domToImage: '是否将svg中富文本节点转换成图片',
|
||||
isTransparent: '背景是否透明',
|
||||
pngTips: 'tips:富文本模式导出图片非常耗时,建议导出为svg格式',
|
||||
svgTips: 'tips:富文本模式导出图片非常耗时',
|
||||
transformingDomToImages: '正在转换节点:',
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 0.5.7
|
||||
|
||||
Breaking change:In rich text mode, exporting png has been changed to using html2canvas to convert the entire svg, greatly improving the export speed. However, html2canvas has a bug where the text color inline with the dom node in the foreignObject element cannot be recognized. Therefore, the text color of the exported node is fixed. However, compared to the previously unavailable state of the export, it can at least be exported quickly and smoothly.
|
||||
|
||||
optimization: Optimize the rich text node editing experience.
|
||||
|
||||
New: In rich text mode, importing data, initializing data, and switching theme scene node styles support following theme changes.
|
||||
|
||||
## 0.5.6
|
||||
|
||||
Fix: 1.Fix the issue of node position disorder during fast and multiple renderings in a short period of time. 2.Fix the issue of dragging the canvas while the node is being edited, causing the edit box and node to separate.
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.5.7</h2>
|
||||
<p>Breaking change:In rich text mode, exporting png has been changed to using html2canvas to convert the entire svg, greatly improving the export speed. However, html2canvas has a bug where the text color inline with the dom node in the foreignObject element cannot be recognized. Therefore, the text color of the exported node is fixed. However, compared to the previously unavailable state of the export, it can at least be exported quickly and smoothly.</p>
|
||||
<p>optimization: Optimize the rich text node editing experience.</p>
|
||||
<p>New: In rich text mode, importing data, initializing data, and switching theme scene node styles support following theme changes.</p>
|
||||
<h2>0.5.6</h2>
|
||||
<p>Fix: 1.Fix the issue of node position disorder during fast and multiple renderings in a short period of time. 2.Fix the issue of dragging the canvas while the node is being edited, causing the edit box and node to separate.</p>
|
||||
<p>New: 1.Add a maximum history limit.</p>
|
||||
|
||||
@@ -355,6 +355,18 @@ smm (essentially also json)
|
||||
`fileName`: (v0.1.6+) the name of the exported file, default is `思维导图` (mind
|
||||
map).
|
||||
|
||||
If it is exported as `png`, the fourth parameter can be passed:
|
||||
|
||||
`transparent`: v0.5.7+, `Boolean`, default is `false`, Specify whether the background of the exported image is transparent
|
||||
|
||||
If it is exported as `svg`, the fourth parameter can be passed:
|
||||
|
||||
`plusCssText`: Additional `CSS` style. If there is a `dom` node in `svg`, you can pass in some styles specific to the node through this parameter
|
||||
|
||||
If it is exported as `json` or `smm`, the fourth parameter can be passed:
|
||||
|
||||
`withConfig`: `Boolean`, default is `true`, Specify whether the exported data includes configuration data, otherwise only pure node tree data will be exported
|
||||
|
||||
### toPos(x, y)
|
||||
|
||||
> v0.1.5+
|
||||
|
||||
@@ -814,6 +814,12 @@ smm (essentially also json)</p>
|
||||
<code>false</code></p>
|
||||
<p><code>fileName</code>: (v0.1.6+) the name of the exported file, default is <code>思维导图</code> (mind
|
||||
map).</p>
|
||||
<p>If it is exported as <code>png</code>, the fourth parameter can be passed:</p>
|
||||
<p><code>transparent</code>: v0.5.7+, <code>Boolean</code>, default is <code>false</code>, Specify whether the background of the exported image is transparent</p>
|
||||
<p>If it is exported as <code>svg</code>, the fourth parameter can be passed:</p>
|
||||
<p><code>plusCssText</code>: Additional <code>CSS</code> style. If there is a <code>dom</code> node in <code>svg</code>, you can pass in some styles specific to the node through this parameter</p>
|
||||
<p>If it is exported as <code>json</code> or <code>smm</code>, the fourth parameter can be passed:</p>
|
||||
<p><code>withConfig</code>: <code>Boolean</code>, default is <code>true</code>, Specify whether the exported data includes configuration data, otherwise only pure node tree data will be exported</p>
|
||||
<h3>toPos(x, y)</h3>
|
||||
<blockquote>
|
||||
<p>v0.1.5+</p>
|
||||
|
||||
@@ -15,17 +15,19 @@ After registration and instantiation of `MindMap`, the instance can be obtained
|
||||
|
||||
## Methods
|
||||
|
||||
### png()
|
||||
### png(name, transparent = false)
|
||||
|
||||
- `name`: Name, optional
|
||||
|
||||
- `transparent`: v0.5.7+, Specify whether the background of the exported image is transparent
|
||||
|
||||
Exports as `png`, an async method that returns image data, `data:url` data which
|
||||
can be downloaded or displayed.
|
||||
|
||||
### svg(name, domToImage = false, plusCssText)
|
||||
### svg(name, plusCssText)
|
||||
|
||||
- `name`:`svg` title
|
||||
|
||||
- `domToImage`:v0.4.0+, When node rich text editing is enabled, you can use this parameter to specify whether to convert the `dom` node in the `svg` into a picture
|
||||
|
||||
- `plusCssText`:v0.4.0+, When node rich text editing is enabled and `domToImage` passes `false`, additional `css` styles can be added. If there is a `dom` node in `svg`, you can set some styles for the node through this parameter, such as:
|
||||
|
||||
```js
|
||||
@@ -43,9 +45,7 @@ svg(
|
||||
Exports as `svg`, an async method that returns `svg` data, `data:url` data which
|
||||
can be downloaded or displayed.
|
||||
|
||||
### getSvgData(domToImage)
|
||||
|
||||
- `domToImage`:v0.4.0+, If node rich text is enabled, you can use this parameter to specify whether to convert the `DOM` node embedded in `svg` into a picture.
|
||||
### getSvgData()
|
||||
|
||||
Gets `svg` data, an async method that returns an object:
|
||||
|
||||
@@ -71,4 +71,10 @@ Export as `pdf`
|
||||
|
||||
`withConfig``:Boolean`, default `true`, Whether the data contains configuration, otherwise it is pure mind map node data
|
||||
|
||||
Return `json` data, `data:url` type, you can download it yourself
|
||||
Return `json` data, `data:url` type, you can download it yourself
|
||||
|
||||
### md()
|
||||
|
||||
> v0.4.7+
|
||||
|
||||
Export as `markdown` file, Return `json` data, `data:url` type, you can download it yourself
|
||||
@@ -10,18 +10,23 @@ MindMap.usePlugin(Export)
|
||||
</code></pre>
|
||||
<p>After registration and instantiation of <code>MindMap</code>, the instance can be obtained through <code>mindMap.doExport</code>.</p>
|
||||
<h2>Methods</h2>
|
||||
<h3>png()</h3>
|
||||
<h3>png(name, transparent = false)</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>name</code>: Name, optional</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>transparent</code>: v0.5.7+, Specify whether the background of the exported image is transparent</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Exports as <code>png</code>, an async method that returns image data, <code>data:url</code> data which
|
||||
can be downloaded or displayed.</p>
|
||||
<h3>svg(name, domToImage = false, plusCssText)</h3>
|
||||
<h3>svg(name, plusCssText)</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>name</code>:<code>svg</code> title</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>domToImage</code>:v0.4.0+, When node rich text editing is enabled, you can use this parameter to specify whether to convert the <code>dom</code> node in the <code>svg</code> into a picture</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>plusCssText</code>:v0.4.0+, When node rich text editing is enabled and <code>domToImage</code> passes <code>false</code>, additional <code>css</code> styles can be added. If there is a <code>dom</code> node in <code>svg</code>, you can set some styles for the node through this parameter, such as:</p>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -37,10 +42,7 @@ can be downloaded or displayed.</p>
|
||||
</code></pre>
|
||||
<p>Exports as <code>svg</code>, an async method that returns <code>svg</code> data, <code>data:url</code> data which
|
||||
can be downloaded or displayed.</p>
|
||||
<h3>getSvgData(domToImage)</h3>
|
||||
<ul>
|
||||
<li><code>domToImage</code>:v0.4.0+, If node rich text is enabled, you can use this parameter to specify whether to convert the <code>DOM</code> node embedded in <code>svg</code> into a picture.</li>
|
||||
</ul>
|
||||
<h3>getSvgData()</h3>
|
||||
<p>Gets <code>svg</code> data, an async method that returns an object:</p>
|
||||
<pre class="hljs"><code>{
|
||||
node; <span class="hljs-comment">// svg object</span>
|
||||
@@ -58,6 +60,11 @@ can be downloaded or displayed.</p>
|
||||
<p><code>name</code>:It is temporarily useless, just pass an empty string</p>
|
||||
<p><code>withConfig``:Boolean</code>, default <code>true</code>, Whether the data contains configuration, otherwise it is pure mind map node data</p>
|
||||
<p>Return <code>json</code> data, <code>data:url</code> type, you can download it yourself</p>
|
||||
<h3>md()</h3>
|
||||
<blockquote>
|
||||
<p>v0.4.7+</p>
|
||||
</blockquote>
|
||||
<p>Export as <code>markdown</code> file, Return <code>json</code> data, <code>data:url</code> type, you can download it yourself</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -10,9 +10,11 @@ By default, node editing can only uniformly apply styles to all text in the node
|
||||
|
||||
The principle of this plugin is to use [Quill](https://github.com/quilljs/quill) editor implements rich text editing, and then uses the edited `DOM` node directly as the text data of the node, and embeds the `DOM` node through the `svg` `foreignObject` tag during rendering.
|
||||
|
||||
This also caused a problem, that is, the function of exporting as a picture was affected, The original principle of exporting `svg` as an image is very simple, Get the `svg` string, and then create the `blob` data of the `type=image/svg+xml` type. Then use the `URL.createObjectURL` method to generate the `data:url` data. Then create a `Image` tag, use the `data:url` as the `src` of the image, and finally draw the image on the `canvas` object for export, However, after testing, when the `DOM` node is embedded in the `svg`, this method of export will cause errors, and after trying many ways, the perfect export effect cannot be achieved, The current method is to traverse the `foreignObject` node in `svg`, using [html2canvas](https://github.com/niklasvh/html2canvas) Convert the `DOM` node in the `foreignObject` node into an image and then replace the `foreignObject` node. This method can work, but it is very time-consuming. Because the `html2canvas` conversion takes a long time, it takes about 2 seconds to convert a node. This leads to the more nodes, the slower the conversion time. Therefore, it is recommended not to use this plugin if you cannot tolerate the long time of export.
|
||||
> The following prompts exist in versions prior to v0.5.6:
|
||||
>
|
||||
> This also caused a problem, that is, the function of exporting as a picture was affected, The original principle of exporting `svg` as an image is very simple, Get the `svg` string, and then create the `blob` data of the `type=image/svg+xml` type. Then use the `URL.createObjectURL` method to generate the `data:url` data. Then create a `Image` tag, use the `data:url` as the `src` of the image, and finally draw the image on the `canvas` object for export, However, after testing, when the `DOM` node is embedded in the `svg`, this method of export will cause errors, and after trying many ways, the perfect export effect cannot be achieved, The current method is to traverse the `foreignObject` node in `svg`, using [html2canvas](https://github.com/niklasvh/html2canvas) Convert the `DOM` node in the `foreignObject` node into an image and then replace the `foreignObject` node. This method can work, but it is very time-consuming. Because the `html2canvas` conversion takes a long time, it takes about 2 seconds to convert a node. This leads to the more nodes, the slower the conversion time. Therefore, it is recommended not to use this plugin if you cannot tolerate the long time of export.
|
||||
|
||||
If you have a better way, please leave a message.
|
||||
The version of `v0.5.7+` directly uses `html2canvas` to convert the entire `svg`, which is no longer an issue with speed. However, there is currently a bug where the color of the node does not take effect after export.
|
||||
|
||||
## Register
|
||||
|
||||
|
||||
@@ -10,8 +10,11 @@
|
||||
<p>This plugin provides the ability to edit rich text of nodes, and takes effect after registration.</p>
|
||||
<p>By default, node editing can only uniformly apply styles to all text in the node. This plugin can support rich text editing effects. Currently, it supports bold, italic, underline, strikethrough, font, font size, color, and backgroundColor. Underline and line height are not supported.</p>
|
||||
<p>The principle of this plugin is to use <a href="https://github.com/quilljs/quill">Quill</a> editor implements rich text editing, and then uses the edited <code>DOM</code> node directly as the text data of the node, and embeds the <code>DOM</code> node through the <code>svg</code> <code>foreignObject</code> tag during rendering.</p>
|
||||
<blockquote>
|
||||
<p>The following prompts exist in versions prior to v0.5.6:</p>
|
||||
<p>This also caused a problem, that is, the function of exporting as a picture was affected, The original principle of exporting <code>svg</code> as an image is very simple, Get the <code>svg</code> string, and then create the <code>blob</code> data of the <code>type=image/svg+xml</code> type. Then use the <code>URL.createObjectURL</code> method to generate the <code>data:url</code> data. Then create a <code>Image</code> tag, use the <code>data:url</code> as the <code>src</code> of the image, and finally draw the image on the <code>canvas</code> object for export, However, after testing, when the <code>DOM</code> node is embedded in the <code>svg</code>, this method of export will cause errors, and after trying many ways, the perfect export effect cannot be achieved, The current method is to traverse the <code>foreignObject</code> node in <code>svg</code>, using <a href="https://github.com/niklasvh/html2canvas">html2canvas</a> Convert the <code>DOM</code> node in the <code>foreignObject</code> node into an image and then replace the <code>foreignObject</code> node. This method can work, but it is very time-consuming. Because the <code>html2canvas</code> conversion takes a long time, it takes about 2 seconds to convert a node. This leads to the more nodes, the slower the conversion time. Therefore, it is recommended not to use this plugin if you cannot tolerate the long time of export.</p>
|
||||
<p>If you have a better way, please leave a message.</p>
|
||||
</blockquote>
|
||||
<p>The version of <code>v0.5.7+</code> directly uses <code>html2canvas</code> to convert the entire <code>svg</code>, which is no longer an issue with speed. However, there is currently a bug where the color of the node does not take effect after export.</p>
|
||||
<h2>Register</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> RichText <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/RichText.js'</span>
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 0.5.7
|
||||
|
||||
破坏性更新:富文本模式下导出png改为使用html2canvas转换整个svg,大幅提高导出速度,不过html2canvas存在一个bug,foreignObject元素中的dom节点内联的文字颜色无法识别,所以导出节点的文字颜色是固定的,不过相对于之前的导出基本不可用状态,目前至少能快速顺利的导出。
|
||||
|
||||
优化:优化富文本节点编辑体验。
|
||||
|
||||
新增:富文本模式下,导入数据、初始化数据、切换主题场景节点样式支持跟随主题变化。
|
||||
|
||||
## 0.5.6
|
||||
|
||||
修复:1.修复短时间快速多次渲染时节点位置错乱的问题。 2.修复节点正在编辑中时拖动画布导致编辑框和节点分离的问题。
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Changelog</h1>
|
||||
<h2>0.5.7</h2>
|
||||
<p>破坏性更新:富文本模式下导出png改为使用html2canvas转换整个svg,大幅提高导出速度,不过html2canvas存在一个bug,foreignObject元素中的dom节点内联的文字颜色无法识别,所以导出节点的文字颜色是固定的,不过相对于之前的导出基本不可用状态,目前至少能快速顺利的导出。</p>
|
||||
<p>优化:优化富文本节点编辑体验。</p>
|
||||
<p>新增:富文本模式下,导入数据、初始化数据、切换主题场景节点样式支持跟随主题变化。</p>
|
||||
<h2>0.5.6</h2>
|
||||
<p>修复:1.修复短时间快速多次渲染时节点位置错乱的问题。 2.修复节点正在编辑中时拖动画布导致编辑框和节点分离的问题。</p>
|
||||
<p>新增:1.添加最大历史记录数限制。</p>
|
||||
|
||||
@@ -344,6 +344,18 @@ mindMap.updateConfig({
|
||||
|
||||
`fileName`:(v0.1.6+)导出文件的名称,默认为`思维导图`
|
||||
|
||||
如果是导出为`png`,那么可以传递第四个参数:
|
||||
|
||||
`transparent`:v0.5.7+, `Boolean`,默认为`false`,指定导出图片的背景是否是透明的
|
||||
|
||||
如果是导出为`svg`,那么可以传递第四个参数:
|
||||
|
||||
`plusCssText`:附加的`css`样式,如果`svg`中存在`dom`节点,想要设置一些针对节点的样式可以通过这个参数传入
|
||||
|
||||
如果是导出为`json`或`smm`,那么可以传递第四个参数:
|
||||
|
||||
`withConfig`:`Boolean`,默认为`true`,指定导出的数据中是否包含配置数据,否则只导出纯节点树数据
|
||||
|
||||
### toPos(x, y)
|
||||
|
||||
> v0.1.5+
|
||||
|
||||
@@ -803,6 +803,12 @@ mindMap.setTheme(<span class="hljs-string">'主题名称'</span>)
|
||||
<p><code>type</code>:要导出的类型,可选值:png、svg、json、pdf(v0.2.1+)、smm(本质也是json)</p>
|
||||
<p><code>isDownload</code>:是否需要直接触发下载,布尔值,默认为<code>false</code></p>
|
||||
<p><code>fileName</code>:(v0.1.6+)导出文件的名称,默认为<code>思维导图</code></p>
|
||||
<p>如果是导出为<code>png</code>,那么可以传递第四个参数:</p>
|
||||
<p><code>transparent</code>:v0.5.7+, <code>Boolean</code>,默认为<code>false</code>,指定导出图片的背景是否是透明的</p>
|
||||
<p>如果是导出为<code>svg</code>,那么可以传递第四个参数:</p>
|
||||
<p><code>plusCssText</code>:附加的<code>css</code>样式,如果<code>svg</code>中存在<code>dom</code>节点,想要设置一些针对节点的样式可以通过这个参数传入</p>
|
||||
<p>如果是导出为<code>json</code>或<code>smm</code>,那么可以传递第四个参数:</p>
|
||||
<p><code>withConfig</code>:<code>Boolean</code>,默认为<code>true</code>,指定导出的数据中是否包含配置数据,否则只导出纯节点树数据</p>
|
||||
<h3>toPos(x, y)</h3>
|
||||
<blockquote>
|
||||
<p>v0.1.5+</p>
|
||||
|
||||
@@ -50,19 +50,15 @@ mindMap.export('png', true, '文件名')
|
||||
mindMap.export('pdf', true, '文件名')
|
||||
```
|
||||
|
||||
如果开启了节点富文本编辑,那么导出会非常慢,因为需要挨个转换节点,所以如果导出操作很频繁的话建议关闭节点非文本编辑功能。
|
||||
|
||||
### 导出为svg
|
||||
|
||||
导出为`svg`可以传递的参数如下:
|
||||
|
||||
```js
|
||||
mindMap.export(type, isDownload, fileName, domToImage = false, plusCssText = '')
|
||||
mindMap.export(type, isDownload, fileName, plusCssText = '')
|
||||
```
|
||||
|
||||
如果开启了节点富文本编辑功能,那么可以通过`domToImage`参数控制导出的`svg`中是否保留`html`结构,还是转换成图片形式,同样,如果传了`true`,导出会非常耗时,建议导出为`svg`时`domToImage`传`false`。
|
||||
|
||||
如果`domToImage`传的是`false`,也就是`svg`中会保留节点的`html`结构,这就又存在一个问题,因为浏览器对每个元素默认会设置一些样式,影响最大的就是`margin`和`padding`,这就有可能会导致节点中的文字错位,所以可以通过`plusCssText`参数传入`css`样式:
|
||||
如果开启了节点富文本编辑,也就是`svg`中会存在节点的`html`结构,这就又存在一个问题,因为浏览器对每个元素默认会设置一些样式,影响最大的就是`margin`和`padding`,这就有可能会导致节点中的文字错位,所以可以通过`plusCssText`参数传入`css`样式:
|
||||
|
||||
```js
|
||||
mindMap.export(
|
||||
|
||||
@@ -33,13 +33,11 @@ mindMap.export(<span class="hljs-string">'json'</span>, <span class="h
|
||||
<pre class="hljs"><code>mindMap.export(<span class="hljs-string">'png'</span>, <span class="hljs-literal">true</span>, <span class="hljs-string">'文件名'</span>)
|
||||
mindMap.export(<span class="hljs-string">'pdf'</span>, <span class="hljs-literal">true</span>, <span class="hljs-string">'文件名'</span>)
|
||||
</code></pre>
|
||||
<p>如果开启了节点富文本编辑,那么导出会非常慢,因为需要挨个转换节点,所以如果导出操作很频繁的话建议关闭节点非文本编辑功能。</p>
|
||||
<h3>导出为svg</h3>
|
||||
<p>导出为<code>svg</code>可以传递的参数如下:</p>
|
||||
<pre class="hljs"><code>mindMap.export(type, isDownload, fileName, domToImage = <span class="hljs-literal">false</span>, plusCssText = <span class="hljs-string">''</span>)
|
||||
<pre class="hljs"><code>mindMap.export(type, isDownload, fileName, plusCssText = <span class="hljs-string">''</span>)
|
||||
</code></pre>
|
||||
<p>如果开启了节点富文本编辑功能,那么可以通过<code>domToImage</code>参数控制导出的<code>svg</code>中是否保留<code>html</code>结构,还是转换成图片形式,同样,如果传了<code>true</code>,导出会非常耗时,建议导出为<code>svg</code>时<code>domToImage</code>传<code>false</code>。</p>
|
||||
<p>如果<code>domToImage</code>传的是<code>false</code>,也就是<code>svg</code>中会保留节点的<code>html</code>结构,这就又存在一个问题,因为浏览器对每个元素默认会设置一些样式,影响最大的就是<code>margin</code>和<code>padding</code>,这就有可能会导致节点中的文字错位,所以可以通过<code>plusCssText</code>参数传入<code>css</code>样式:</p>
|
||||
<p>如果开启了节点富文本编辑,也就是<code>svg</code>中会存在节点的<code>html</code>结构,这就又存在一个问题,因为浏览器对每个元素默认会设置一些样式,影响最大的就是<code>margin</code>和<code>padding</code>,这就有可能会导致节点中的文字错位,所以可以通过<code>plusCssText</code>参数传入<code>css</code>样式:</p>
|
||||
<pre class="hljs"><code>mindMap.export(
|
||||
<span class="hljs-string">'svg'</span>,
|
||||
<span class="hljs-literal">true</span>,
|
||||
|
||||
@@ -15,16 +15,18 @@ MindMap.usePlugin(Export)
|
||||
|
||||
## 方法
|
||||
|
||||
### png()
|
||||
### png(name, transparent = false)
|
||||
|
||||
- `name`:名称,可不传
|
||||
|
||||
- `transparent`:v0.5.7+,指定导出图片的背景是否是透明的
|
||||
|
||||
导出为`png`,异步方法,返回图片数据,`data:url`数据,可以自行下载或显示
|
||||
|
||||
### svg(name, domToImage = false, plusCssText)
|
||||
### svg(name, plusCssText)
|
||||
|
||||
- `name`:`svg`标题
|
||||
|
||||
- `domToImage`:v0.4.0+,当开启了节点富文本编辑,可以通过该参数指定是否将`svg`中的`dom`节点转换成图片的形式
|
||||
|
||||
- `plusCssText`:v0.4.0+,当开启了节点富文本编辑,且`domToImage`传了`false`时,可以添加附加的`css`样式,如果`svg`中存在`dom`节点,想要设置一些针对节点的样式可以通过这个参数传入,比如:
|
||||
|
||||
```js
|
||||
@@ -41,9 +43,7 @@ svg(
|
||||
|
||||
导出为`svg`,异步方法,返回`svg`数据,`data:url`数据,可以自行下载或显示
|
||||
|
||||
### getSvgData(domToImage)
|
||||
|
||||
- `domToImage`:v0.4.0+,如果开启了节点富文本,则可以通过该参数指定是否要将`svg`中嵌入的`DOM`节点转换为图片。
|
||||
### getSvgData()
|
||||
|
||||
获取`svg`数据,异步方法,返回一个对象:
|
||||
|
||||
@@ -70,3 +70,9 @@ svg(
|
||||
`withConfig``:Boolean`, 默认为`true`,数据中是否包含配置,否则为纯思维导图节点数据
|
||||
|
||||
返回`json`数据,`data:url`数据,可以自行下载
|
||||
|
||||
### md()
|
||||
|
||||
> v0.4.7+
|
||||
|
||||
导出`markdown`文件,返回`data:url`数据,可以自行下载
|
||||
@@ -10,17 +10,22 @@ MindMap.usePlugin(Export)
|
||||
</code></pre>
|
||||
<p>注册完且实例化<code>MindMap</code>后可通过<code>mindMap.doExport</code>获取到该实例。</p>
|
||||
<h2>方法</h2>
|
||||
<h3>png()</h3>
|
||||
<h3>png(name, transparent = false)</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>name</code>:名称,可不传</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>transparent</code>:v0.5.7+,指定导出图片的背景是否是透明的</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p>导出为<code>png</code>,异步方法,返回图片数据,<code>data:url</code>数据,可以自行下载或显示</p>
|
||||
<h3>svg(name, domToImage = false, plusCssText)</h3>
|
||||
<h3>svg(name, plusCssText)</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<p><code>name</code>:<code>svg</code>标题</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>domToImage</code>:v0.4.0+,当开启了节点富文本编辑,可以通过该参数指定是否将<code>svg</code>中的<code>dom</code>节点转换成图片的形式</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><code>plusCssText</code>:v0.4.0+,当开启了节点富文本编辑,且<code>domToImage</code>传了<code>false</code>时,可以添加附加的<code>css</code>样式,如果<code>svg</code>中存在<code>dom</code>节点,想要设置一些针对节点的样式可以通过这个参数传入,比如:</p>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -35,10 +40,7 @@ MindMap.usePlugin(Export)
|
||||
)
|
||||
</code></pre>
|
||||
<p>导出为<code>svg</code>,异步方法,返回<code>svg</code>数据,<code>data:url</code>数据,可以自行下载或显示</p>
|
||||
<h3>getSvgData(domToImage)</h3>
|
||||
<ul>
|
||||
<li><code>domToImage</code>:v0.4.0+,如果开启了节点富文本,则可以通过该参数指定是否要将<code>svg</code>中嵌入的<code>DOM</code>节点转换为图片。</li>
|
||||
</ul>
|
||||
<h3>getSvgData()</h3>
|
||||
<p>获取<code>svg</code>数据,异步方法,返回一个对象:</p>
|
||||
<pre class="hljs"><code>{
|
||||
node<span class="hljs-comment">// svg对象</span>
|
||||
@@ -56,6 +58,11 @@ MindMap.usePlugin(Export)
|
||||
<p><code>name</code>:暂时没有用处,传空字符串即可</p>
|
||||
<p><code>withConfig``:Boolean</code>, 默认为<code>true</code>,数据中是否包含配置,否则为纯思维导图节点数据</p>
|
||||
<p>返回<code>json</code>数据,<code>data:url</code>数据,可以自行下载</p>
|
||||
<h3>md()</h3>
|
||||
<blockquote>
|
||||
<p>v0.4.7+</p>
|
||||
</blockquote>
|
||||
<p>导出<code>markdown</code>文件,返回<code>data:url</code>数据,可以自行下载</p>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
|
||||
该插件的原理是使用[Quill](https://github.com/quilljs/quill)编辑器实现富文本编辑,然后把编辑后生成的`DOM`节点直接作为节点的文本数据,并且在渲染的时候通过`svg`的`foreignObject`标签嵌入`DOM`节点。
|
||||
|
||||
这样也造成了一个问题,就是导出为图片的功能受到了影响,原本将`svg`导出为图片的原理很简单,获取到`svg`字符串,然后创建为`type=image/svg+xml`类型的`blob`数据,再使用`URL.createObjectURL`方法生成`data:url`数据,再创建一个`Image`标签,将`data:url`作为该图片的`src`,最后再将这个图片绘制到`canvas`对象上进行导出,但是经过测试,当`svg`中嵌入了`DOM`节点,这种方式导出会出错,并且尝试了多种方式后都无法实现完美的导出效果,目前的方式是遍历`svg`中的`foreignObject`节点,使用[html2canvas](https://github.com/niklasvh/html2canvas)将`foreignObject`节点内的`DOM`节点转换为图片再替换掉`foreignObject`节点,这种方式可以工作,但是非常耗时,因为`html2canvas`转换一次的时间很长,导致转换一个节点都需要耗时差不多2秒,这样导致节点越多,转换时间越慢,所以如果无法忍受长时间的导出的话推荐不要使用该插件。
|
||||
> v0.5.6即以前的版本存在以下提示:
|
||||
>
|
||||
> 这样也造成了一个问题,就是导出为图片的功能受到了影响,原本将`svg`导出为图片的原理很简单,获取到`svg`字符串,然后创建为`type=image/svg+xml`类型的`blob`数据,再使用`URL.createObjectURL`方法生成`data:url`数据,再创建一个`Image`标签,将`data:url`作为该图片的`src`,最后再将这个图片绘制到`canvas`对象上进行导出,但是经过测试,当`svg`中嵌入了`DOM`节点,这种方式导出会出错,并且尝试了多种方式后都无法实现完美的导出效果,目前的方式是遍历`svg`中的`foreignObject`节点,使用[html2canvas](https://github.com/niklasvh/html2canvas)将`foreignObject`节点内的`DOM`节点转换为图片再替换掉`foreignObject`节点,这种方式可以工作,但是非常耗时,因为`html2canvas`转换一次的时间很长,导致转换一个节点都需要耗时差不多2秒,这样导致节点越多,转换时间越慢,所以如果无法忍受长时间的导出的话推荐不要使用该插件。
|
||||
|
||||
如果你有更好的方式也欢迎留言。
|
||||
`v0.5.7+`的版本直接使用`html2canvas`转换整个`svg`,速度不再是问题,但是目前存在一个`bug`,就是节点的颜色导出后不生效。
|
||||
|
||||
## 注册
|
||||
|
||||
|
||||
@@ -10,8 +10,11 @@
|
||||
<p>该插件提供节点富文本编辑的能力,注册了即可生效。</p>
|
||||
<p>默认节点编辑只能对节点内所有文本统一应用样式,通过该插件可以支持富文本编辑的效果,目前支持:加粗、斜体、下划线、删除线、字体、字号、颜色、背景颜色。不支持上划线、行高。</p>
|
||||
<p>该插件的原理是使用<a href="https://github.com/quilljs/quill">Quill</a>编辑器实现富文本编辑,然后把编辑后生成的<code>DOM</code>节点直接作为节点的文本数据,并且在渲染的时候通过<code>svg</code>的<code>foreignObject</code>标签嵌入<code>DOM</code>节点。</p>
|
||||
<blockquote>
|
||||
<p>v0.5.6即以前的版本存在以下提示:</p>
|
||||
<p>这样也造成了一个问题,就是导出为图片的功能受到了影响,原本将<code>svg</code>导出为图片的原理很简单,获取到<code>svg</code>字符串,然后创建为<code>type=image/svg+xml</code>类型的<code>blob</code>数据,再使用<code>URL.createObjectURL</code>方法生成<code>data:url</code>数据,再创建一个<code>Image</code>标签,将<code>data:url</code>作为该图片的<code>src</code>,最后再将这个图片绘制到<code>canvas</code>对象上进行导出,但是经过测试,当<code>svg</code>中嵌入了<code>DOM</code>节点,这种方式导出会出错,并且尝试了多种方式后都无法实现完美的导出效果,目前的方式是遍历<code>svg</code>中的<code>foreignObject</code>节点,使用<a href="https://github.com/niklasvh/html2canvas">html2canvas</a>将<code>foreignObject</code>节点内的<code>DOM</code>节点转换为图片再替换掉<code>foreignObject</code>节点,这种方式可以工作,但是非常耗时,因为<code>html2canvas</code>转换一次的时间很长,导致转换一个节点都需要耗时差不多2秒,这样导致节点越多,转换时间越慢,所以如果无法忍受长时间的导出的话推荐不要使用该插件。</p>
|
||||
<p>如果你有更好的方式也欢迎留言。</p>
|
||||
</blockquote>
|
||||
<p><code>v0.5.7+</code>的版本直接使用<code>html2canvas</code>转换整个<code>svg</code>,速度不再是问题,但是目前存在一个<code>bug</code>,就是节点的颜色导出后不生效。</p>
|
||||
<h2>注册</h2>
|
||||
<pre class="hljs"><code><span class="hljs-keyword">import</span> MindMap <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map'</span>
|
||||
<span class="hljs-keyword">import</span> RichText <span class="hljs-keyword">from</span> <span class="hljs-string">'simple-mind-map/src/RichText.js'</span>
|
||||
|
||||
@@ -23,12 +23,6 @@
|
||||
style="margin-left: 12px"
|
||||
>{{ $t('export.include') }}</el-checkbox
|
||||
>
|
||||
<el-checkbox
|
||||
v-show="['svg'].includes(exportType)"
|
||||
v-model="domToImage"
|
||||
style="margin-left: 12px"
|
||||
>{{ $t('export.domToImage') }}</el-checkbox
|
||||
>
|
||||
</div>
|
||||
<div class="paddingInputBox" v-show="['svg', 'png', 'pdf'].includes(exportType)">
|
||||
<span class="name">{{ $t('export.paddingX') }}</span>
|
||||
@@ -45,6 +39,12 @@
|
||||
size="mini"
|
||||
@change="onPaddingChange"
|
||||
></el-input>
|
||||
<el-checkbox
|
||||
v-show="['png'].includes(exportType)"
|
||||
v-model="isTransparent"
|
||||
style="margin-left: 12px"
|
||||
>{{ $t('export.isTransparent') }}</el-checkbox
|
||||
>
|
||||
</div>
|
||||
<div class="downloadTypeList">
|
||||
<div
|
||||
@@ -62,7 +62,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tip">{{ $t('export.tips') }}</div>
|
||||
<div class="tip warning" v-if="openNodeRichText && ['png', 'pdf'].includes(exportType)">{{ $t('export.pngTips') }}</div>
|
||||
<div class="tip warning" v-if="openNodeRichText && exportType === 'svg' && domToImage">{{ $t('export.svgTips') }}</div>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
@@ -91,7 +90,7 @@ export default {
|
||||
exportType: 'smm',
|
||||
fileName: '思维导图',
|
||||
widthConfig: true,
|
||||
domToImage: false,
|
||||
isTransparent: false,
|
||||
loading: false,
|
||||
loadingText: '',
|
||||
paddingX: 10,
|
||||
@@ -111,13 +110,6 @@ export default {
|
||||
this.$bus.$on('showExport', () => {
|
||||
this.dialogVisible = true
|
||||
})
|
||||
this.$bus.$on('transforming-dom-to-images', (index, len) => {
|
||||
this.loading = true
|
||||
this.loadingText = `${this.$t('export.transformingDomToImages')}${index + 1}/${len}`
|
||||
if (index >= len - 1) {
|
||||
this.loading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onPaddingChange() {
|
||||
@@ -148,14 +140,13 @@ export default {
|
||||
this.exportType,
|
||||
true,
|
||||
this.fileName,
|
||||
this.domToImage,
|
||||
`* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}`
|
||||
)
|
||||
} else {
|
||||
} else if (['smm', 'json'].includes(this.exportType)) {
|
||||
this.$bus.$emit(
|
||||
'export',
|
||||
this.exportType,
|
||||
@@ -163,6 +154,21 @@ export default {
|
||||
this.fileName,
|
||||
this.widthConfig
|
||||
)
|
||||
} else if (this.exportType === 'png') {
|
||||
this.$bus.$emit(
|
||||
'export',
|
||||
this.exportType,
|
||||
true,
|
||||
this.fileName,
|
||||
this.isTransparent
|
||||
)
|
||||
} else {
|
||||
this.$bus.$emit(
|
||||
'export',
|
||||
this.exportType,
|
||||
true,
|
||||
this.fileName
|
||||
)
|
||||
}
|
||||
this.$notify.info({
|
||||
title: this.$t('export.notifyTitle'),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Sidebar ref="sidebar" :title="$t('style.title')">
|
||||
<Sidebar ref="sidebar" :title="$t('theme.title')">
|
||||
<div class="themeList">
|
||||
<div
|
||||
class="themeItem"
|
||||
|
||||
Reference in New Issue
Block a user