mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
Getting closer
This commit is contained in:
parent
6915634729
commit
fcd2126330
@ -292,9 +292,9 @@ const config = {
|
|||||||
wrap: false,
|
wrap: false,
|
||||||
/**
|
/**
|
||||||
* This sets the auto-wrap padding for the diagram (sides only)
|
* This sets the auto-wrap padding for the diagram (sides only)
|
||||||
* **Default value 15.
|
* **Default value 10.
|
||||||
*/
|
*/
|
||||||
wrapPadding: 15,
|
wrapPadding: 10,
|
||||||
/**
|
/**
|
||||||
* This sets the width of the loop-box (loop, alt, opt, par)
|
* This sets the width of the loop-box (loop, alt, opt, par)
|
||||||
* **Default value 50.
|
* **Default value 50.
|
||||||
@ -306,24 +306,27 @@ const config = {
|
|||||||
*/
|
*/
|
||||||
labelBoxHeight: 20,
|
labelBoxHeight: 20,
|
||||||
messageFont: () => {
|
messageFont: () => {
|
||||||
|
const c = getConfig();
|
||||||
return {
|
return {
|
||||||
fontFamily: config.messageFontFamily,
|
fontFamily: c.messageFontFamily,
|
||||||
fontSize: config.messageFontSize,
|
fontSize: c.messageFontSize,
|
||||||
fontWeight: config.messageFontWeight
|
fontWeight: c.messageFontWeight
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
noteFont: () => {
|
noteFont: () => {
|
||||||
|
const c = getConfig();
|
||||||
return {
|
return {
|
||||||
fontFamily: config.noteFontFamily,
|
fontFamily: c.noteFontFamily,
|
||||||
fontSize: config.noteFontSize,
|
fontSize: c.noteFontSize,
|
||||||
fontWeight: config.noteFontWeight
|
fontWeight: c.noteFontWeight
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
actorFont: () => {
|
actorFont: () => {
|
||||||
|
const c = getConfig();
|
||||||
return {
|
return {
|
||||||
fontFamily: config.actorFontFamily,
|
fontFamily: c.actorFontFamily,
|
||||||
fontSize: config.actorFontSize,
|
fontSize: c.actorFontSize,
|
||||||
fontWeight: config.actorFontWeight
|
fontWeight: c.actorFontWeight
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -136,7 +136,7 @@ export const bounds = {
|
|||||||
},
|
},
|
||||||
newActivation: function(message, diagram, actors) {
|
newActivation: function(message, diagram, actors) {
|
||||||
const actorRect = actors[message.from.actor];
|
const actorRect = actors[message.from.actor];
|
||||||
const stackedSize = actorActivations(message.from.actor).length;
|
const stackedSize = actorActivations(message.from.actor).length || 0;
|
||||||
const x = actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2;
|
const x = actorRect.x + actorRect.width / 2 + ((stackedSize - 1) * conf.activationWidth) / 2;
|
||||||
this.activations.push({
|
this.activations.push({
|
||||||
startx: x,
|
startx: x,
|
||||||
@ -248,13 +248,16 @@ const drawNote = function(elem, noteModel) {
|
|||||||
* @param msgModel - the model containing fields describing a message
|
* @param msgModel - the model containing fields describing a message
|
||||||
*/
|
*/
|
||||||
const drawMessage = function(g, msgModel) {
|
const drawMessage = function(g, msgModel) {
|
||||||
bounds.bumpVerticalPos(conf.messageMargin);
|
const { startx, stopx, starty, message, type, sequenceIndex, wrap } = msgModel;
|
||||||
msgModel.height += conf.messageMargin;
|
const lines = message.split(common.lineBreakRegex).length;
|
||||||
msgModel.starty = bounds.getVerticalPos();
|
let textDims = utils.calculateTextDimensions(message, conf);
|
||||||
const { startx, stopx, starty: verticalPos, message, type, sequenceIndex, wrap } = msgModel;
|
const lineHeight = textDims.height / lines;
|
||||||
|
msgModel.height += lineHeight;
|
||||||
|
|
||||||
|
bounds.bumpVerticalPos(lineHeight);
|
||||||
const textObj = svgDraw.getTextObj();
|
const textObj = svgDraw.getTextObj();
|
||||||
textObj.x = startx;
|
textObj.x = startx;
|
||||||
textObj.y = verticalPos;
|
textObj.y = starty;
|
||||||
textObj.width = stopx - startx;
|
textObj.width = stopx - startx;
|
||||||
textObj.class = 'messageText';
|
textObj.class = 'messageText';
|
||||||
textObj.dy = '1em';
|
textObj.dy = '1em';
|
||||||
@ -268,18 +271,11 @@ const drawMessage = function(g, msgModel) {
|
|||||||
textObj.tspan = false;
|
textObj.tspan = false;
|
||||||
textObj.wrap = wrap;
|
textObj.wrap = wrap;
|
||||||
|
|
||||||
let textElem = drawText(g, textObj);
|
drawText(g, textObj);
|
||||||
const lineHeight = (textElem[0]._groups || textElem[0])[0][0].getBBox().height;
|
|
||||||
textElem.forEach(te => te.attr('y', verticalPos - 7 - lineHeight / 2));
|
|
||||||
|
|
||||||
const lines = message.split(common.lineBreakRegex).length - 1;
|
let totalOffset = textDims.height;
|
||||||
|
|
||||||
let totalOffset = Math.round(lineHeight + lines * lineHeight);
|
let textWidth = textDims.width;
|
||||||
|
|
||||||
let textWidth = Math.max.apply(
|
|
||||||
null,
|
|
||||||
textElem.map(te => (te._groups || te)[0][0].getBBox().width)
|
|
||||||
);
|
|
||||||
|
|
||||||
let line;
|
let line;
|
||||||
if (startx === stopx) {
|
if (startx === stopx) {
|
||||||
@ -288,7 +284,8 @@ const drawMessage = function(g, msgModel) {
|
|||||||
.append('path')
|
.append('path')
|
||||||
.attr(
|
.attr(
|
||||||
'd',
|
'd',
|
||||||
`M ${startx},${verticalPos + totalOffset} H ${startx + conf.width / 2} V ${verticalPos +
|
`M ${startx},${bounds.getVerticalPos() + totalOffset} H ${startx +
|
||||||
|
Math.max(conf.width / 2, textWidth / 2)} V ${bounds.getVerticalPos() +
|
||||||
25 +
|
25 +
|
||||||
totalOffset} H ${startx}`
|
totalOffset} H ${startx}`
|
||||||
);
|
);
|
||||||
@ -302,49 +299,43 @@ const drawMessage = function(g, msgModel) {
|
|||||||
'M ' +
|
'M ' +
|
||||||
startx +
|
startx +
|
||||||
',' +
|
',' +
|
||||||
(verticalPos + totalOffset) +
|
(bounds.getVerticalPos() + totalOffset) +
|
||||||
' C ' +
|
' C ' +
|
||||||
(startx + 60) +
|
(startx + 60) +
|
||||||
',' +
|
',' +
|
||||||
(verticalPos - 10 + totalOffset) +
|
(bounds.getVerticalPos() - 10 + totalOffset) +
|
||||||
' ' +
|
' ' +
|
||||||
(startx + 60) +
|
(startx + 60) +
|
||||||
',' +
|
',' +
|
||||||
(verticalPos + 30 + totalOffset) +
|
(bounds.getVerticalPos() + 30 + totalOffset) +
|
||||||
' ' +
|
' ' +
|
||||||
startx +
|
startx +
|
||||||
',' +
|
',' +
|
||||||
(verticalPos + 20 + totalOffset)
|
(bounds.getVerticalPos() + 20 + totalOffset)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bounds.bumpVerticalPos(30);
|
totalOffset += 30;
|
||||||
msgModel.height += 30;
|
const dx = Math.max(textWidth / 2, conf.width / 2);
|
||||||
const dx = Math.max(textWidth / 2, 100);
|
|
||||||
bounds.insert(
|
bounds.insert(
|
||||||
startx - dx,
|
startx - dx,
|
||||||
bounds.getVerticalPos() - 10 + totalOffset,
|
bounds.getVerticalPos() - 10 + totalOffset,
|
||||||
stopx + dx,
|
stopx + dx,
|
||||||
bounds.getVerticalPos() + 30 + totalOffset
|
bounds.getVerticalPos() + 30 + totalOffset
|
||||||
);
|
);
|
||||||
bounds.bumpVerticalPos(10);
|
|
||||||
msgModel.height += 10;
|
|
||||||
} else {
|
} else {
|
||||||
|
totalOffset += conf.boxMargin;
|
||||||
line = g.append('line');
|
line = g.append('line');
|
||||||
line.attr('x1', startx);
|
line.attr('x1', startx);
|
||||||
line.attr('y1', verticalPos + totalOffset);
|
line.attr('y1', bounds.getVerticalPos() + totalOffset);
|
||||||
line.attr('x2', stopx);
|
line.attr('x2', stopx);
|
||||||
line.attr('y2', verticalPos + totalOffset);
|
line.attr('y2', bounds.getVerticalPos() + totalOffset);
|
||||||
bounds.bumpVerticalPos(10);
|
|
||||||
msgModel.height += 10;
|
|
||||||
bounds.insert(
|
bounds.insert(
|
||||||
startx,
|
startx,
|
||||||
bounds.getVerticalPos() - 10 + totalOffset,
|
bounds.getVerticalPos() - 10 + totalOffset,
|
||||||
stopx,
|
stopx,
|
||||||
bounds.getVerticalPos() + totalOffset
|
bounds.getVerticalPos() + totalOffset
|
||||||
);
|
);
|
||||||
msgModel.height += 10;
|
|
||||||
bounds.bumpVerticalPos(10);
|
|
||||||
}
|
}
|
||||||
// Make an SVG Container
|
// Make an SVG Container
|
||||||
// Draw the line
|
// Draw the line
|
||||||
@ -387,7 +378,7 @@ const drawMessage = function(g, msgModel) {
|
|||||||
line.attr('marker-start', 'url(' + url + '#sequencenumber)');
|
line.attr('marker-start', 'url(' + url + '#sequencenumber)');
|
||||||
g.append('text')
|
g.append('text')
|
||||||
.attr('x', startx)
|
.attr('x', startx)
|
||||||
.attr('y', verticalPos + 4 + totalOffset)
|
.attr('y', bounds.getVerticalPos() + 4 + totalOffset)
|
||||||
.attr('font-family', 'sans-serif')
|
.attr('font-family', 'sans-serif')
|
||||||
.attr('font-size', '12px')
|
.attr('font-size', '12px')
|
||||||
.attr('text-anchor', 'middle')
|
.attr('text-anchor', 'middle')
|
||||||
@ -395,9 +386,10 @@ const drawMessage = function(g, msgModel) {
|
|||||||
.attr('class', 'sequenceNumber')
|
.attr('class', 'sequenceNumber')
|
||||||
.text(sequenceIndex);
|
.text(sequenceIndex);
|
||||||
}
|
}
|
||||||
|
bounds.bumpVerticalPos(totalOffset);
|
||||||
|
msgModel.height += totalOffset;
|
||||||
msgModel.stopy = msgModel.starty + msgModel.height;
|
msgModel.stopy = msgModel.starty + msgModel.height;
|
||||||
bounds.insert(msgModel.fromBounds, msgModel.starty, msgModel.toBounds, msgModel.stopy);
|
bounds.insert(msgModel.fromBounds, msgModel.starty, msgModel.toBounds, msgModel.stopy);
|
||||||
logger.debug(`mm.h:${msgModel.height} vs c.h:${msgModel.stopy - msgModel.starty}`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const drawActors = function(diagram, actors, actorKeys, verticalPos) {
|
export const drawActors = function(diagram, actors, actorKeys, verticalPos) {
|
||||||
@ -472,8 +464,11 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop
|
|||||||
msg.message = utils.wrapLabel(`[${msg.message}]`, loopWidth - 2 * conf.wrapPadding, textConf);
|
msg.message = utils.wrapLabel(`[${msg.message}]`, loopWidth - 2 * conf.wrapPadding, textConf);
|
||||||
msg.width = loopWidth;
|
msg.width = loopWidth;
|
||||||
|
|
||||||
const textHeight = utils.calculateTextHeight(msg.message, textConf);
|
// const lines = msg.message.split(common.lineBreakRegex).length;
|
||||||
heightAdjust += textHeight;
|
const textDims = utils.calculateTextDimensions(msg.message, textConf);
|
||||||
|
const totalOffset = textDims.height - conf.labelBoxHeight;
|
||||||
|
heightAdjust = postMargin + totalOffset;
|
||||||
|
logger.debug(`${totalOffset} - ${msg.message}`);
|
||||||
}
|
}
|
||||||
addLoopFn(msg);
|
addLoopFn(msg);
|
||||||
bounds.bumpVerticalPos(heightAdjust);
|
bounds.bumpVerticalPos(heightAdjust);
|
||||||
@ -488,8 +483,9 @@ export const draw = function(text, id) {
|
|||||||
parser.yy.clear();
|
parser.yy.clear();
|
||||||
parser.yy.setWrap(conf.wrap);
|
parser.yy.setWrap(conf.wrap);
|
||||||
parser.parse(text + '\n');
|
parser.parse(text + '\n');
|
||||||
|
|
||||||
bounds.init();
|
bounds.init();
|
||||||
|
logger.debug(`C:${JSON.stringify(conf, null, 2)}`);
|
||||||
|
|
||||||
const diagram = select(`[id="${id}"]`);
|
const diagram = select(`[id="${id}"]`);
|
||||||
|
|
||||||
// Fetch data from the parsing
|
// Fetch data from the parsing
|
||||||
@ -553,7 +549,7 @@ export const draw = function(text, id) {
|
|||||||
break;
|
break;
|
||||||
case parser.yy.LINETYPE.LOOP_END:
|
case parser.yy.LINETYPE.LOOP_END:
|
||||||
loopModel = bounds.endLoop();
|
loopModel = bounds.endLoop();
|
||||||
svgDraw.drawLoop(diagram, loopModel, 'loop', conf, bounds);
|
svgDraw.drawLoop(diagram, loopModel, 'loop', conf);
|
||||||
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos());
|
||||||
bounds.models.addLoop(loopModel);
|
bounds.models.addLoop(loopModel);
|
||||||
break;
|
break;
|
||||||
@ -635,6 +631,7 @@ export const draw = function(text, id) {
|
|||||||
try {
|
try {
|
||||||
// lastMsg = msg
|
// lastMsg = msg
|
||||||
msgModel = msg.msgModel;
|
msgModel = msg.msgModel;
|
||||||
|
msgModel.starty = bounds.getVerticalPos();
|
||||||
msgModel.sequenceIndex = sequenceIndex;
|
msgModel.sequenceIndex = sequenceIndex;
|
||||||
drawMessage(diagram, msgModel);
|
drawMessage(diagram, msgModel);
|
||||||
bounds.models.addMessage(msgModel);
|
bounds.models.addMessage(msgModel);
|
||||||
@ -706,7 +703,7 @@ export const draw = function(text, id) {
|
|||||||
' ' +
|
' ' +
|
||||||
(height + extraVertForTitle)
|
(height + extraVertForTitle)
|
||||||
);
|
);
|
||||||
logger.debug(`models: ${JSON.stringify(bounds.models, null, 2)}`);
|
logger.debug(`models:`, bounds.models);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -767,6 +764,11 @@ const getMaxMessageWidthPerActor = function(actors, messages) {
|
|||||||
maxMessageWidthPerActor[msg.to] || 0,
|
maxMessageWidthPerActor[msg.to] || 0,
|
||||||
messageWidth
|
messageWidth
|
||||||
);
|
);
|
||||||
|
} else if (isMessage && msg.from === actor.prevActor) {
|
||||||
|
maxMessageWidthPerActor[msg.from] = Math.max(
|
||||||
|
maxMessageWidthPerActor[msg.from] || 0,
|
||||||
|
messageWidth
|
||||||
|
);
|
||||||
} else if (msg.placement === parser.yy.PLACEMENT.RIGHTOF) {
|
} else if (msg.placement === parser.yy.PLACEMENT.RIGHTOF) {
|
||||||
maxMessageWidthPerActor[msg.from] = Math.max(
|
maxMessageWidthPerActor[msg.from] = Math.max(
|
||||||
maxMessageWidthPerActor[msg.from] || 0,
|
maxMessageWidthPerActor[msg.from] || 0,
|
||||||
@ -861,7 +863,6 @@ const buildNoteModel = function(msg, actors) {
|
|||||||
shouldWrap ? utils.wrapLabel(msg.message, conf.width, conf.noteFont()) : msg.message,
|
shouldWrap ? utils.wrapLabel(msg.message, conf.width, conf.noteFont()) : msg.message,
|
||||||
conf.noteFont()
|
conf.noteFont()
|
||||||
);
|
);
|
||||||
logger.debug(`TD:[${textDimensions.width},${textDimensions.height}]`);
|
|
||||||
let noteModel = {
|
let noteModel = {
|
||||||
width: shouldWrap
|
width: shouldWrap
|
||||||
? conf.width
|
? conf.width
|
||||||
@ -892,14 +893,18 @@ const buildNoteModel = function(msg, actors) {
|
|||||||
} else if (msg.to === msg.from) {
|
} else if (msg.to === msg.from) {
|
||||||
textDimensions = utils.calculateTextDimensions(
|
textDimensions = utils.calculateTextDimensions(
|
||||||
shouldWrap
|
shouldWrap
|
||||||
? utils.wrapLabel(msg.message, Math.max(conf.width, actors[msg.to].width), conf.noteFont())
|
? utils.wrapLabel(
|
||||||
|
msg.message,
|
||||||
|
Math.max(conf.width, actors[msg.from].width),
|
||||||
|
conf.noteFont()
|
||||||
|
)
|
||||||
: msg.message,
|
: msg.message,
|
||||||
conf.noteFont()
|
conf.noteFont()
|
||||||
);
|
);
|
||||||
noteModel.width = shouldWrap
|
noteModel.width = shouldWrap
|
||||||
? Math.max(conf.width, actors[msg.to].width)
|
? Math.max(conf.width, actors[msg.from].width)
|
||||||
: Math.max(actors[msg.to].width, conf.width, textDimensions.width + 2 * conf.noteMargin);
|
: Math.max(actors[msg.from].width, conf.width, textDimensions.width + 2 * conf.noteMargin);
|
||||||
noteModel.startx = startx + (actors[msg.to].width - noteModel.width) / 2;
|
noteModel.startx = startx + (actors[msg.from].width - noteModel.width) / 2;
|
||||||
} else {
|
} else {
|
||||||
noteModel.width =
|
noteModel.width =
|
||||||
Math.abs(startx + actors[msg.from].width / 2 - (stopx + actors[msg.to].width / 2)) +
|
Math.abs(startx + actors[msg.from].width / 2 - (stopx + actors[msg.to].width / 2)) +
|
||||||
@ -916,6 +921,9 @@ const buildNoteModel = function(msg, actors) {
|
|||||||
conf.noteFont()
|
conf.noteFont()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
logger.debug(
|
||||||
|
`NM:[${noteModel.startx},${noteModel.stopx},${noteModel.starty},${noteModel.stopy}:${noteModel.width},${noteModel.height}=${msg.message}]`
|
||||||
|
);
|
||||||
return noteModel;
|
return noteModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -957,7 +965,7 @@ const buildMessageModel = function(msg, actors) {
|
|||||||
if (msg.wrap && msg.message && !common.lineBreakRegex.test(msg.message)) {
|
if (msg.wrap && msg.message && !common.lineBreakRegex.test(msg.message)) {
|
||||||
msgModel.message = utils.wrapLabel(
|
msgModel.message = utils.wrapLabel(
|
||||||
msg.message,
|
msg.message,
|
||||||
Math.max(msgModel.width, conf.width),
|
Math.max(msgModel.width - 2 * conf.wrapPadding, conf.width),
|
||||||
conf.messageFont()
|
conf.messageFont()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1028,44 +1036,31 @@ const calculateLoopBounds = function(messages, actors) {
|
|||||||
if (isNote) {
|
if (isNote) {
|
||||||
noteModel = buildNoteModel(msg, actors);
|
noteModel = buildNoteModel(msg, actors);
|
||||||
msg.noteModel = noteModel;
|
msg.noteModel = noteModel;
|
||||||
let depth = 0;
|
|
||||||
stack.forEach(stk => {
|
stack.forEach(stk => {
|
||||||
current = stk;
|
current = stk;
|
||||||
current.from = Math.min(current.from, noteModel.startx);
|
current.from = Math.min(current.from, noteModel.startx);
|
||||||
current.to = Math.max(current.to, noteModel.startx + noteModel.width);
|
current.to = Math.max(current.to, noteModel.startx + noteModel.width);
|
||||||
current.width =
|
current.width =
|
||||||
Math.max(current.width, Math.abs(current.from - current.to)) -
|
Math.max(current.width, Math.abs(current.from - current.to)) - conf.labelBoxWidth;
|
||||||
50 -
|
|
||||||
conf.boxMargin * depth;
|
|
||||||
depth++;
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
msgModel = buildMessageModel(msg, actors);
|
msgModel = buildMessageModel(msg, actors);
|
||||||
msg.msgModel = msgModel;
|
msg.msgModel = msgModel;
|
||||||
if (msg.from && msg.to && stack.length > 0) {
|
if (msgModel.startx && msgModel.stopx && stack.length > 0) {
|
||||||
let depth = 0;
|
|
||||||
stack.forEach(stk => {
|
stack.forEach(stk => {
|
||||||
current = stk;
|
current = stk;
|
||||||
let from = actors[msg.from];
|
if (msgModel.startx === msgModel.stopx) {
|
||||||
let to = actors[msg.to];
|
let from = actors[msg.from];
|
||||||
if (from.x === to.x) {
|
let to = actors[msg.to];
|
||||||
current.from = Math.min(current.from, from.x);
|
current.from = Math.min(from.x - from.width / 2, current.from);
|
||||||
current.to = Math.max(current.to, to.x);
|
current.to = Math.max(to.x + from.width / 2, current.to);
|
||||||
current.width = Math.max(current.width, from.width) - 50 - conf.boxMargin * depth;
|
|
||||||
} else {
|
|
||||||
if (from.x < to.x) {
|
|
||||||
current.from = Math.min(current.from, from.x);
|
|
||||||
current.to = Math.max(current.to, to.x);
|
|
||||||
} else {
|
|
||||||
current.from = Math.min(current.from, to.x);
|
|
||||||
current.to = Math.max(current.to, from.x);
|
|
||||||
}
|
|
||||||
current.width =
|
current.width =
|
||||||
Math.max(current.width, Math.abs(current.from - current.to)) -
|
Math.max(current.width, Math.abs(current.to - current.from)) - conf.labelBoxWidth;
|
||||||
50 -
|
} else {
|
||||||
conf.boxMargin * depth;
|
current.from = Math.min(msgModel.startx, current.from);
|
||||||
|
current.to = Math.max(msgModel.stopx, current.to);
|
||||||
|
current.width = Math.max(current.width, msgModel.width) - conf.labelBoxWidth;
|
||||||
}
|
}
|
||||||
depth++;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import common from '../common/common';
|
import common from '../common/common';
|
||||||
|
import utils from '../../utils';
|
||||||
|
import { logger } from '../../logger';
|
||||||
|
|
||||||
export const drawRect = function(elem, rectData) {
|
export const drawRect = function(elem, rectData) {
|
||||||
const rectElem = elem.append('rect');
|
const rectElem = elem.append('rect');
|
||||||
@ -36,18 +38,21 @@ export const drawText = function(elem, textData) {
|
|||||||
switch (textData.valign) {
|
switch (textData.valign) {
|
||||||
case 'top':
|
case 'top':
|
||||||
case 'start':
|
case 'start':
|
||||||
yfunc = () => textData.y + textData.textMargin;
|
yfunc = () => Math.round(textData.y + textData.textMargin);
|
||||||
break;
|
break;
|
||||||
case 'middle':
|
case 'middle':
|
||||||
case 'center':
|
case 'center':
|
||||||
yfunc = () => textData.y + (prevTextHeight + textHeight + textData.textMargin) / 2;
|
yfunc = () =>
|
||||||
|
Math.round(textData.y + (prevTextHeight + textHeight + textData.textMargin) / 2);
|
||||||
break;
|
break;
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
case 'end':
|
case 'end':
|
||||||
yfunc = () =>
|
yfunc = () =>
|
||||||
textData.y +
|
Math.round(
|
||||||
(prevTextHeight + textHeight + 2 * textData.textMargin) -
|
textData.y +
|
||||||
textData.textMargin;
|
(prevTextHeight + textHeight + 2 * textData.textMargin) -
|
||||||
|
textData.textMargin
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,21 +64,21 @@ export const drawText = function(elem, textData) {
|
|||||||
switch (textData.anchor) {
|
switch (textData.anchor) {
|
||||||
case 'left':
|
case 'left':
|
||||||
case 'start':
|
case 'start':
|
||||||
textData.x = textData.x + textData.textMargin;
|
textData.x = Math.round(textData.x + textData.textMargin);
|
||||||
textData.anchor = 'start';
|
textData.anchor = 'start';
|
||||||
textData.dominantBaseline = 'text-after-edge';
|
textData.dominantBaseline = 'text-after-edge';
|
||||||
textData.alignmentBaseline = 'middle';
|
textData.alignmentBaseline = 'middle';
|
||||||
break;
|
break;
|
||||||
case 'middle':
|
case 'middle':
|
||||||
case 'center':
|
case 'center':
|
||||||
textData.x = textData.x + textData.width / 2;
|
textData.x = Math.round(textData.x + textData.width / 2);
|
||||||
textData.anchor = 'middle';
|
textData.anchor = 'middle';
|
||||||
textData.dominantBaseline = 'middle';
|
textData.dominantBaseline = 'middle';
|
||||||
textData.alignmentBaseline = 'middle';
|
textData.alignmentBaseline = 'middle';
|
||||||
break;
|
break;
|
||||||
case 'right':
|
case 'right':
|
||||||
case 'end':
|
case 'end':
|
||||||
textData.x = textData.x + textData.width - textData.textMargin;
|
textData.x = Math.round(textData.x + textData.width - textData.textMargin);
|
||||||
textData.anchor = 'end';
|
textData.anchor = 'end';
|
||||||
textData.dominantBaseline = 'text-before-edge';
|
textData.dominantBaseline = 'text-before-edge';
|
||||||
textData.alignmentBaseline = 'middle';
|
textData.alignmentBaseline = 'middle';
|
||||||
@ -256,6 +261,15 @@ export const drawActivation = function(elem, bounds, verticalPos, conf, actorAct
|
|||||||
* @param conf - diagrom configuration
|
* @param conf - diagrom configuration
|
||||||
*/
|
*/
|
||||||
export const drawLoop = function(elem, loopModel, labelText, conf) {
|
export const drawLoop = function(elem, loopModel, labelText, conf) {
|
||||||
|
const {
|
||||||
|
boxMargin,
|
||||||
|
boxTextMargin,
|
||||||
|
labelBoxHeight,
|
||||||
|
labelBoxWidth,
|
||||||
|
messageFontFamily: fontFamily,
|
||||||
|
messageFontSize: fontSize,
|
||||||
|
messageFontWeight: fontWeight
|
||||||
|
} = conf;
|
||||||
const g = elem.append('g');
|
const g = elem.append('g');
|
||||||
const drawLoopLine = function(startx, starty, stopx, stopy) {
|
const drawLoopLine = function(startx, starty, stopx, stopy) {
|
||||||
return g
|
return g
|
||||||
@ -283,45 +297,51 @@ export const drawLoop = function(elem, loopModel, labelText, conf) {
|
|||||||
txt.text = labelText;
|
txt.text = labelText;
|
||||||
txt.x = loopModel.startx;
|
txt.x = loopModel.startx;
|
||||||
txt.y = loopModel.starty;
|
txt.y = loopModel.starty;
|
||||||
const msgFont = conf.messageFont();
|
txt.fontFamily = fontFamily;
|
||||||
txt.fontFamily = msgFont.fontFamily;
|
txt.fontSize = fontSize;
|
||||||
txt.fontSize = msgFont.fontSize;
|
txt.fontWeight = fontWeight;
|
||||||
txt.fontWeight = msgFont.fontWeight;
|
|
||||||
txt.anchor = 'middle';
|
txt.anchor = 'middle';
|
||||||
txt.valign = 'middle';
|
txt.valign = 'middle';
|
||||||
txt.tspan = false;
|
txt.tspan = false;
|
||||||
txt.width = conf.labelBoxWidth || 50;
|
txt.width = labelBoxWidth || 50;
|
||||||
txt.height = conf.labelBoxHeight || 20;
|
txt.height = labelBoxHeight || 20;
|
||||||
txt.textMargin = conf.boxTextMargin;
|
txt.textMargin = boxTextMargin;
|
||||||
txt.class = 'labelText';
|
txt.class = 'labelText';
|
||||||
|
|
||||||
drawLabel(g, txt);
|
drawLabel(g, txt);
|
||||||
txt = getTextObj();
|
txt = getTextObj();
|
||||||
txt.text = loopModel.title;
|
txt.text = loopModel.title;
|
||||||
txt.x = loopModel.startx + conf.labelBoxWidth / 2 + (loopModel.stopx - loopModel.startx) / 2;
|
txt.x = loopModel.startx + labelBoxWidth / 2 + (loopModel.stopx - loopModel.startx) / 2;
|
||||||
txt.y = loopModel.starty + conf.boxMargin + conf.boxTextMargin;
|
txt.y = loopModel.starty + boxMargin + boxTextMargin;
|
||||||
txt.anchor = 'middle';
|
txt.anchor = 'middle';
|
||||||
|
txt.valign = 'middle';
|
||||||
|
txt.textMargin = boxTextMargin;
|
||||||
txt.class = 'loopText';
|
txt.class = 'loopText';
|
||||||
txt.fontFamily = msgFont.fontFamily;
|
txt.fontFamily = fontFamily;
|
||||||
txt.fontSize = msgFont.fontSize;
|
txt.fontSize = fontSize;
|
||||||
txt.fontWeight = msgFont.fontWeight;
|
txt.fontWeight = fontWeight;
|
||||||
txt.wrap = true;
|
txt.wrap = true;
|
||||||
|
|
||||||
let textElem = drawText(g, txt);
|
let textElem = drawText(g, txt);
|
||||||
|
let textHeight = Math.round(
|
||||||
|
textElem.map(te => (te._groups || te)[0][0].getBBox().height).reduce((acc, curr) => acc + curr)
|
||||||
|
);
|
||||||
|
const textDims = utils.calculateTextDimensions(txt.text, txt);
|
||||||
|
logger.debug(`loop: ${textHeight} vs ${textDims.height} ${txt.text}`, textDims);
|
||||||
|
|
||||||
if (typeof loopModel.sectionTitles !== 'undefined') {
|
if (typeof loopModel.sectionTitles !== 'undefined') {
|
||||||
loopModel.sectionTitles.forEach(function(item, idx) {
|
loopModel.sectionTitles.forEach(function(item, idx) {
|
||||||
if (item.message) {
|
if (item.message) {
|
||||||
txt.text = item.message;
|
txt.text = item.message;
|
||||||
txt.x = loopModel.startx + (loopModel.stopx - loopModel.startx) / 2;
|
txt.x = loopModel.startx + (loopModel.stopx - loopModel.startx) / 2;
|
||||||
txt.y = loopModel.sections[idx].y + conf.boxMargin + conf.boxTextMargin;
|
txt.y = loopModel.sections[idx].y + boxMargin + boxTextMargin;
|
||||||
txt.class = 'loopText';
|
txt.class = 'loopText';
|
||||||
txt.anchor = 'middle';
|
txt.anchor = 'middle';
|
||||||
txt.valign = 'middle';
|
txt.valign = 'middle';
|
||||||
txt.tspan = false;
|
txt.tspan = false;
|
||||||
txt.fontFamily = msgFont.fontFamily;
|
txt.fontFamily = fontFamily;
|
||||||
txt.fontSize = msgFont.fontSize;
|
txt.fontSize = fontSize;
|
||||||
txt.fontWeight = msgFont.fontWeight;
|
txt.fontWeight = fontWeight;
|
||||||
txt.wrap = loopModel.wrap;
|
txt.wrap = loopModel.wrap;
|
||||||
textElem = drawText(g, txt);
|
textElem = drawText(g, txt);
|
||||||
let sectionHeight = Math.round(
|
let sectionHeight = Math.round(
|
||||||
@ -329,7 +349,7 @@ export const drawLoop = function(elem, loopModel, labelText, conf) {
|
|||||||
.map(te => (te._groups || te)[0][0].getBBox().height)
|
.map(te => (te._groups || te)[0][0].getBBox().height)
|
||||||
.reduce((acc, curr) => acc + curr)
|
.reduce((acc, curr) => acc + curr)
|
||||||
);
|
);
|
||||||
loopModel.sections[idx].height += sectionHeight - (conf.boxMargin + conf.boxTextMargin);
|
loopModel.sections[idx].height += sectionHeight - (boxMargin + boxTextMargin);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
30
src/utils.js
30
src/utils.js
@ -627,21 +627,21 @@ export const calculateTextDimensions = function(text, config) {
|
|||||||
// of sans-serif.
|
// of sans-serif.
|
||||||
const fontFamilies = ['sans-serif', fontFamily];
|
const fontFamilies = ['sans-serif', fontFamily];
|
||||||
const lines = text.split(common.lineBreakRegex);
|
const lines = text.split(common.lineBreakRegex);
|
||||||
let maxWidth = 0,
|
let dims = [];
|
||||||
height = 0;
|
|
||||||
|
|
||||||
const body = select('body');
|
const body = select('body');
|
||||||
// We don't want to leak DOM elements - if a removal operation isn't available
|
// We don't want to leak DOM elements - if a removal operation isn't available
|
||||||
// for any reason, do not continue.
|
// for any reason, do not continue.
|
||||||
if (!body.remove) {
|
if (!body.remove) {
|
||||||
return { width: 0, height: 0 };
|
return { width: 0, height: 0, lineHeight: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
const g = body.append('svg');
|
const g = body.append('svg');
|
||||||
|
|
||||||
for (let line of lines) {
|
for (let fontFamily of fontFamilies) {
|
||||||
let cheight = 0;
|
let cheight = 0;
|
||||||
for (let fontFamily of fontFamilies) {
|
let dim = { width: 0, height: 0, lineHeight: 0 };
|
||||||
|
for (let line of lines) {
|
||||||
const textObj = getTextObj();
|
const textObj = getTextObj();
|
||||||
textObj.text = line;
|
textObj.text = line;
|
||||||
const textElem = drawSimpleText(g, textObj)
|
const textElem = drawSimpleText(g, textObj)
|
||||||
@ -650,16 +650,26 @@ export const calculateTextDimensions = function(text, config) {
|
|||||||
.style('font-family', fontFamily);
|
.style('font-family', fontFamily);
|
||||||
|
|
||||||
let bBox = (textElem._groups || textElem)[0][0].getBBox();
|
let bBox = (textElem._groups || textElem)[0][0].getBBox();
|
||||||
maxWidth = Math.max(maxWidth, bBox.width);
|
dim.width = Math.round(Math.max(dim.width, bBox.width));
|
||||||
cheight = Math.max(bBox.height, cheight);
|
cheight = Math.round(bBox.height);
|
||||||
|
dim.height += cheight;
|
||||||
|
dim.lineHeight = Math.round(Math.max(dim.lineHeight, cheight));
|
||||||
}
|
}
|
||||||
height += cheight;
|
dims.push(dim);
|
||||||
}
|
}
|
||||||
|
|
||||||
g.remove();
|
g.remove();
|
||||||
|
|
||||||
// Adds some padding, so the text won't sit exactly within the actor's borders
|
let index =
|
||||||
const result = { width: Math.round(maxWidth), height: Math.round(height) };
|
isNaN(dims[1].height) ||
|
||||||
|
isNaN(dims[1].width) ||
|
||||||
|
isNaN(dims[1].lineHeight) ||
|
||||||
|
(dims[0].height > dims[1].height &&
|
||||||
|
dims[0].width > dims[1].width &&
|
||||||
|
dims[0].lineHeight > dims[1].lineHeight)
|
||||||
|
? 0
|
||||||
|
: 1;
|
||||||
|
const result = dims[index];
|
||||||
calculateTextDimensions[cacheKey] = result;
|
calculateTextDimensions[cacheKey] = result;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user