Add sketch rendering for simple arrows and fix bug where wavy lines do not render when drawn right-to-left [#18]
This commit is contained in:
parent
86e8b89a9c
commit
531b284afa
|
@ -3969,8 +3969,8 @@ define('sequence/components/Connect',[
|
|||
) => {
|
||||
'use strict';
|
||||
|
||||
function drawHorizontalArrowHead(container, {x, y, dx, dy, attrs}) {
|
||||
container.appendChild(svg.make(
|
||||
function drawHorizontalArrowHead({x, y, dx, dy, attrs}) {
|
||||
return svg.make(
|
||||
attrs.fill === 'none' ? 'polyline' : 'polygon',
|
||||
Object.assign({
|
||||
'points': (
|
||||
|
@ -3979,7 +3979,7 @@ define('sequence/components/Connect',[
|
|||
(x + dx) + ' ' + (y + dy)
|
||||
),
|
||||
}, attrs)
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
class Arrowhead {
|
||||
|
@ -4006,15 +4006,16 @@ define('sequence/components/Connect',[
|
|||
}
|
||||
}
|
||||
|
||||
render(layer, theme, {x, y, dir}) {
|
||||
render(layer, theme, pt, dir) {
|
||||
const config = this.getConfig(theme);
|
||||
drawHorizontalArrowHead(layer, {
|
||||
x: x + this.short(theme) * dir,
|
||||
y,
|
||||
const func = config.render || drawHorizontalArrowHead;
|
||||
layer.appendChild(func({
|
||||
x: pt.x + this.short(theme) * dir,
|
||||
y: pt.y,
|
||||
dx: config.width * dir,
|
||||
dy: config.height / 2,
|
||||
attrs: config.attrs,
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
width(theme) {
|
||||
|
@ -4063,19 +4064,21 @@ define('sequence/components/Connect',[
|
|||
];
|
||||
}
|
||||
|
||||
class ConnectingLine {
|
||||
renderFlat(container, {x1, x2, y}, attrs) {
|
||||
function renderFlat({x1, dx1, x2, dx2, y}, attrs) {
|
||||
const ww = attrs['wave-width'];
|
||||
const hh = attrs['wave-height'];
|
||||
|
||||
if(!ww || !hh) {
|
||||
container.appendChild(svg.make('line', Object.assign({
|
||||
'x1': x1,
|
||||
return {
|
||||
shape: svg.make('line', Object.assign({
|
||||
'x1': x1 + dx1,
|
||||
'y1': y,
|
||||
'x2': x2,
|
||||
'x2': x2 + dx2,
|
||||
'y2': y,
|
||||
}, attrs)));
|
||||
return;
|
||||
}, attrs)),
|
||||
p1: {x: x1, y},
|
||||
p2: {x: x2, y},
|
||||
};
|
||||
}
|
||||
|
||||
const heights = makeWavyLineHeights(hh);
|
||||
|
@ -4083,33 +4086,40 @@ define('sequence/components/Connect',[
|
|||
let p = 0;
|
||||
|
||||
let points = '';
|
||||
for(let x = x1; x + dw <= x2; x += dw) {
|
||||
const xL = Math.min(x1 + dx1, x2 + dx2);
|
||||
const xR = Math.max(x1 + dx1, x2 + dx2);
|
||||
for(let x = xL; x + dw <= xR; x += dw) {
|
||||
points += (
|
||||
x + ' ' +
|
||||
(y + heights[(p ++) % heights.length]) + ' '
|
||||
);
|
||||
}
|
||||
points += x2 + ' ' + y;
|
||||
container.appendChild(svg.make('polyline', Object.assign({
|
||||
points,
|
||||
}, attrs)));
|
||||
points += xR + ' ' + y;
|
||||
return {
|
||||
shape: svg.make('polyline', Object.assign({points}, attrs)),
|
||||
p1: {x: x1, y},
|
||||
p2: {x: x2, y},
|
||||
};
|
||||
}
|
||||
|
||||
renderRev(container, {xL1, xL2, y1, y2, xR}, attrs) {
|
||||
function renderRev({xL, dx1, dx2, y1, y2, xR}, attrs) {
|
||||
const r = (y2 - y1) / 2;
|
||||
const ww = attrs['wave-width'];
|
||||
const hh = attrs['wave-height'];
|
||||
|
||||
if(!ww || !hh) {
|
||||
container.appendChild(svg.make('path', Object.assign({
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
'd': (
|
||||
'M' + xL1 + ' ' + y1 +
|
||||
'M' + (xL + dx1) + ' ' + y1 +
|
||||
'L' + xR + ' ' + y1 +
|
||||
'A' + r + ' ' + r + ' 0 0 1 ' + xR + ' ' + y2 +
|
||||
'L' + xL2 + ' ' + y2
|
||||
'L' + (xL + dx2) + ' ' + y2
|
||||
),
|
||||
}, attrs)));
|
||||
return;
|
||||
}, attrs)),
|
||||
p1: {x: xL, y: y1},
|
||||
p2: {x: xL, y: y2},
|
||||
};
|
||||
}
|
||||
|
||||
const heights = makeWavyLineHeights(hh);
|
||||
|
@ -4117,7 +4127,7 @@ define('sequence/components/Connect',[
|
|||
let p = 0;
|
||||
|
||||
let points = '';
|
||||
for(let x = xL1; x + dw <= xR; x += dw) {
|
||||
for(let x = xL + dx1; x + dw <= xR; x += dw) {
|
||||
points += (
|
||||
x + ' ' +
|
||||
(y1 + heights[(p ++) % heights.length]) + ' '
|
||||
|
@ -4133,21 +4143,20 @@ define('sequence/components/Connect',[
|
|||
);
|
||||
}
|
||||
|
||||
for(let x = xR; x - dw >= xL2; x -= dw) {
|
||||
for(let x = xR; x - dw >= xL + dx2; x -= dw) {
|
||||
points += (
|
||||
x + ' ' +
|
||||
(y2 - heights[(p ++) % heights.length]) + ' '
|
||||
);
|
||||
}
|
||||
|
||||
points += xL2 + ' ' + y2;
|
||||
container.appendChild(svg.make('polyline', Object.assign({
|
||||
points,
|
||||
}, attrs)));
|
||||
points += (xL + dx2) + ' ' + y2;
|
||||
return {
|
||||
shape: svg.make('polyline', Object.assign({points}, attrs)),
|
||||
p1: {x: xL, y: y1},
|
||||
p2: {x: xL, y: y2},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const CONNECTING_LINE = new ConnectingLine();
|
||||
|
||||
class Connect extends BaseComponent {
|
||||
separation({label, agentNames, options}, env) {
|
||||
|
@ -4237,17 +4246,19 @@ define('sequence/components/Connect',[
|
|||
const x1 = Math.max(lineX + rArrow.width(env.theme), x0 + labelW);
|
||||
const y1 = y0 + r * 2;
|
||||
|
||||
const lineAttrs = config.lineAttrs[options.line];
|
||||
CONNECTING_LINE.renderRev(env.shapeLayer, {
|
||||
xL1: lineX + lArrow.lineGap(env.theme, lineAttrs),
|
||||
xL2: lineX + rArrow.lineGap(env.theme, lineAttrs),
|
||||
const line = config.line[options.line];
|
||||
const rendered = (line.renderRev || renderRev)({
|
||||
xL: lineX,
|
||||
dx1: lArrow.lineGap(env.theme, line.attrs),
|
||||
dx2: rArrow.lineGap(env.theme, line.attrs),
|
||||
y1: y0,
|
||||
y2: y1,
|
||||
xR: x1,
|
||||
}, lineAttrs);
|
||||
}, line.attrs);
|
||||
env.shapeLayer.appendChild(rendered.shape);
|
||||
|
||||
lArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y0, dir: 1});
|
||||
rArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y1, dir: 1});
|
||||
lArrow.render(env.shapeLayer, env.theme, rendered.p1, 1);
|
||||
rArrow.render(env.shapeLayer, env.theme, rendered.p2, 1);
|
||||
|
||||
const raise = Math.max(height, lArrow.height(env.theme) / 2);
|
||||
const arrowDip = rArrow.height(env.theme) / 2;
|
||||
|
@ -4299,15 +4310,18 @@ define('sequence/components/Connect',[
|
|||
SVGTextBlockClass: env.SVGTextBlockClass,
|
||||
});
|
||||
|
||||
const lineAttrs = config.lineAttrs[options.line];
|
||||
CONNECTING_LINE.renderFlat(env.shapeLayer, {
|
||||
x1: x0 + lArrow.lineGap(env.theme, lineAttrs) * dir,
|
||||
x2: x1 - rArrow.lineGap(env.theme, lineAttrs) * dir,
|
||||
const line = config.line[options.line];
|
||||
const rendered = (line.render || renderFlat)({
|
||||
x1: x0,
|
||||
dx1: lArrow.lineGap(env.theme, line.attrs) * dir,
|
||||
x2: x1,
|
||||
dx2: -rArrow.lineGap(env.theme, line.attrs) * dir,
|
||||
y,
|
||||
}, lineAttrs);
|
||||
}, line.attrs);
|
||||
env.shapeLayer.appendChild(rendered.shape);
|
||||
|
||||
lArrow.render(env.shapeLayer, env.theme, {x: x0, y, dir});
|
||||
rArrow.render(env.shapeLayer, env.theme, {x: x1, y, dir: -dir});
|
||||
lArrow.render(env.shapeLayer, env.theme, rendered.p1, dir);
|
||||
rArrow.render(env.shapeLayer, env.theme, rendered.p2, -dir);
|
||||
|
||||
const arrowSpread = Math.max(
|
||||
lArrow.height(env.theme),
|
||||
|
@ -5344,19 +5358,24 @@ define('sequence/themes/Basic',[
|
|||
|
||||
connect: {
|
||||
loopbackRadius: 6,
|
||||
lineAttrs: {
|
||||
line: {
|
||||
'solid': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
},
|
||||
},
|
||||
'dash': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
'stroke-dasharray': '4, 2',
|
||||
},
|
||||
},
|
||||
'wave': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
|
@ -5366,8 +5385,9 @@ define('sequence/themes/Basic',[
|
|||
'wave-height': 0.5,
|
||||
},
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
single: {
|
||||
'single': {
|
||||
width: 5,
|
||||
height: 10,
|
||||
attrs: {
|
||||
|
@ -5376,7 +5396,7 @@ define('sequence/themes/Basic',[
|
|||
'stroke-linejoin': 'miter',
|
||||
},
|
||||
},
|
||||
double: {
|
||||
'double': {
|
||||
width: 4,
|
||||
height: 6,
|
||||
attrs: {
|
||||
|
@ -5684,19 +5704,24 @@ define('sequence/themes/Chunky',[
|
|||
|
||||
connect: {
|
||||
loopbackRadius: 8,
|
||||
lineAttrs: {
|
||||
line: {
|
||||
'solid': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 3,
|
||||
},
|
||||
},
|
||||
'dash': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 3,
|
||||
'stroke-dasharray': '10, 4',
|
||||
},
|
||||
},
|
||||
'wave': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 3,
|
||||
|
@ -5706,6 +5731,7 @@ define('sequence/themes/Chunky',[
|
|||
'wave-height': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
single: {
|
||||
width: 10,
|
||||
|
@ -6386,7 +6412,6 @@ define('sequence/themes/Sketch',[
|
|||
'use strict';
|
||||
|
||||
// TODO:
|
||||
// * arrows
|
||||
// * fade starter/terminator sometimes does not fully cover line
|
||||
// * blocks (if/else/repeat/ref)
|
||||
|
||||
|
@ -6407,6 +6432,13 @@ define('sequence/themes/Sketch',[
|
|||
return r;
|
||||
}
|
||||
|
||||
const PENCIL = {
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'stroke-linejoin': 'round',
|
||||
'stroke-linecap': 'round',
|
||||
};
|
||||
|
||||
const SETTINGS = {
|
||||
titleMargin: 10,
|
||||
outerMargin: 5,
|
||||
|
@ -6451,47 +6483,50 @@ define('sequence/themes/Sketch',[
|
|||
|
||||
connect: {
|
||||
loopbackRadius: 6,
|
||||
lineAttrs: {
|
||||
line: {
|
||||
'solid': {
|
||||
attrs: Object.assign({
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
renderRev: null,
|
||||
},
|
||||
'dash': {
|
||||
attrs: Object.assign({
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
'stroke-dasharray': '4, 2',
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
renderRev: null,
|
||||
},
|
||||
'wave': {
|
||||
attrs: Object.assign({
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
'stroke-linejoin': 'round',
|
||||
'stroke-linecap': 'round',
|
||||
'wave-width': 6,
|
||||
'wave-height': 0.5,
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
renderRev: null,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
single: {
|
||||
'single': {
|
||||
width: 5,
|
||||
height: 10,
|
||||
attrs: {
|
||||
'fill': '#000000',
|
||||
'stroke-width': 0,
|
||||
'stroke-linejoin': 'miter',
|
||||
},
|
||||
},
|
||||
double: {
|
||||
width: 4,
|
||||
height: 6,
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
'stroke-linejoin': 'miter',
|
||||
attrs: Object.assign({
|
||||
'fill': 'rgba(0,0,0,0.9)',
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
},
|
||||
'double': {
|
||||
width: 4,
|
||||
height: 8,
|
||||
attrs: Object.assign({
|
||||
'fill': 'none',
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
|
@ -6704,6 +6739,10 @@ define('sequence/themes/Sketch',[
|
|||
this.agentCap.cross.render = this.renderCross.bind(this);
|
||||
this.agentCap.bar.render = this.renderBar.bind(this);
|
||||
this.agentCap.box.boxRenderer = this.renderBox.bind(this);
|
||||
this.connect.arrow.single.render = this.renderArrowHead.bind(this);
|
||||
this.connect.arrow.double.render = this.renderArrowHead.bind(this);
|
||||
this.connect.line.solid.render = this.renderConnect.bind(this);
|
||||
this.connect.line.dash.render = this.renderConnect.bind(this);
|
||||
this.notes.note.boxRenderer = this.renderNote.bind(this);
|
||||
this.notes.state.boxRenderer = this.renderState.bind(this);
|
||||
}
|
||||
|
@ -6748,16 +6787,22 @@ define('sequence/themes/Sketch',[
|
|||
return Math.asin(rand * 2 - 1) * 2 * range / Math.PI;
|
||||
}
|
||||
|
||||
lineNodes(p1, p2, {var1 = 1, var2 = 1, move = true}) {
|
||||
lineNodes(p1, p2, {
|
||||
var1 = 1,
|
||||
var2 = 1,
|
||||
varX = 1,
|
||||
varY = 1,
|
||||
move = true,
|
||||
}) {
|
||||
const length = Math.sqrt(
|
||||
(p2.x - p1.x) * (p2.x - p1.x) +
|
||||
(p2.y - p1.y) * (p2.y - p1.y)
|
||||
);
|
||||
const rough = Math.min(Math.sqrt(length) * 0.2, 5);
|
||||
const x1 = p1.x + this.vary(var1 * rough);
|
||||
const y1 = p1.y + this.vary(var1 * rough);
|
||||
const x2 = p2.x + this.vary(var2 * rough);
|
||||
const y2 = p2.y + this.vary(var2 * rough);
|
||||
const x1 = p1.x + this.vary(var1 * varX * rough);
|
||||
const y1 = p1.y + this.vary(var1 * varY * rough);
|
||||
const x2 = p2.x + this.vary(var2 * varX * rough);
|
||||
const y2 = p2.y + this.vary(var2 * varY * rough);
|
||||
|
||||
// -1 = p1 higher, 1 = p2 higher
|
||||
const upper = Math.max(-1, Math.min(1,
|
||||
|
@ -6784,14 +6829,12 @@ define('sequence/themes/Sketch',[
|
|||
};
|
||||
}
|
||||
|
||||
renderLine(p1, p2, {var1 = 1, var2 = 1}) {
|
||||
const line = this.lineNodes(p1, p2, {var1, var2});
|
||||
const shape = svg.make('path', {
|
||||
renderLine(p1, p2, lineOptions) {
|
||||
const line = this.lineNodes(p1, p2, lineOptions);
|
||||
const shape = svg.make('path', Object.assign({
|
||||
'd': line.nodes,
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': 'none',
|
||||
});
|
||||
}, PENCIL));
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
@ -6817,12 +6860,10 @@ define('sequence/themes/Sketch',[
|
|||
{var1: 0, var2: 0.3, move: false}
|
||||
);
|
||||
|
||||
const shape = svg.make('path', {
|
||||
const shape = svg.make('path', Object.assign({
|
||||
'd': lT.nodes + lR.nodes + lB.nodes + lL.nodes,
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': fill || '#FFFFFF',
|
||||
});
|
||||
}, PENCIL));
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
@ -6866,7 +6907,7 @@ define('sequence/themes/Sketch',[
|
|||
);
|
||||
|
||||
const g = svg.make('g');
|
||||
g.appendChild(svg.make('path', {
|
||||
g.appendChild(svg.make('path', Object.assign({
|
||||
'd': (
|
||||
lT.nodes +
|
||||
lF.nodes +
|
||||
|
@ -6874,20 +6915,52 @@ define('sequence/themes/Sketch',[
|
|||
lB.nodes +
|
||||
lL.nodes
|
||||
),
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': '#FFFFFF',
|
||||
}));
|
||||
g.appendChild(svg.make('path', {
|
||||
}, PENCIL)));
|
||||
g.appendChild(svg.make('path', Object.assign({
|
||||
'd': lF1.nodes + lF2.nodes,
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': 'none',
|
||||
}));
|
||||
}, PENCIL)));
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
renderConnect({x1, dx1, x2, dx2, y}, attrs) {
|
||||
const ln = this.lineNodes(
|
||||
{x: x1 + dx1, y},
|
||||
{x: x2 + dx2, y},
|
||||
{varX: 0.3}
|
||||
);
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({'d': ln.nodes}, attrs)),
|
||||
p1: {x: ln.p1.x - dx1, y: ln.p2.y},
|
||||
p2: {x: ln.p2.x - dx2, y: ln.p2.y},
|
||||
};
|
||||
}
|
||||
|
||||
renderArrowHead({x, y, dx, dy, attrs}) {
|
||||
const w = dx * (1 + this.vary(0.2));
|
||||
const h = dy * (1 + this.vary(0.3));
|
||||
const l1 = this.lineNodes(
|
||||
{x: x + w, y: y - h},
|
||||
{x, y},
|
||||
{var1: 2.0, var2: 0.2}
|
||||
);
|
||||
const l2 = this.lineNodes(
|
||||
l1.p2,
|
||||
{x: x + w, y: y + h},
|
||||
{var1: 0, var2: 2.0, move: false}
|
||||
);
|
||||
const l3 = (attrs.fill === 'none') ? {nodes: ''} : this.lineNodes(
|
||||
l2.p2,
|
||||
l1.p1,
|
||||
{var1: 0, var2: 0, move: false}
|
||||
);
|
||||
return svg.make('path', Object.assign({
|
||||
'd': l1.nodes + l2.nodes + l3.nodes,
|
||||
}, attrs));
|
||||
}
|
||||
|
||||
renderState({x, y, width, height}) {
|
||||
// TODO: rounded corners
|
||||
return this.renderBox({x, y, width, height});
|
||||
|
@ -6911,12 +6984,10 @@ define('sequence/themes/Sketch',[
|
|||
{}
|
||||
);
|
||||
|
||||
return svg.make('path', {
|
||||
return svg.make('path', Object.assign({
|
||||
'd': l1.nodes + l2.nodes,
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': 'none',
|
||||
});
|
||||
}, PENCIL));
|
||||
}
|
||||
|
||||
getNote(type) {
|
||||
|
@ -6937,7 +7008,7 @@ define('sequence/themes/Sketch',[
|
|||
const shape = this.renderLine(
|
||||
{x, y: y0},
|
||||
{x, y: y1},
|
||||
{}
|
||||
{varY: 0.3}
|
||||
);
|
||||
shape.setAttribute('class', className);
|
||||
container.appendChild(shape);
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 39 KiB |
|
@ -9,8 +9,8 @@ define([
|
|||
) => {
|
||||
'use strict';
|
||||
|
||||
function drawHorizontalArrowHead(container, {x, y, dx, dy, attrs}) {
|
||||
container.appendChild(svg.make(
|
||||
function drawHorizontalArrowHead({x, y, dx, dy, attrs}) {
|
||||
return svg.make(
|
||||
attrs.fill === 'none' ? 'polyline' : 'polygon',
|
||||
Object.assign({
|
||||
'points': (
|
||||
|
@ -19,7 +19,7 @@ define([
|
|||
(x + dx) + ' ' + (y + dy)
|
||||
),
|
||||
}, attrs)
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
class Arrowhead {
|
||||
|
@ -46,15 +46,16 @@ define([
|
|||
}
|
||||
}
|
||||
|
||||
render(layer, theme, {x, y, dir}) {
|
||||
render(layer, theme, pt, dir) {
|
||||
const config = this.getConfig(theme);
|
||||
drawHorizontalArrowHead(layer, {
|
||||
x: x + this.short(theme) * dir,
|
||||
y,
|
||||
const func = config.render || drawHorizontalArrowHead;
|
||||
layer.appendChild(func({
|
||||
x: pt.x + this.short(theme) * dir,
|
||||
y: pt.y,
|
||||
dx: config.width * dir,
|
||||
dy: config.height / 2,
|
||||
attrs: config.attrs,
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
width(theme) {
|
||||
|
@ -103,19 +104,21 @@ define([
|
|||
];
|
||||
}
|
||||
|
||||
class ConnectingLine {
|
||||
renderFlat(container, {x1, x2, y}, attrs) {
|
||||
function renderFlat({x1, dx1, x2, dx2, y}, attrs) {
|
||||
const ww = attrs['wave-width'];
|
||||
const hh = attrs['wave-height'];
|
||||
|
||||
if(!ww || !hh) {
|
||||
container.appendChild(svg.make('line', Object.assign({
|
||||
'x1': x1,
|
||||
return {
|
||||
shape: svg.make('line', Object.assign({
|
||||
'x1': x1 + dx1,
|
||||
'y1': y,
|
||||
'x2': x2,
|
||||
'x2': x2 + dx2,
|
||||
'y2': y,
|
||||
}, attrs)));
|
||||
return;
|
||||
}, attrs)),
|
||||
p1: {x: x1, y},
|
||||
p2: {x: x2, y},
|
||||
};
|
||||
}
|
||||
|
||||
const heights = makeWavyLineHeights(hh);
|
||||
|
@ -123,33 +126,40 @@ define([
|
|||
let p = 0;
|
||||
|
||||
let points = '';
|
||||
for(let x = x1; x + dw <= x2; x += dw) {
|
||||
const xL = Math.min(x1 + dx1, x2 + dx2);
|
||||
const xR = Math.max(x1 + dx1, x2 + dx2);
|
||||
for(let x = xL; x + dw <= xR; x += dw) {
|
||||
points += (
|
||||
x + ' ' +
|
||||
(y + heights[(p ++) % heights.length]) + ' '
|
||||
);
|
||||
}
|
||||
points += x2 + ' ' + y;
|
||||
container.appendChild(svg.make('polyline', Object.assign({
|
||||
points,
|
||||
}, attrs)));
|
||||
points += xR + ' ' + y;
|
||||
return {
|
||||
shape: svg.make('polyline', Object.assign({points}, attrs)),
|
||||
p1: {x: x1, y},
|
||||
p2: {x: x2, y},
|
||||
};
|
||||
}
|
||||
|
||||
renderRev(container, {xL1, xL2, y1, y2, xR}, attrs) {
|
||||
function renderRev({xL, dx1, dx2, y1, y2, xR}, attrs) {
|
||||
const r = (y2 - y1) / 2;
|
||||
const ww = attrs['wave-width'];
|
||||
const hh = attrs['wave-height'];
|
||||
|
||||
if(!ww || !hh) {
|
||||
container.appendChild(svg.make('path', Object.assign({
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
'd': (
|
||||
'M' + xL1 + ' ' + y1 +
|
||||
'M' + (xL + dx1) + ' ' + y1 +
|
||||
'L' + xR + ' ' + y1 +
|
||||
'A' + r + ' ' + r + ' 0 0 1 ' + xR + ' ' + y2 +
|
||||
'L' + xL2 + ' ' + y2
|
||||
'L' + (xL + dx2) + ' ' + y2
|
||||
),
|
||||
}, attrs)));
|
||||
return;
|
||||
}, attrs)),
|
||||
p1: {x: xL, y: y1},
|
||||
p2: {x: xL, y: y2},
|
||||
};
|
||||
}
|
||||
|
||||
const heights = makeWavyLineHeights(hh);
|
||||
|
@ -157,7 +167,7 @@ define([
|
|||
let p = 0;
|
||||
|
||||
let points = '';
|
||||
for(let x = xL1; x + dw <= xR; x += dw) {
|
||||
for(let x = xL + dx1; x + dw <= xR; x += dw) {
|
||||
points += (
|
||||
x + ' ' +
|
||||
(y1 + heights[(p ++) % heights.length]) + ' '
|
||||
|
@ -173,21 +183,20 @@ define([
|
|||
);
|
||||
}
|
||||
|
||||
for(let x = xR; x - dw >= xL2; x -= dw) {
|
||||
for(let x = xR; x - dw >= xL + dx2; x -= dw) {
|
||||
points += (
|
||||
x + ' ' +
|
||||
(y2 - heights[(p ++) % heights.length]) + ' '
|
||||
);
|
||||
}
|
||||
|
||||
points += xL2 + ' ' + y2;
|
||||
container.appendChild(svg.make('polyline', Object.assign({
|
||||
points,
|
||||
}, attrs)));
|
||||
points += (xL + dx2) + ' ' + y2;
|
||||
return {
|
||||
shape: svg.make('polyline', Object.assign({points}, attrs)),
|
||||
p1: {x: xL, y: y1},
|
||||
p2: {x: xL, y: y2},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const CONNECTING_LINE = new ConnectingLine();
|
||||
|
||||
class Connect extends BaseComponent {
|
||||
separation({label, agentNames, options}, env) {
|
||||
|
@ -277,17 +286,19 @@ define([
|
|||
const x1 = Math.max(lineX + rArrow.width(env.theme), x0 + labelW);
|
||||
const y1 = y0 + r * 2;
|
||||
|
||||
const lineAttrs = config.lineAttrs[options.line];
|
||||
CONNECTING_LINE.renderRev(env.shapeLayer, {
|
||||
xL1: lineX + lArrow.lineGap(env.theme, lineAttrs),
|
||||
xL2: lineX + rArrow.lineGap(env.theme, lineAttrs),
|
||||
const line = config.line[options.line];
|
||||
const rendered = (line.renderRev || renderRev)({
|
||||
xL: lineX,
|
||||
dx1: lArrow.lineGap(env.theme, line.attrs),
|
||||
dx2: rArrow.lineGap(env.theme, line.attrs),
|
||||
y1: y0,
|
||||
y2: y1,
|
||||
xR: x1,
|
||||
}, lineAttrs);
|
||||
}, line.attrs);
|
||||
env.shapeLayer.appendChild(rendered.shape);
|
||||
|
||||
lArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y0, dir: 1});
|
||||
rArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y1, dir: 1});
|
||||
lArrow.render(env.shapeLayer, env.theme, rendered.p1, 1);
|
||||
rArrow.render(env.shapeLayer, env.theme, rendered.p2, 1);
|
||||
|
||||
const raise = Math.max(height, lArrow.height(env.theme) / 2);
|
||||
const arrowDip = rArrow.height(env.theme) / 2;
|
||||
|
@ -339,15 +350,18 @@ define([
|
|||
SVGTextBlockClass: env.SVGTextBlockClass,
|
||||
});
|
||||
|
||||
const lineAttrs = config.lineAttrs[options.line];
|
||||
CONNECTING_LINE.renderFlat(env.shapeLayer, {
|
||||
x1: x0 + lArrow.lineGap(env.theme, lineAttrs) * dir,
|
||||
x2: x1 - rArrow.lineGap(env.theme, lineAttrs) * dir,
|
||||
const line = config.line[options.line];
|
||||
const rendered = (line.render || renderFlat)({
|
||||
x1: x0,
|
||||
dx1: lArrow.lineGap(env.theme, line.attrs) * dir,
|
||||
x2: x1,
|
||||
dx2: -rArrow.lineGap(env.theme, line.attrs) * dir,
|
||||
y,
|
||||
}, lineAttrs);
|
||||
}, line.attrs);
|
||||
env.shapeLayer.appendChild(rendered.shape);
|
||||
|
||||
lArrow.render(env.shapeLayer, env.theme, {x: x0, y, dir});
|
||||
rArrow.render(env.shapeLayer, env.theme, {x: x1, y, dir: -dir});
|
||||
lArrow.render(env.shapeLayer, env.theme, rendered.p1, dir);
|
||||
rArrow.render(env.shapeLayer, env.theme, rendered.p2, -dir);
|
||||
|
||||
const arrowSpread = Math.max(
|
||||
lArrow.height(env.theme),
|
||||
|
|
|
@ -82,19 +82,24 @@ define([
|
|||
|
||||
connect: {
|
||||
loopbackRadius: 6,
|
||||
lineAttrs: {
|
||||
line: {
|
||||
'solid': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
},
|
||||
},
|
||||
'dash': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
'stroke-dasharray': '4, 2',
|
||||
},
|
||||
},
|
||||
'wave': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
|
@ -104,8 +109,9 @@ define([
|
|||
'wave-height': 0.5,
|
||||
},
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
single: {
|
||||
'single': {
|
||||
width: 5,
|
||||
height: 10,
|
||||
attrs: {
|
||||
|
@ -114,7 +120,7 @@ define([
|
|||
'stroke-linejoin': 'miter',
|
||||
},
|
||||
},
|
||||
double: {
|
||||
'double': {
|
||||
width: 4,
|
||||
height: 6,
|
||||
attrs: {
|
||||
|
|
|
@ -89,19 +89,24 @@ define([
|
|||
|
||||
connect: {
|
||||
loopbackRadius: 8,
|
||||
lineAttrs: {
|
||||
line: {
|
||||
'solid': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 3,
|
||||
},
|
||||
},
|
||||
'dash': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 3,
|
||||
'stroke-dasharray': '10, 4',
|
||||
},
|
||||
},
|
||||
'wave': {
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 3,
|
||||
|
@ -111,6 +116,7 @@ define([
|
|||
'wave-height': 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
single: {
|
||||
width: 10,
|
||||
|
|
|
@ -12,7 +12,6 @@ define([
|
|||
'use strict';
|
||||
|
||||
// TODO:
|
||||
// * arrows
|
||||
// * fade starter/terminator sometimes does not fully cover line
|
||||
// * blocks (if/else/repeat/ref)
|
||||
|
||||
|
@ -33,6 +32,13 @@ define([
|
|||
return r;
|
||||
}
|
||||
|
||||
const PENCIL = {
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'stroke-linejoin': 'round',
|
||||
'stroke-linecap': 'round',
|
||||
};
|
||||
|
||||
const SETTINGS = {
|
||||
titleMargin: 10,
|
||||
outerMargin: 5,
|
||||
|
@ -77,47 +83,50 @@ define([
|
|||
|
||||
connect: {
|
||||
loopbackRadius: 6,
|
||||
lineAttrs: {
|
||||
line: {
|
||||
'solid': {
|
||||
attrs: Object.assign({
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
renderRev: null,
|
||||
},
|
||||
'dash': {
|
||||
attrs: Object.assign({
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
'stroke-dasharray': '4, 2',
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
renderRev: null,
|
||||
},
|
||||
'wave': {
|
||||
attrs: Object.assign({
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
'stroke-linejoin': 'round',
|
||||
'stroke-linecap': 'round',
|
||||
'wave-width': 6,
|
||||
'wave-height': 0.5,
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
renderRev: null,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
single: {
|
||||
'single': {
|
||||
width: 5,
|
||||
height: 10,
|
||||
attrs: {
|
||||
'fill': '#000000',
|
||||
'stroke-width': 0,
|
||||
'stroke-linejoin': 'miter',
|
||||
},
|
||||
},
|
||||
double: {
|
||||
width: 4,
|
||||
height: 6,
|
||||
attrs: {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
'stroke-linejoin': 'miter',
|
||||
attrs: Object.assign({
|
||||
'fill': 'rgba(0,0,0,0.9)',
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
},
|
||||
'double': {
|
||||
width: 4,
|
||||
height: 8,
|
||||
attrs: Object.assign({
|
||||
'fill': 'none',
|
||||
}, PENCIL),
|
||||
render: null,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
|
@ -330,6 +339,10 @@ define([
|
|||
this.agentCap.cross.render = this.renderCross.bind(this);
|
||||
this.agentCap.bar.render = this.renderBar.bind(this);
|
||||
this.agentCap.box.boxRenderer = this.renderBox.bind(this);
|
||||
this.connect.arrow.single.render = this.renderArrowHead.bind(this);
|
||||
this.connect.arrow.double.render = this.renderArrowHead.bind(this);
|
||||
this.connect.line.solid.render = this.renderConnect.bind(this);
|
||||
this.connect.line.dash.render = this.renderConnect.bind(this);
|
||||
this.notes.note.boxRenderer = this.renderNote.bind(this);
|
||||
this.notes.state.boxRenderer = this.renderState.bind(this);
|
||||
}
|
||||
|
@ -374,16 +387,22 @@ define([
|
|||
return Math.asin(rand * 2 - 1) * 2 * range / Math.PI;
|
||||
}
|
||||
|
||||
lineNodes(p1, p2, {var1 = 1, var2 = 1, move = true}) {
|
||||
lineNodes(p1, p2, {
|
||||
var1 = 1,
|
||||
var2 = 1,
|
||||
varX = 1,
|
||||
varY = 1,
|
||||
move = true,
|
||||
}) {
|
||||
const length = Math.sqrt(
|
||||
(p2.x - p1.x) * (p2.x - p1.x) +
|
||||
(p2.y - p1.y) * (p2.y - p1.y)
|
||||
);
|
||||
const rough = Math.min(Math.sqrt(length) * 0.2, 5);
|
||||
const x1 = p1.x + this.vary(var1 * rough);
|
||||
const y1 = p1.y + this.vary(var1 * rough);
|
||||
const x2 = p2.x + this.vary(var2 * rough);
|
||||
const y2 = p2.y + this.vary(var2 * rough);
|
||||
const x1 = p1.x + this.vary(var1 * varX * rough);
|
||||
const y1 = p1.y + this.vary(var1 * varY * rough);
|
||||
const x2 = p2.x + this.vary(var2 * varX * rough);
|
||||
const y2 = p2.y + this.vary(var2 * varY * rough);
|
||||
|
||||
// -1 = p1 higher, 1 = p2 higher
|
||||
const upper = Math.max(-1, Math.min(1,
|
||||
|
@ -410,14 +429,12 @@ define([
|
|||
};
|
||||
}
|
||||
|
||||
renderLine(p1, p2, {var1 = 1, var2 = 1}) {
|
||||
const line = this.lineNodes(p1, p2, {var1, var2});
|
||||
const shape = svg.make('path', {
|
||||
renderLine(p1, p2, lineOptions) {
|
||||
const line = this.lineNodes(p1, p2, lineOptions);
|
||||
const shape = svg.make('path', Object.assign({
|
||||
'd': line.nodes,
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': 'none',
|
||||
});
|
||||
}, PENCIL));
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
@ -443,12 +460,10 @@ define([
|
|||
{var1: 0, var2: 0.3, move: false}
|
||||
);
|
||||
|
||||
const shape = svg.make('path', {
|
||||
const shape = svg.make('path', Object.assign({
|
||||
'd': lT.nodes + lR.nodes + lB.nodes + lL.nodes,
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': fill || '#FFFFFF',
|
||||
});
|
||||
}, PENCIL));
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
@ -492,7 +507,7 @@ define([
|
|||
);
|
||||
|
||||
const g = svg.make('g');
|
||||
g.appendChild(svg.make('path', {
|
||||
g.appendChild(svg.make('path', Object.assign({
|
||||
'd': (
|
||||
lT.nodes +
|
||||
lF.nodes +
|
||||
|
@ -500,20 +515,52 @@ define([
|
|||
lB.nodes +
|
||||
lL.nodes
|
||||
),
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': '#FFFFFF',
|
||||
}));
|
||||
g.appendChild(svg.make('path', {
|
||||
}, PENCIL)));
|
||||
g.appendChild(svg.make('path', Object.assign({
|
||||
'd': lF1.nodes + lF2.nodes,
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': 'none',
|
||||
}));
|
||||
}, PENCIL)));
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
renderConnect({x1, dx1, x2, dx2, y}, attrs) {
|
||||
const ln = this.lineNodes(
|
||||
{x: x1 + dx1, y},
|
||||
{x: x2 + dx2, y},
|
||||
{varX: 0.3}
|
||||
);
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({'d': ln.nodes}, attrs)),
|
||||
p1: {x: ln.p1.x - dx1, y: ln.p2.y},
|
||||
p2: {x: ln.p2.x - dx2, y: ln.p2.y},
|
||||
};
|
||||
}
|
||||
|
||||
renderArrowHead({x, y, dx, dy, attrs}) {
|
||||
const w = dx * (1 + this.vary(0.2));
|
||||
const h = dy * (1 + this.vary(0.3));
|
||||
const l1 = this.lineNodes(
|
||||
{x: x + w, y: y - h},
|
||||
{x, y},
|
||||
{var1: 2.0, var2: 0.2}
|
||||
);
|
||||
const l2 = this.lineNodes(
|
||||
l1.p2,
|
||||
{x: x + w, y: y + h},
|
||||
{var1: 0, var2: 2.0, move: false}
|
||||
);
|
||||
const l3 = (attrs.fill === 'none') ? {nodes: ''} : this.lineNodes(
|
||||
l2.p2,
|
||||
l1.p1,
|
||||
{var1: 0, var2: 0, move: false}
|
||||
);
|
||||
return svg.make('path', Object.assign({
|
||||
'd': l1.nodes + l2.nodes + l3.nodes,
|
||||
}, attrs));
|
||||
}
|
||||
|
||||
renderState({x, y, width, height}) {
|
||||
// TODO: rounded corners
|
||||
return this.renderBox({x, y, width, height});
|
||||
|
@ -537,12 +584,10 @@ define([
|
|||
{}
|
||||
);
|
||||
|
||||
return svg.make('path', {
|
||||
return svg.make('path', Object.assign({
|
||||
'd': l1.nodes + l2.nodes,
|
||||
'stroke': 'rgba(0,0,0,0.7)',
|
||||
'stroke-width': 0.8,
|
||||
'fill': 'none',
|
||||
});
|
||||
}, PENCIL));
|
||||
}
|
||||
|
||||
getNote(type) {
|
||||
|
@ -563,7 +608,7 @@ define([
|
|||
const shape = this.renderLine(
|
||||
{x, y: y0},
|
||||
{x, y: y1},
|
||||
{}
|
||||
{varY: 0.3}
|
||||
);
|
||||
shape.setAttribute('class', className);
|
||||
container.appendChild(shape);
|
||||
|
|
Loading…
Reference in New Issue