diff --git a/simple-mind-map/index.js b/simple-mind-map/index.js index e81bdea9..492c2317 100644 --- a/simple-mind-map/index.js +++ b/simple-mind-map/index.js @@ -59,7 +59,9 @@ const defaultOpt = { opacity: 0.5, fontSize: 14 } - } + }, + // 达到该宽度文本自动换行 + textAutoWrapWidth: 500 } // 思维导图 diff --git a/simple-mind-map/package.json b/simple-mind-map/package.json index 927d88af..812c681f 100644 --- a/simple-mind-map/package.json +++ b/simple-mind-map/package.json @@ -1,6 +1,6 @@ { "name": "simple-mind-map", - "version": "0.3.3", + "version": "0.3.4", "description": "一个简单的web在线思维导图", "authors": [ { diff --git a/simple-mind-map/src/Node.js b/simple-mind-map/src/Node.js index 1e6a9cbe..cd322882 100644 --- a/simple-mind-map/src/Node.js +++ b/simple-mind-map/src/Node.js @@ -1,6 +1,6 @@ import Style from './Style' import Shape from './Shape' -import { resizeImgSize, asyncRun } from './utils' +import { resizeImgSize, asyncRun, measureText } from './utils' import { Image, SVG, Circle, A, G, Rect, Text } from '@svgdotjs/svg.js' import btnsSvg from './svg/btns' import iconsSvg from './svg/icons' @@ -376,10 +376,31 @@ class Node { false, this.nodeData.data.isActive ) - this.nodeData.data.text.split(/\n/gim).forEach((item, index) => { + // 文本超长自动换行 + let textStyle = this.style.getTextFontStyle() + let textArr = this.nodeData.data.text.split(/\n/gim) + let maxWidth = this.mindMap.opt.textAutoWrapWidth + textArr.forEach((item, index) => { + let arr = item.split('') + let lines = [] + let line = [] + while(arr.length) { + line.push(arr.shift()) + let text = line.join('') + if (measureText(text, textStyle).width >= maxWidth) { + lines.push(text) + line = [] + } + } + if (line.length > 0) { + lines.push(line.join('')) + } + textArr[index] = lines.join('\n') + }) + textArr = textArr.join('\n').split(/\n/gim) + textArr.forEach((item, index) => { let node = new Text().text(item) this.style.text(node) - console.log(this.isRoot, fontSize, lineHeight, index); node.y(fontSize * lineHeight * index) g.add(node) }) diff --git a/simple-mind-map/src/Style.js b/simple-mind-map/src/Style.js index 97ed9b49..9059876f 100644 --- a/simple-mind-map/src/Style.js +++ b/simple-mind-map/src/Style.js @@ -124,6 +124,16 @@ class Style { }) } + // 获取文本样式 + getTextFontStyle() { + return { + italic: this.merge('fontStyle') === 'italic', + bold: this.merge('fontWeight'), + fontSize: this.merge('fontSize'), + fontFamily: this.merge('fontFamily') + } + } + // html文字节点 domText(node, fontSizeScale = 1) { diff --git a/simple-mind-map/src/TextEdit.js b/simple-mind-map/src/TextEdit.js index 6916bdcc..57bcbda5 100644 --- a/simple-mind-map/src/TextEdit.js +++ b/simple-mind-map/src/TextEdit.js @@ -75,6 +75,7 @@ export default class TextEdit { 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 * this.mindMap.view.scale + 'px' this.showTextEdit = true // 选中文本 this.selectNodeText() diff --git a/simple-mind-map/src/utils/index.js b/simple-mind-map/src/utils/index.js index f69a8543..ce55a50a 100644 --- a/simple-mind-map/src/utils/index.js +++ b/simple-mind-map/src/utils/index.js @@ -235,4 +235,34 @@ export const camelCaseToHyphen = (str) => { return str.replace(/([a-z])([A-Z])/g, (...args) => { return args[1] + '-' + args[2].toLowerCase() }) +} + +//计算节点的文本长宽 +let measureTextContext = null +export const measureText = (text, { italic, bold, fontSize, fontFamily }) => { + const font = joinFontStr({ + italic, + bold, + fontSize, + fontFamily + }) + if (!measureTextContext) { + const canvas = document.createElement('canvas') + measureTextContext = canvas.getContext('2d') + } + measureTextContext.save() + measureTextContext.font = font + const { + width, + actualBoundingBoxAscent, + actualBoundingBoxDescent + } = measureTextContext.measureText(text) + measureTextContext.restore() + const height = actualBoundingBoxAscent + actualBoundingBoxDescent + return { width, height } +} + +// 拼接font字符串 +export const joinFontStr = ({ italic, bold, fontSize, fontFamily }) => { + return `${italic ? 'italic ' : ''} ${bold ? 'bold ' : ''} ${fontSize}px ${fontFamily} ` } \ No newline at end of file diff --git a/web/src/pages/Doc/en/changelog/index.md b/web/src/pages/Doc/en/changelog/index.md index 15507b77..77b61b8d 100644 --- a/web/src/pages/Doc/en/changelog/index.md +++ b/web/src/pages/Doc/en/changelog/index.md @@ -1,5 +1,9 @@ # Changelog +## 0.3.4 + +New:1.Automatic line wrapping function is added to node text. + ## 0.3.3 Fix: The root node text cannot wrap. diff --git a/web/src/pages/Doc/en/changelog/index.vue b/web/src/pages/Doc/en/changelog/index.vue index 9de415dc..37d914a3 100644 --- a/web/src/pages/Doc/en/changelog/index.vue +++ b/web/src/pages/Doc/en/changelog/index.vue @@ -1,6 +1,8 @@