Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 增加文本自动换行时支持以单词为最小分割单位进行计算 #1093

Open
wants to merge 1 commit into
base: feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions simple-mind-map/src/constants/defaultOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export const defaultOpt = {
*/
// 达到该宽度文本自动换行
textAutoWrapWidth: 500,
// 以单词为最小单位计算自动换行
textAutoWrapBreakWord: false,
// 自定义鼠标滚轮事件处理
// 可以传一个函数,回调参数为事件对象
customHandleMousewheel: null,
Expand Down
71 changes: 54 additions & 17 deletions simple-mind-map/src/core/render/node/nodeCreateContents.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,31 @@ function createRichTextNode(specifyText) {
}
}

function wrapTextByUnit(units, maxWidth, style, joinChar = '') {
const lines = []
let line = []

while (units.length) {
const unit = units.shift()
const text = [...line, unit].join(joinChar)

if (measureText(text, style).width <= maxWidth) {
line.push(unit)
} else {
if (line.length > 0) {
lines.push(line.join(joinChar))
}
line = [unit]
}
}

if (line.length > 0) {
lines.push(line.join(joinChar))
}

return lines
}

// 创建文本节点
function createTextNode(specifyText) {
if (this.getData('needUpdate')) {
Expand All @@ -240,32 +265,42 @@ function createTextNode(specifyText) {
if (!isUndef(text)) {
textArr = String(text).split(/\n/gim)
}
const { textAutoWrapWidth: maxWidth, emptyTextMeasureHeightText } =
this.mindMap.opt

const {
textAutoWrapWidth: maxWidth,
emptyTextMeasureHeightText,
textAutoWrapBreakWord
} = this.mindMap.opt

let isMultiLine = textArr.length > 1

textArr.forEach((item, index) => {
let arr = item.split('')
let lines = []
let line = []
while (arr.length) {
let str = arr.shift()
let text = [...line, str].join('')
if (measureText(text, this.style).width <= maxWidth) {
line.push(str)
} else {
lines.push(line.join(''))
line = [str]
}
}
if (line.length > 0) {
lines.push(line.join(''))
let lines

if (textAutoWrapBreakWord) {
const words = item.split(/\s+/)
lines = wrapTextByUnit(words, maxWidth, this.style, ' ')

lines = lines.flatMap((line) => {
if (measureText(line, this.style).width > maxWidth) {
const chars = line.split('')
return wrapTextByUnit(chars, maxWidth, this.style, '')
}
return [line]
})
} else {
const chars = item.split('')
lines = wrapTextByUnit(chars, maxWidth, this.style, '')
}

if (lines.length > 1) {
isMultiLine = true
}
textArr[index] = lines.join('\n')
})

textArr = textArr.join('\n').replace(/\n$/g, '').split(/\n/gim)

textArr.forEach((item, index) => {
// 避免尾部的空行不占宽度
// 同时解决该问题:https://github.com/wanglin2/mind-map/issues/1037
Expand All @@ -289,11 +324,13 @@ function createTextNode(specifyText) {
const tmpBbox = tmpNode.bbox()
height = tmpBbox.height
}

width = Math.min(Math.ceil(width), maxWidth)
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,
Expand Down