Render self connections and wavy lines in vaguely sketch style [#18]
This commit is contained in:
parent
d1bab06bcc
commit
f24933e5a1
|
@ -3104,7 +3104,130 @@ define('svg/SVGTextBlock',['./SVGUtilities'], (svg) => {
|
|||
return SVGTextBlock;
|
||||
});
|
||||
|
||||
define('svg/SVGShapes',['./SVGUtilities', './SVGTextBlock'], (svg, SVGTextBlock) => {
|
||||
define('svg/PatternedLine',[],() => {
|
||||
'use strict';
|
||||
|
||||
return class PatternedLine {
|
||||
constructor(pattern = null, phase = 0) {
|
||||
this.pattern = pattern;
|
||||
this.dw = pattern && pattern.partWidth;
|
||||
this.points = [];
|
||||
this.phase = phase;
|
||||
this.x = null;
|
||||
this.y = null;
|
||||
this.disconnect = 0;
|
||||
}
|
||||
|
||||
_nextDelta() {
|
||||
return this.pattern.getDelta(this.phase ++);
|
||||
}
|
||||
|
||||
_link() {
|
||||
if(this.disconnect === 2) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cap() {
|
||||
if(this.disconnect > 0) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
move(x, y) {
|
||||
this.cap();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.disconnect = 2;
|
||||
return this;
|
||||
}
|
||||
|
||||
line(x, y) {
|
||||
if(this.pattern) {
|
||||
const len = Math.sqrt(
|
||||
(x - this.x) * (x - this.x) +
|
||||
(y - this.y) * (y - this.y)
|
||||
);
|
||||
const dx1 = (x - this.x) / len;
|
||||
const dy1 = (y - this.y) / len;
|
||||
const dx2 = -dy1;
|
||||
const dy2 = dx1;
|
||||
|
||||
for(let pos = 0; pos + this.dw <= len; pos += this.dw) {
|
||||
const delta = this._nextDelta();
|
||||
this.points.push(
|
||||
(this.x + pos * dx1 + delta * dx2) + ' ' +
|
||||
(this.y + pos * dy1 + delta * dy2)
|
||||
);
|
||||
}
|
||||
this.disconnect = 1;
|
||||
} else {
|
||||
this._link();
|
||||
this.disconnect = 2;
|
||||
}
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
arc(cx, cy, theta) {
|
||||
const radius = Math.sqrt(
|
||||
(cx - this.x) * (cx - this.x) +
|
||||
(cy - this.y) * (cy - this.y)
|
||||
);
|
||||
const theta1 = Math.atan2(cx - this.x, cy - this.y);
|
||||
const nextX = cx + Math.sin(theta1 + theta) * radius;
|
||||
const nextY = cy - Math.cos(theta1 + theta) * radius;
|
||||
|
||||
if(this.pattern) {
|
||||
const dir = (theta < 0 ? 1 : -1);
|
||||
const dt = this.dw / radius;
|
||||
|
||||
for(let t = theta1; t + dt <= theta1 + theta; t += dt) {
|
||||
const delta = this._nextDelta() * dir;
|
||||
this.points.push(
|
||||
(cx + Math.sin(t) * (radius + delta)) + ' ' +
|
||||
(cy - Math.cos(t) * (radius + delta))
|
||||
);
|
||||
}
|
||||
this.disconnect = 1;
|
||||
} else {
|
||||
this.points.push(
|
||||
this.x + ' ' + this.y +
|
||||
'A' + radius + ' ' + radius + ' 0 ' +
|
||||
((theta < 0) ? '0 ' : '1 ') +
|
||||
'1 ' +
|
||||
nextX + ' ' + nextY
|
||||
);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
|
||||
this.x = nextX;
|
||||
this.y = nextY;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
asPath() {
|
||||
this._link();
|
||||
return 'M' + this.points.join('L');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
define('svg/SVGShapes',[
|
||||
'./SVGUtilities',
|
||||
'./SVGTextBlock',
|
||||
'./PatternedLine',
|
||||
], (
|
||||
svg,
|
||||
SVGTextBlock,
|
||||
PatternedLine
|
||||
) => {
|
||||
'use strict';
|
||||
|
||||
function renderBox(attrs, position) {
|
||||
|
@ -3218,6 +3341,7 @@ define('svg/SVGShapes',['./SVGUtilities', './SVGTextBlock'], (svg, SVGTextBlock)
|
|||
renderNote,
|
||||
renderBoxedText,
|
||||
TextBlock: SVGTextBlock,
|
||||
PatternedLine,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -5218,122 +5342,13 @@ define('sequence/Exporter',[],() => {
|
|||
};
|
||||
});
|
||||
|
||||
define('svg/PatternedLine',[],() => {
|
||||
'use strict';
|
||||
|
||||
return class PatternedLine {
|
||||
constructor(pattern = null, phase = 0) {
|
||||
this.pattern = pattern;
|
||||
this.dw = pattern && pattern.partWidth;
|
||||
this.points = [];
|
||||
this.phase = phase;
|
||||
this.x = null;
|
||||
this.y = null;
|
||||
this.disconnect = 0;
|
||||
}
|
||||
|
||||
_nextDelta() {
|
||||
return this.pattern.getDelta(this.phase ++);
|
||||
}
|
||||
|
||||
_link() {
|
||||
if(this.disconnect === 2) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cap() {
|
||||
if(this.disconnect > 0) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
move(x, y) {
|
||||
this.cap();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.disconnect = 2;
|
||||
return this;
|
||||
}
|
||||
|
||||
line(x, y) {
|
||||
if(this.pattern) {
|
||||
const len = Math.sqrt(
|
||||
(x - this.x) * (x - this.x) +
|
||||
(y - this.y) * (y - this.y)
|
||||
);
|
||||
const dx1 = (x - this.x) / len;
|
||||
const dy1 = (y - this.y) / len;
|
||||
const dx2 = -dy1;
|
||||
const dy2 = dx1;
|
||||
|
||||
for(let pos = 0; pos + this.dw <= len; pos += this.dw) {
|
||||
const delta = this._nextDelta();
|
||||
this.points.push(
|
||||
(this.x + pos * dx1 + delta * dx2) + ' ' +
|
||||
(this.y + pos * dy1 + delta * dy2)
|
||||
);
|
||||
}
|
||||
this.disconnect = 1;
|
||||
} else {
|
||||
this._link();
|
||||
this.disconnect = 2;
|
||||
}
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
arc(cx, cy, theta) {
|
||||
const radius = Math.sqrt(
|
||||
(cx - this.x) * (cx - this.x) +
|
||||
(cy - this.y) * (cy - this.y)
|
||||
);
|
||||
const theta1 = Math.atan2(cx - this.x, cy - this.y);
|
||||
const nextX = cx + Math.sin(theta1 + theta) * radius;
|
||||
const nextY = cy - Math.cos(theta1 + theta) * radius;
|
||||
|
||||
if(this.pattern) {
|
||||
const dir = (theta < 0 ? 1 : -1);
|
||||
const dt = this.dw / radius;
|
||||
|
||||
for(let t = theta1; t + dt <= theta1 + theta; t += dt) {
|
||||
const delta = this._nextDelta() * dir;
|
||||
this.points.push(
|
||||
(cx + Math.sin(t) * (radius + delta)) + ' ' +
|
||||
(cy - Math.cos(t) * (radius + delta))
|
||||
);
|
||||
}
|
||||
this.disconnect = 1;
|
||||
} else {
|
||||
this.points.push(
|
||||
this.x + ' ' + this.y +
|
||||
'A' + radius + ' ' + radius + ' 0 ' +
|
||||
((theta < 0) ? '0 ' : '1 ') +
|
||||
'1 ' +
|
||||
nextX + ' ' + nextY
|
||||
);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
|
||||
this.x = nextX;
|
||||
this.y = nextY;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
asPath() {
|
||||
this._link();
|
||||
return 'M' + this.points.join('L');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
define('sequence/themes/BaseTheme',['svg/SVGUtilities', 'svg/PatternedLine'], (svg, PatternedLine) => {
|
||||
define('sequence/themes/BaseTheme',[
|
||||
'svg/SVGUtilities',
|
||||
'svg/SVGShapes',
|
||||
], (
|
||||
svg,
|
||||
SVGShapes
|
||||
) => {
|
||||
'use strict';
|
||||
|
||||
function deepCopy(o) {
|
||||
|
@ -5446,16 +5461,20 @@ define('sequence/themes/BaseTheme',['svg/SVGUtilities', 'svg/PatternedLine'], (s
|
|||
|
||||
BaseTheme.WavePattern = class WavePattern {
|
||||
constructor(width, height) {
|
||||
this.deltas = [
|
||||
0,
|
||||
-height * 2 / 3,
|
||||
-height,
|
||||
-height * 2 / 3,
|
||||
0,
|
||||
height * 2 / 3,
|
||||
height,
|
||||
height * 2 / 3,
|
||||
];
|
||||
if(Array.isArray(height)) {
|
||||
this.deltas = height;
|
||||
} else {
|
||||
this.deltas = [
|
||||
0,
|
||||
-height * 2 / 3,
|
||||
-height,
|
||||
-height * 2 / 3,
|
||||
0,
|
||||
height * 2 / 3,
|
||||
height,
|
||||
height * 2 / 3,
|
||||
];
|
||||
}
|
||||
this.partWidth = width / this.deltas.length;
|
||||
}
|
||||
|
||||
|
@ -5467,7 +5486,7 @@ define('sequence/themes/BaseTheme',['svg/SVGUtilities', 'svg/PatternedLine'], (s
|
|||
BaseTheme.renderFlatConnector = (pattern, attrs, {x1, dx1, x2, dx2, y}) => {
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: new PatternedLine(pattern)
|
||||
d: new SVGShapes.PatternedLine(pattern)
|
||||
.move(x1 + dx1, y)
|
||||
.line(x2 + dx2, y)
|
||||
.cap()
|
||||
|
@ -5485,7 +5504,7 @@ define('sequence/themes/BaseTheme',['svg/SVGUtilities', 'svg/PatternedLine'], (s
|
|||
) => {
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: new PatternedLine(pattern)
|
||||
d: new SVGShapes.PatternedLine(pattern)
|
||||
.move(xL + dx1, y1)
|
||||
.line(xR, y1)
|
||||
.arc(xR, (y1 + y2) / 2, Math.PI)
|
||||
|
@ -6588,8 +6607,6 @@ define('sequence/themes/Sketch',[
|
|||
'stroke-linecap': 'round',
|
||||
};
|
||||
|
||||
const WAVE = new BaseTheme.WavePattern(6, 0.5);
|
||||
|
||||
const SETTINGS = {
|
||||
titleMargin: 10,
|
||||
outerMargin: 5,
|
||||
|
@ -6641,7 +6658,7 @@ define('sequence/themes/Sketch',[
|
|||
'fill': 'none',
|
||||
}, PENCIL),
|
||||
renderFlat: null,
|
||||
renderRev: BaseTheme.renderRevConnector.bind(null, null),
|
||||
renderRev: null,
|
||||
},
|
||||
'dash': {
|
||||
attrs: Object.assign({
|
||||
|
@ -6649,7 +6666,7 @@ define('sequence/themes/Sketch',[
|
|||
'stroke-dasharray': '4, 2',
|
||||
}, PENCIL),
|
||||
renderFlat: null,
|
||||
renderRev: BaseTheme.renderRevConnector.bind(null, null),
|
||||
renderRev: null,
|
||||
},
|
||||
'wave': {
|
||||
attrs: Object.assign({
|
||||
|
@ -6657,8 +6674,8 @@ define('sequence/themes/Sketch',[
|
|||
'stroke-linejoin': 'round',
|
||||
'stroke-linecap': 'round',
|
||||
}, PENCIL),
|
||||
renderFlat: BaseTheme.renderFlatConnector.bind(null, WAVE),
|
||||
renderRev: BaseTheme.renderRevConnector.bind(null, WAVE),
|
||||
renderFlat: null,
|
||||
renderRev: null,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
|
@ -6849,6 +6866,31 @@ define('sequence/themes/Sketch',[
|
|||
const RIGHT = {};
|
||||
const LEFT = {};
|
||||
|
||||
class SketchWavePattern extends BaseTheme.WavePattern {
|
||||
constructor(width, handedness) {
|
||||
const heights = [
|
||||
+0.0,
|
||||
-0.3,
|
||||
-0.6,
|
||||
-0.75,
|
||||
-0.45,
|
||||
+0.0,
|
||||
+0.45,
|
||||
+0.75,
|
||||
+0.6,
|
||||
+0.3,
|
||||
];
|
||||
if(handedness !== RIGHT) {
|
||||
heights.reverse();
|
||||
}
|
||||
super(6, heights);
|
||||
}
|
||||
|
||||
getDelta(p) {
|
||||
return super.getDelta(p) + Math.sin(p * 0.03) * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
class SketchTheme extends BaseTheme {
|
||||
constructor(handedness = RIGHT) {
|
||||
super({
|
||||
|
@ -6866,29 +6908,49 @@ define('sequence/themes/Sketch',[
|
|||
this.handedness = -1;
|
||||
}
|
||||
this.random = new Random();
|
||||
this.wave = new SketchWavePattern(4, handedness);
|
||||
|
||||
this._assignFunctions();
|
||||
this._assignCapFunctions();
|
||||
this._assignConnectFunctions();
|
||||
this._assignNoteFunctions();
|
||||
this._assignBlockFunctions();
|
||||
}
|
||||
|
||||
_assignFunctions() {
|
||||
_assignCapFunctions() {
|
||||
this.renderBar = this.renderBar.bind(this);
|
||||
this.renderBox = this.renderBox.bind(this);
|
||||
this.renderArrowHead = this.renderArrowHead.bind(this);
|
||||
this.renderFlatConnector = this.renderFlatConnector.bind(this);
|
||||
this.renderTag = this.renderTag.bind(this);
|
||||
|
||||
this.agentCap.cross.render = this.renderCross.bind(this);
|
||||
this.agentCap.bar.render = this.renderBar;
|
||||
this.agentCap.box.boxRenderer = this.renderBox;
|
||||
}
|
||||
|
||||
_assignConnectFunctions() {
|
||||
this.renderArrowHead = this.renderArrowHead.bind(this);
|
||||
this.renderFlatConnector = this.renderFlatConnector.bind(this);
|
||||
this.renderRevConnector = this.renderRevConnector.bind(this);
|
||||
|
||||
this.connect.arrow.single.render = this.renderArrowHead;
|
||||
this.connect.arrow.double.render = this.renderArrowHead;
|
||||
|
||||
this.connect.line.solid.renderFlat = this.renderFlatConnector;
|
||||
this.connect.line.solid.renderRev = this.renderRevConnector;
|
||||
this.connect.line.dash.renderFlat = this.renderFlatConnector;
|
||||
this.connect.line.dash.renderRev = this.renderRevConnector;
|
||||
this.connect.line.wave.renderFlat =
|
||||
this.renderFlatConnectorWave.bind(this);
|
||||
this.connect.line.wave.renderRev =
|
||||
this.renderRevConnectorWave.bind(this);
|
||||
}
|
||||
|
||||
_assignNoteFunctions() {
|
||||
this.notes.note.boxRenderer = this.renderNote.bind(this);
|
||||
this.notes.state.boxRenderer = this.renderState.bind(this);
|
||||
}
|
||||
|
||||
_assignBlockFunctions() {
|
||||
this.renderTag = this.renderTag.bind(this);
|
||||
|
||||
this.blocks.ref.boxRenderer = this.renderRefBlock.bind(this);
|
||||
this.blocks[''].boxRenderer = this.renderBlock.bind(this);
|
||||
this.blocks.ref.section.mode.boxRenderer = this.renderTag;
|
||||
|
@ -7088,6 +7150,74 @@ define('sequence/themes/Sketch',[
|
|||
};
|
||||
}
|
||||
|
||||
renderRevConnector(attrs, {xL, dx1, dx2, y1, y2, xR}) {
|
||||
const variance = Math.min((xR - xL) * 0.06, 3);
|
||||
const overshoot = Math.min((xR - xL) * 0.5, 6);
|
||||
const p1x = xL + dx1 + this.vary(variance, -1);
|
||||
const p1y = y1 + this.vary(variance, -1);
|
||||
const b1x = xR - overshoot * this.vary(0.2, 1);
|
||||
const b1y = y1 - this.vary(1, 2);
|
||||
const p2x = xR;
|
||||
const p2y = y1 + this.vary(1, 1);
|
||||
const b2x = xR;
|
||||
const b2y = y2 + this.vary(2);
|
||||
const p3x = xL + dx2 + this.vary(variance, -1);
|
||||
const p3y = y2 + this.vary(variance, -1);
|
||||
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: (
|
||||
'M' + p1x + ' ' + p1y +
|
||||
'C' + p1x + ' ' + p1y +
|
||||
',' + b1x + ' ' + b1y +
|
||||
',' + p2x + ' ' + p2y +
|
||||
'S' + b2x + ' ' + b2y +
|
||||
',' + p3x + ' ' + p3y
|
||||
),
|
||||
}, attrs)),
|
||||
p1: {x: p1x - dx1, y: p1y},
|
||||
p2: {x: p3x - dx2, y: p3y},
|
||||
};
|
||||
}
|
||||
|
||||
renderFlatConnectorWave(attrs, {x1, dx1, x2, dx2, y}) {
|
||||
const x1v = x1 + this.vary(0.3);
|
||||
const x2v = x2 + this.vary(0.3);
|
||||
const y1v = y + this.vary(1);
|
||||
const y2v = y + this.vary(1);
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: new SVGShapes.PatternedLine(this.wave)
|
||||
.move(x1v + dx1, y1v)
|
||||
.line(x2v + dx2, y2v)
|
||||
.cap()
|
||||
.asPath(),
|
||||
}, attrs)),
|
||||
p1: {x: x1v, y: y1v},
|
||||
p2: {x: x2v, y: y2v},
|
||||
};
|
||||
}
|
||||
|
||||
renderRevConnectorWave(attrs, {xL, dx1, dx2, y1, y2, xR}) {
|
||||
const x1v = xL + this.vary(0.3);
|
||||
const x2v = xL + this.vary(0.3);
|
||||
const y1v = y1 + this.vary(1);
|
||||
const y2v = y2 + this.vary(1);
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: new SVGShapes.PatternedLine(this.wave)
|
||||
.move(x1v + dx1, y1v)
|
||||
.line(xR, y1)
|
||||
.arc(xR, (y1 + y2) / 2, Math.PI)
|
||||
.line(x2v + dx2, y2v)
|
||||
.cap()
|
||||
.asPath(),
|
||||
}, attrs)),
|
||||
p1: {x: x1v, y: y1v},
|
||||
p2: {x: x2v, y: y2v},
|
||||
};
|
||||
}
|
||||
|
||||
renderArrowHead(attrs, {x, y, dx, dy}) {
|
||||
const w = dx * this.vary(0.2, 1);
|
||||
const h = dy * this.vary(0.3, 1);
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,10 @@
|
|||
define(['svg/SVGUtilities', 'svg/PatternedLine'], (svg, PatternedLine) => {
|
||||
define([
|
||||
'svg/SVGUtilities',
|
||||
'svg/SVGShapes',
|
||||
], (
|
||||
svg,
|
||||
SVGShapes
|
||||
) => {
|
||||
'use strict';
|
||||
|
||||
function deepCopy(o) {
|
||||
|
@ -111,16 +117,20 @@ define(['svg/SVGUtilities', 'svg/PatternedLine'], (svg, PatternedLine) => {
|
|||
|
||||
BaseTheme.WavePattern = class WavePattern {
|
||||
constructor(width, height) {
|
||||
this.deltas = [
|
||||
0,
|
||||
-height * 2 / 3,
|
||||
-height,
|
||||
-height * 2 / 3,
|
||||
0,
|
||||
height * 2 / 3,
|
||||
height,
|
||||
height * 2 / 3,
|
||||
];
|
||||
if(Array.isArray(height)) {
|
||||
this.deltas = height;
|
||||
} else {
|
||||
this.deltas = [
|
||||
0,
|
||||
-height * 2 / 3,
|
||||
-height,
|
||||
-height * 2 / 3,
|
||||
0,
|
||||
height * 2 / 3,
|
||||
height,
|
||||
height * 2 / 3,
|
||||
];
|
||||
}
|
||||
this.partWidth = width / this.deltas.length;
|
||||
}
|
||||
|
||||
|
@ -132,7 +142,7 @@ define(['svg/SVGUtilities', 'svg/PatternedLine'], (svg, PatternedLine) => {
|
|||
BaseTheme.renderFlatConnector = (pattern, attrs, {x1, dx1, x2, dx2, y}) => {
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: new PatternedLine(pattern)
|
||||
d: new SVGShapes.PatternedLine(pattern)
|
||||
.move(x1 + dx1, y)
|
||||
.line(x2 + dx2, y)
|
||||
.cap()
|
||||
|
@ -150,7 +160,7 @@ define(['svg/SVGUtilities', 'svg/PatternedLine'], (svg, PatternedLine) => {
|
|||
) => {
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: new PatternedLine(pattern)
|
||||
d: new SVGShapes.PatternedLine(pattern)
|
||||
.move(xL + dx1, y1)
|
||||
.line(xR, y1)
|
||||
.arc(xR, (y1 + y2) / 2, Math.PI)
|
||||
|
|
|
@ -30,8 +30,6 @@ define([
|
|||
'stroke-linecap': 'round',
|
||||
};
|
||||
|
||||
const WAVE = new BaseTheme.WavePattern(6, 0.5);
|
||||
|
||||
const SETTINGS = {
|
||||
titleMargin: 10,
|
||||
outerMargin: 5,
|
||||
|
@ -83,7 +81,7 @@ define([
|
|||
'fill': 'none',
|
||||
}, PENCIL),
|
||||
renderFlat: null,
|
||||
renderRev: BaseTheme.renderRevConnector.bind(null, null),
|
||||
renderRev: null,
|
||||
},
|
||||
'dash': {
|
||||
attrs: Object.assign({
|
||||
|
@ -91,7 +89,7 @@ define([
|
|||
'stroke-dasharray': '4, 2',
|
||||
}, PENCIL),
|
||||
renderFlat: null,
|
||||
renderRev: BaseTheme.renderRevConnector.bind(null, null),
|
||||
renderRev: null,
|
||||
},
|
||||
'wave': {
|
||||
attrs: Object.assign({
|
||||
|
@ -99,8 +97,8 @@ define([
|
|||
'stroke-linejoin': 'round',
|
||||
'stroke-linecap': 'round',
|
||||
}, PENCIL),
|
||||
renderFlat: BaseTheme.renderFlatConnector.bind(null, WAVE),
|
||||
renderRev: BaseTheme.renderRevConnector.bind(null, WAVE),
|
||||
renderFlat: null,
|
||||
renderRev: null,
|
||||
},
|
||||
},
|
||||
arrow: {
|
||||
|
@ -291,6 +289,31 @@ define([
|
|||
const RIGHT = {};
|
||||
const LEFT = {};
|
||||
|
||||
class SketchWavePattern extends BaseTheme.WavePattern {
|
||||
constructor(width, handedness) {
|
||||
const heights = [
|
||||
+0.0,
|
||||
-0.3,
|
||||
-0.6,
|
||||
-0.75,
|
||||
-0.45,
|
||||
+0.0,
|
||||
+0.45,
|
||||
+0.75,
|
||||
+0.6,
|
||||
+0.3,
|
||||
];
|
||||
if(handedness !== RIGHT) {
|
||||
heights.reverse();
|
||||
}
|
||||
super(6, heights);
|
||||
}
|
||||
|
||||
getDelta(p) {
|
||||
return super.getDelta(p) + Math.sin(p * 0.03) * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
class SketchTheme extends BaseTheme {
|
||||
constructor(handedness = RIGHT) {
|
||||
super({
|
||||
|
@ -308,29 +331,49 @@ define([
|
|||
this.handedness = -1;
|
||||
}
|
||||
this.random = new Random();
|
||||
this.wave = new SketchWavePattern(4, handedness);
|
||||
|
||||
this._assignFunctions();
|
||||
this._assignCapFunctions();
|
||||
this._assignConnectFunctions();
|
||||
this._assignNoteFunctions();
|
||||
this._assignBlockFunctions();
|
||||
}
|
||||
|
||||
_assignFunctions() {
|
||||
_assignCapFunctions() {
|
||||
this.renderBar = this.renderBar.bind(this);
|
||||
this.renderBox = this.renderBox.bind(this);
|
||||
this.renderArrowHead = this.renderArrowHead.bind(this);
|
||||
this.renderFlatConnector = this.renderFlatConnector.bind(this);
|
||||
this.renderTag = this.renderTag.bind(this);
|
||||
|
||||
this.agentCap.cross.render = this.renderCross.bind(this);
|
||||
this.agentCap.bar.render = this.renderBar;
|
||||
this.agentCap.box.boxRenderer = this.renderBox;
|
||||
}
|
||||
|
||||
_assignConnectFunctions() {
|
||||
this.renderArrowHead = this.renderArrowHead.bind(this);
|
||||
this.renderFlatConnector = this.renderFlatConnector.bind(this);
|
||||
this.renderRevConnector = this.renderRevConnector.bind(this);
|
||||
|
||||
this.connect.arrow.single.render = this.renderArrowHead;
|
||||
this.connect.arrow.double.render = this.renderArrowHead;
|
||||
|
||||
this.connect.line.solid.renderFlat = this.renderFlatConnector;
|
||||
this.connect.line.solid.renderRev = this.renderRevConnector;
|
||||
this.connect.line.dash.renderFlat = this.renderFlatConnector;
|
||||
this.connect.line.dash.renderRev = this.renderRevConnector;
|
||||
this.connect.line.wave.renderFlat =
|
||||
this.renderFlatConnectorWave.bind(this);
|
||||
this.connect.line.wave.renderRev =
|
||||
this.renderRevConnectorWave.bind(this);
|
||||
}
|
||||
|
||||
_assignNoteFunctions() {
|
||||
this.notes.note.boxRenderer = this.renderNote.bind(this);
|
||||
this.notes.state.boxRenderer = this.renderState.bind(this);
|
||||
}
|
||||
|
||||
_assignBlockFunctions() {
|
||||
this.renderTag = this.renderTag.bind(this);
|
||||
|
||||
this.blocks.ref.boxRenderer = this.renderRefBlock.bind(this);
|
||||
this.blocks[''].boxRenderer = this.renderBlock.bind(this);
|
||||
this.blocks.ref.section.mode.boxRenderer = this.renderTag;
|
||||
|
@ -530,6 +573,74 @@ define([
|
|||
};
|
||||
}
|
||||
|
||||
renderRevConnector(attrs, {xL, dx1, dx2, y1, y2, xR}) {
|
||||
const variance = Math.min((xR - xL) * 0.06, 3);
|
||||
const overshoot = Math.min((xR - xL) * 0.5, 6);
|
||||
const p1x = xL + dx1 + this.vary(variance, -1);
|
||||
const p1y = y1 + this.vary(variance, -1);
|
||||
const b1x = xR - overshoot * this.vary(0.2, 1);
|
||||
const b1y = y1 - this.vary(1, 2);
|
||||
const p2x = xR;
|
||||
const p2y = y1 + this.vary(1, 1);
|
||||
const b2x = xR;
|
||||
const b2y = y2 + this.vary(2);
|
||||
const p3x = xL + dx2 + this.vary(variance, -1);
|
||||
const p3y = y2 + this.vary(variance, -1);
|
||||
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: (
|
||||
'M' + p1x + ' ' + p1y +
|
||||
'C' + p1x + ' ' + p1y +
|
||||
',' + b1x + ' ' + b1y +
|
||||
',' + p2x + ' ' + p2y +
|
||||
'S' + b2x + ' ' + b2y +
|
||||
',' + p3x + ' ' + p3y
|
||||
),
|
||||
}, attrs)),
|
||||
p1: {x: p1x - dx1, y: p1y},
|
||||
p2: {x: p3x - dx2, y: p3y},
|
||||
};
|
||||
}
|
||||
|
||||
renderFlatConnectorWave(attrs, {x1, dx1, x2, dx2, y}) {
|
||||
const x1v = x1 + this.vary(0.3);
|
||||
const x2v = x2 + this.vary(0.3);
|
||||
const y1v = y + this.vary(1);
|
||||
const y2v = y + this.vary(1);
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: new SVGShapes.PatternedLine(this.wave)
|
||||
.move(x1v + dx1, y1v)
|
||||
.line(x2v + dx2, y2v)
|
||||
.cap()
|
||||
.asPath(),
|
||||
}, attrs)),
|
||||
p1: {x: x1v, y: y1v},
|
||||
p2: {x: x2v, y: y2v},
|
||||
};
|
||||
}
|
||||
|
||||
renderRevConnectorWave(attrs, {xL, dx1, dx2, y1, y2, xR}) {
|
||||
const x1v = xL + this.vary(0.3);
|
||||
const x2v = xL + this.vary(0.3);
|
||||
const y1v = y1 + this.vary(1);
|
||||
const y2v = y2 + this.vary(1);
|
||||
return {
|
||||
shape: svg.make('path', Object.assign({
|
||||
d: new SVGShapes.PatternedLine(this.wave)
|
||||
.move(x1v + dx1, y1v)
|
||||
.line(xR, y1)
|
||||
.arc(xR, (y1 + y2) / 2, Math.PI)
|
||||
.line(x2v + dx2, y2v)
|
||||
.cap()
|
||||
.asPath(),
|
||||
}, attrs)),
|
||||
p1: {x: x1v, y: y1v},
|
||||
p2: {x: x2v, y: y2v},
|
||||
};
|
||||
}
|
||||
|
||||
renderArrowHead(attrs, {x, y, dx, dy}) {
|
||||
const w = dx * this.vary(0.2, 1);
|
||||
const h = dy * this.vary(0.3, 1);
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
define(['./SVGUtilities', './SVGTextBlock'], (svg, SVGTextBlock) => {
|
||||
define([
|
||||
'./SVGUtilities',
|
||||
'./SVGTextBlock',
|
||||
'./PatternedLine',
|
||||
], (
|
||||
svg,
|
||||
SVGTextBlock,
|
||||
PatternedLine
|
||||
) => {
|
||||
'use strict';
|
||||
|
||||
function renderBox(attrs, position) {
|
||||
|
@ -112,5 +120,6 @@ define(['./SVGUtilities', './SVGTextBlock'], (svg, SVGTextBlock) => {
|
|||
renderNote,
|
||||
renderBoxedText,
|
||||
TextBlock: SVGTextBlock,
|
||||
PatternedLine,
|
||||
};
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue