mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
#6097 Next shapes, learn-right and card
This commit is contained in:
parent
3c93e4640a
commit
8336d1cf2d
102
cypress/platform/shape-tester.html
Normal file
102
cypress/platform/shape-tester.html
Normal file
@ -0,0 +1,102 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Arial';
|
||||
background-color: #333;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="diagram"></div>
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||
mermaid.registerLayoutLoaders(layouts);
|
||||
mermaid.parseError = function (err, hash) {
|
||||
console.error('Mermaid error: ', err);
|
||||
};
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
//look: 'handdrawn',
|
||||
// layout: 'fixed',
|
||||
theme: 'dark',
|
||||
//layout: 'elk',
|
||||
fontFamily: 'Kalam',
|
||||
logLevel: 1,
|
||||
});
|
||||
|
||||
let shape = 'card';
|
||||
// let simplified = true;
|
||||
let simplified = false;
|
||||
let algorithm = 'elk';
|
||||
// let algorithm = 'dagre';
|
||||
let code = `---
|
||||
config:
|
||||
layout: ${algorithm}
|
||||
---
|
||||
flowchart TD
|
||||
A["Abrakadabra"] --> C["C"] & D["I am a circle"] & n4["Untitled Node"]
|
||||
D@{ shape: diamond}
|
||||
B["Bombrakadombra"] --> D & C & D
|
||||
C --> E["E"] & B
|
||||
D --> E & A
|
||||
n4 --> C
|
||||
A@{ shape: ${shape}}
|
||||
B@{ shape: ${shape}}
|
||||
C@{ shape: ${shape}}
|
||||
D@{ shape: ${shape}}
|
||||
E@{ shape: ${shape}}
|
||||
n4@{ shape: ${shape}}
|
||||
|
||||
`;
|
||||
if (simplified) {
|
||||
code = `---
|
||||
config:
|
||||
layout: ${algorithm}
|
||||
---
|
||||
flowchart LR
|
||||
A["Abrakadabra"] --> C["C"] & C & C & C & C
|
||||
%% A["Abrakadabra"] --> C
|
||||
A@{ shape: ${shape}}
|
||||
C@{ shape: ${shape}}
|
||||
|
||||
`;
|
||||
}
|
||||
console.log(code);
|
||||
const { svg } = await mermaid.render('the-id-of-the-svg', code, undefined, undefined);
|
||||
const elem = document.querySelector('#diagram');
|
||||
elem.innerHTML = svg;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -592,9 +592,10 @@ export const render = async (
|
||||
setIncludeChildrenPolicy(target, ancestorId);
|
||||
}
|
||||
});
|
||||
|
||||
// const copy = JSON.parse(JSON.stringify({ ...elkGraph }));
|
||||
// console.log('APA13 layout before', copy);
|
||||
const g = await elk.layout(elkGraph);
|
||||
|
||||
// console.log('APA13 layout', JSON.parse(JSON.stringify(g)));
|
||||
// debugger;
|
||||
await drawNodes(0, 0, g.children, svg, subGraphsEl, 0);
|
||||
g.edges?.map(
|
||||
@ -683,6 +684,18 @@ export const render = async (
|
||||
}
|
||||
|
||||
if (startNode.calcIntersect) {
|
||||
// console.log(
|
||||
// 'APA13 calculating start intersection start node',
|
||||
// startNode.id,
|
||||
// startNode.x,
|
||||
// startNode.y,
|
||||
// 'w:',
|
||||
// startNode.width,
|
||||
// 'h:',
|
||||
// startNode.height,
|
||||
// '\nPos',
|
||||
// edge.points[0]
|
||||
// );
|
||||
const intersection = startNode.calcIntersect(
|
||||
{
|
||||
x: startNode.offset.posX + startNode.width / 2,
|
||||
@ -707,9 +720,18 @@ export const render = async (
|
||||
},
|
||||
edge.points[edge.points.length - 1]
|
||||
);
|
||||
// if (edge.id === 'L_n4_C_10_0') {
|
||||
// console.log('APA14 lineData', edge.points, 'intersection:', intersection);
|
||||
// console.log(
|
||||
// 'APA14! calculating end intersection\ndistance:',
|
||||
// distance(intersection, edge.points[edge.points.length - 1])
|
||||
// );
|
||||
// }
|
||||
|
||||
if (distance(intersection, edge.points[edge.points.length - 1]) > epsilon) {
|
||||
// console.log('APA13! distance ok\nintersection:', intersection);
|
||||
edge.points.push(intersection);
|
||||
// console.log('APA13! distance ok\npoints:', edge.points);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ import { createText } from '../createText.js';
|
||||
import utils from '../../utils.js';
|
||||
import { getLineFunctionsWithOffset } from '../../utils/lineWithOffset.js';
|
||||
import { getSubGraphTitleMargins } from '../../utils/subGraphTitleMargins.js';
|
||||
import { curveBasis, line, select } from 'd3';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { curveBasis, curveLinear, line, select } from 'd3';
|
||||
import rough from 'roughjs';
|
||||
import createLabel from './createLabel.js';
|
||||
import { addEdgeMarkers } from './edgeMarker.ts';
|
||||
@ -335,7 +336,7 @@ const cutPathAtIntersect = (_points, boundaryNode) => {
|
||||
return points;
|
||||
};
|
||||
|
||||
const adjustForArrowHeads = function (lineData, size = 5) {
|
||||
const adjustForArrowHeads = function (lineData, size = 5, shouldLog = false) {
|
||||
const newLineData = [...lineData];
|
||||
const lastPoint = lineData[lineData.length - 1];
|
||||
const secondLastPoint = lineData[lineData.length - 2];
|
||||
@ -344,6 +345,9 @@ const adjustForArrowHeads = function (lineData, size = 5) {
|
||||
(lastPoint.x - secondLastPoint.x) ** 2 + (lastPoint.y - secondLastPoint.y) ** 2
|
||||
);
|
||||
|
||||
if (shouldLog) {
|
||||
log.debug('APA14 distanceBetweenLastPoints', distanceBetweenLastPoints);
|
||||
}
|
||||
if (distanceBetweenLastPoints < size) {
|
||||
// Calculate the direction vector from the last point to the second last point
|
||||
const directionX = secondLastPoint.x - lastPoint.x;
|
||||
@ -366,6 +370,195 @@ const adjustForArrowHeads = function (lineData, size = 5) {
|
||||
|
||||
return newLineData;
|
||||
};
|
||||
function extractCornerPoints(points) {
|
||||
const cornerPoints = [];
|
||||
const cornerPointPositions = [];
|
||||
for (let i = 1; i < points.length - 1; i++) {
|
||||
const prev = points[i - 1];
|
||||
const curr = points[i];
|
||||
const next = points[i + 1];
|
||||
if (
|
||||
prev.x === curr.x &&
|
||||
curr.y === next.y &&
|
||||
Math.abs(curr.x - next.x) > 5 &&
|
||||
Math.abs(curr.y - prev.y) > 5
|
||||
) {
|
||||
cornerPoints.push(curr);
|
||||
cornerPointPositions.push(i);
|
||||
} else if (
|
||||
prev.y === curr.y &&
|
||||
curr.x === next.x &&
|
||||
Math.abs(curr.x - prev.x) > 5 &&
|
||||
Math.abs(curr.y - next.y) > 5
|
||||
) {
|
||||
cornerPoints.push(curr);
|
||||
cornerPointPositions.push(i);
|
||||
}
|
||||
}
|
||||
return { cornerPoints, cornerPointPositions };
|
||||
}
|
||||
|
||||
const findAdjacentPoint = function (pointA, pointB, distance) {
|
||||
const xDiff = pointB.x - pointA.x;
|
||||
const yDiff = pointB.y - pointA.y;
|
||||
const length = Math.sqrt(xDiff * xDiff + yDiff * yDiff);
|
||||
const ratio = distance / length;
|
||||
return { x: pointB.x - ratio * xDiff, y: pointB.y - ratio * yDiff };
|
||||
};
|
||||
|
||||
const fixCorners = function (lineData) {
|
||||
const { cornerPointPositions } = extractCornerPoints(lineData);
|
||||
const newLineData = [];
|
||||
for (let i = 0; i < lineData.length; i++) {
|
||||
if (cornerPointPositions.includes(i)) {
|
||||
const prevPoint = lineData[i - 1];
|
||||
const nextPoint = lineData[i + 1];
|
||||
const cornerPoint = lineData[i];
|
||||
|
||||
const newPrevPoint = findAdjacentPoint(prevPoint, cornerPoint, 5);
|
||||
const newNextPoint = findAdjacentPoint(nextPoint, cornerPoint, 5);
|
||||
|
||||
const xDiff = newNextPoint.x - newPrevPoint.x;
|
||||
const yDiff = newNextPoint.y - newPrevPoint.y;
|
||||
newLineData.push(newPrevPoint);
|
||||
|
||||
const a = Math.sqrt(2) * 2;
|
||||
let newCornerPoint = { x: cornerPoint.x, y: cornerPoint.y };
|
||||
if (Math.abs(nextPoint.x - prevPoint.x) > 10 && Math.abs(nextPoint.y - prevPoint.y) >= 10) {
|
||||
log.debug(
|
||||
'Corner point fixing',
|
||||
Math.abs(nextPoint.x - prevPoint.x),
|
||||
Math.abs(nextPoint.y - prevPoint.y)
|
||||
);
|
||||
const r = 5;
|
||||
if (cornerPoint.x === newPrevPoint.x) {
|
||||
newCornerPoint = {
|
||||
x: xDiff < 0 ? newPrevPoint.x - r + a : newPrevPoint.x + r - a,
|
||||
y: yDiff < 0 ? newPrevPoint.y - a : newPrevPoint.y + a,
|
||||
};
|
||||
} else {
|
||||
newCornerPoint = {
|
||||
x: xDiff < 0 ? newPrevPoint.x - a : newPrevPoint.x + a,
|
||||
y: yDiff < 0 ? newPrevPoint.y - r + a : newPrevPoint.y + r - a,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
log.debug(
|
||||
'Corner point skipping fixing',
|
||||
Math.abs(nextPoint.x - prevPoint.x),
|
||||
Math.abs(nextPoint.y - prevPoint.y)
|
||||
);
|
||||
}
|
||||
newLineData.push(newCornerPoint, newNextPoint);
|
||||
} else {
|
||||
newLineData.push(lineData[i]);
|
||||
}
|
||||
}
|
||||
return newLineData;
|
||||
};
|
||||
|
||||
export const generateRoundedPath = (points, radius, endPosition) => {
|
||||
if (points.length < 2) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// console.trace('here', points);
|
||||
const path = [];
|
||||
const startPoint = points[0];
|
||||
|
||||
path.push(`M ${startPoint.x},${startPoint.y}`);
|
||||
|
||||
for (let i = 1; i < points.length - 1; i++) {
|
||||
const currPoint = points[i];
|
||||
const nextPoint = points[i + 1];
|
||||
const prevPoint = points[i - 1];
|
||||
|
||||
// Calculate vectors
|
||||
const v1 = { x: currPoint.x - prevPoint.x, y: currPoint.y - prevPoint.y };
|
||||
const v2 = { x: nextPoint.x - currPoint.x, y: nextPoint.y - currPoint.y };
|
||||
|
||||
// Normalize vectors
|
||||
const v1Length = Math.hypot(v1.x, v1.y);
|
||||
const v2Length = Math.hypot(v2.x, v2.y);
|
||||
const v1Normalized = { x: v1.x / v1Length, y: v1.y / v1Length };
|
||||
const v2Normalized = { x: v2.x / v2Length, y: v2.y / v2Length };
|
||||
|
||||
// Calculate tangent points
|
||||
const tangentLength = Math.min(radius, v1Length / 2, v2Length / 2);
|
||||
const tangent1 = {
|
||||
x: currPoint.x - v1Normalized.x * tangentLength,
|
||||
y: currPoint.y - v1Normalized.y * tangentLength,
|
||||
};
|
||||
const tangent2 = {
|
||||
x: currPoint.x + v2Normalized.x * tangentLength,
|
||||
y: currPoint.y + v2Normalized.y * tangentLength,
|
||||
};
|
||||
|
||||
if (endPosition) {
|
||||
const { bottomY, leftX, rightX, topY } = endPosition;
|
||||
if (startPoint.pos === 'b' && tangent1.y > topY) {
|
||||
tangent1.y = topY;
|
||||
tangent2.y = topY;
|
||||
currPoint.y = topY;
|
||||
}
|
||||
if (startPoint.pos === 't' && tangent1.y < bottomY) {
|
||||
tangent1.y = bottomY;
|
||||
tangent2.y = bottomY;
|
||||
currPoint.y = bottomY;
|
||||
}
|
||||
if (startPoint.pos === 'l' && tangent1.x < rightX) {
|
||||
tangent1.x = rightX;
|
||||
tangent2.x = rightX;
|
||||
currPoint.x = rightX;
|
||||
}
|
||||
if (startPoint.pos === 'r' && tangent1.x > leftX) {
|
||||
tangent1.x = leftX;
|
||||
tangent2.x = leftX;
|
||||
currPoint.x = leftX;
|
||||
}
|
||||
if (tangent2.x && tangent2.y && tangent1.x && tangent1.y) {
|
||||
path.push(
|
||||
`L ${tangent1.x},${tangent1.y}`,
|
||||
`Q ${currPoint.x},${currPoint.y} ${tangent2.x},${tangent2.y}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (tangent2.x && tangent2.y && tangent1.x && tangent1.y) {
|
||||
path.push(
|
||||
`L ${tangent1.x},${tangent1.y}`,
|
||||
`Q ${currPoint.x},${currPoint.y} ${tangent2.x},${tangent2.y}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Last point
|
||||
const lastPoint = points[points.length - 1];
|
||||
if (endPosition) {
|
||||
if (startPoint.pos === 'b') {
|
||||
if (endPosition?.topY && points[1].y > endPosition?.topY && points[2].y > endPosition?.topY) {
|
||||
points[1].y = endPosition?.topY;
|
||||
points[2].y = endPosition?.topY;
|
||||
}
|
||||
path.push(`L ${lastPoint.x},${endPosition.topY}`);
|
||||
}
|
||||
if (startPoint.pos === 't') {
|
||||
if (points[1].y < endPosition.bottomY) {
|
||||
points[1].y = endPosition.bottomY;
|
||||
points[2].y = endPosition.bottomY;
|
||||
}
|
||||
path.push(`L ${lastPoint.x},${endPosition.bottomY}`);
|
||||
}
|
||||
if (startPoint.pos === 'l') {
|
||||
path.push(`L ${endPosition.rightX},${lastPoint.y}`);
|
||||
}
|
||||
if (startPoint.pos === 'r') {
|
||||
path.push(`L ${endPosition.leftX},${lastPoint.y}`);
|
||||
}
|
||||
} else {
|
||||
path.push(`L ${lastPoint.x},${lastPoint.y}`);
|
||||
}
|
||||
return path.join(' ');
|
||||
};
|
||||
|
||||
export const insertEdge = function (elem, edge, clusterDb, diagramType, startNode, endNode, id) {
|
||||
const { handDrawnSeed } = getConfig();
|
||||
@ -407,8 +600,12 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
}
|
||||
|
||||
let lineData = points.filter((p) => !Number.isNaN(p.y));
|
||||
lineData = adjustForArrowHeads(lineData);
|
||||
// lineData = fixCorners(lineData);
|
||||
lineData = adjustForArrowHeads(lineData, 4, edge.id === 'L_n4_C_10_0');
|
||||
lineData = fixCorners(lineData);
|
||||
// if (edge.id === 'L_n4_C_10_0') {
|
||||
// console.log('APA14 lineData', lineData);
|
||||
// }
|
||||
// lineData = adjustForArrowHeads(lineData);
|
||||
let curve = curveBasis;
|
||||
// let curve = curveLinear;
|
||||
if (edge.curve) {
|
||||
@ -417,6 +614,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
|
||||
const { x, y } = getLineFunctionsWithOffset(edge);
|
||||
const lineFunction = line().x(x).y(y).curve(curve);
|
||||
// const lineFunction = line().curve(curve);
|
||||
|
||||
let strokeClasses;
|
||||
switch (edge.thickness) {
|
||||
@ -447,6 +645,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
}
|
||||
let svgPath;
|
||||
let linePath = lineFunction(lineData);
|
||||
// let linePath = generateRoundedPath(lineData, 5);
|
||||
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
||||
if (edge.look === 'handDrawn') {
|
||||
const rc = rough.svg(elem);
|
||||
@ -478,16 +677,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
||||
|
||||
// DEBUG code, DO NOT REMOVE
|
||||
// adds a red circle at each edge coordinate
|
||||
// cornerPoints.forEach((point) => {
|
||||
// elem
|
||||
// .append('circle')
|
||||
// .style('stroke', 'blue')
|
||||
// .style('fill', 'blue')
|
||||
// .attr('r', 3)
|
||||
// .attr('cx', point.x)
|
||||
// .attr('cy', point.y);
|
||||
// });
|
||||
// lineData.forEach((point) => {
|
||||
// points.forEach((point) => {
|
||||
// elem
|
||||
// .append('circle')
|
||||
// .style('stroke', 'red')
|
||||
|
@ -57,7 +57,7 @@ function intersectLine(p1, p2, q1, q2) {
|
||||
num = a2 * c1 - a1 * c2;
|
||||
const y = num < 0 ? (num - offset) / denom : (num + offset) / denom;
|
||||
// console.log(
|
||||
// 'APA30 intersectLine intersection',
|
||||
// 'APA13 intersectLine intersection',
|
||||
// '\np1: (',
|
||||
// p1.x,
|
||||
// p1.y,
|
||||
|
@ -7,7 +7,7 @@ import intersectLine from './intersect-line.js';
|
||||
function intersectPolygon(node, polyPoints, point) {
|
||||
let x1 = node.x;
|
||||
let y1 = node.y;
|
||||
|
||||
// console.trace('APA14 intersectPolygon', x1, y1, polyPoints, point);
|
||||
let intersections = [];
|
||||
|
||||
let minX = Number.POSITIVE_INFINITY;
|
||||
@ -24,7 +24,7 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
|
||||
let left = x1 - node.width / 2 - minX;
|
||||
let top = y1 - node.height / 2 - minY;
|
||||
|
||||
// console.log('APA13 intersectPolygon2 ', left, y1);
|
||||
for (let i = 0; i < polyPoints.length; i++) {
|
||||
let p1 = polyPoints[i];
|
||||
let p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
|
||||
@ -34,7 +34,9 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
{ x: left + p1.x, y: top + p1.y },
|
||||
{ x: left + p2.x, y: top + p2.y }
|
||||
);
|
||||
// console.log('APA13 intersectPolygon3 ', intersect);
|
||||
if (intersect) {
|
||||
// console.log('APA13 intersectPolygon4 ', intersect);
|
||||
intersections.push(intersect);
|
||||
}
|
||||
}
|
||||
@ -42,6 +44,7 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
if (!intersections.length) {
|
||||
return node;
|
||||
}
|
||||
// console.log('APA12 intersectPolygon5 ');
|
||||
|
||||
if (intersections.length > 1) {
|
||||
// More intersections, find the one nearest to edge end point
|
||||
@ -54,6 +57,8 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
let qdy = q.y - point.y;
|
||||
let distq = Math.sqrt(qdx * qdx + qdy * qdy);
|
||||
|
||||
// console.log('APA12 intersectPolygon6 ');
|
||||
|
||||
return distp < distq ? -1 : distp === distq ? 0 : 1;
|
||||
});
|
||||
}
|
||||
|
@ -66,7 +66,9 @@ export async function card<T extends SVGGraphicsElement>(parent: D3Selection<T>,
|
||||
const w = bounds.width;
|
||||
|
||||
const points = getPoints(w, h, padding);
|
||||
return intersect.polygon(bounds, points, point);
|
||||
|
||||
const res = intersect.polygon(bounds, points, point);
|
||||
return { x: res.x - 0.5, y: res.y - 0.5 };
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
|
@ -61,9 +61,7 @@ export function forkJoin<T extends SVGGraphicsElement>(
|
||||
node.height += padding / 2 || 0;
|
||||
}
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
return intersect.rect(bounds, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
|
@ -51,13 +51,58 @@ export async function lean_right<T extends SVGGraphicsElement>(parent: D3Selecti
|
||||
updateNodeBounds(node, polygon);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
const dx = h / 2;
|
||||
const z = w - h;
|
||||
// (w = dx+z+dx)
|
||||
const points = [
|
||||
{ x: -dx, y: 0 },
|
||||
{ x: z, y: 0 },
|
||||
{ x: z + dx, y: -h },
|
||||
{ x: 0, y: -h },
|
||||
];
|
||||
|
||||
const res = intersect.polygon(bounds, points, point);
|
||||
// if (node.id === 'C') {
|
||||
// console.log(
|
||||
// 'APA14!',
|
||||
// bounds.x,
|
||||
// bounds.x,
|
||||
// bounds.width,
|
||||
// '\nw:',
|
||||
// w,
|
||||
// points,
|
||||
// '\nExternal point: ',
|
||||
// '(',
|
||||
// point.x,
|
||||
// point.y,
|
||||
// ')\nIntersection:',
|
||||
// res
|
||||
// );
|
||||
// }
|
||||
return { x: res.x - 0.5, y: res.y - 0.5 };
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
return intersect.polygon(node, points, point);
|
||||
node.intersect = function (point: Point) {
|
||||
const res = intersect.polygon(node, points, point);
|
||||
// if (node.id === 'C') {
|
||||
// console.log(
|
||||
// 'APA14!!',
|
||||
// node.x,
|
||||
// node.y,
|
||||
// '\nw:',
|
||||
// node.width,
|
||||
// points,
|
||||
// '\nExternal point: ',
|
||||
// '(',
|
||||
// point.x,
|
||||
// point.y,
|
||||
// ')\nIntersection:',
|
||||
// res
|
||||
// );
|
||||
// }
|
||||
return res;
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
|
@ -12,6 +12,14 @@ import rough from 'roughjs';
|
||||
import type { D3Selection } from '../../../types.js';
|
||||
import type { Bounds, Point } from '../../../types.js';
|
||||
|
||||
function getPoints(w: number, finalH: number, waveAmplitude: number) {
|
||||
return [
|
||||
{ x: -w / 2, y: finalH / 2 },
|
||||
...generateFullSineWavePoints(-w / 2, finalH / 2, w / 2, finalH / 2, waveAmplitude, 1),
|
||||
{ x: w / 2, y: -finalH / 2 },
|
||||
...generateFullSineWavePoints(w / 2, -finalH / 2, -w / 2, -finalH / 2, waveAmplitude, -1),
|
||||
];
|
||||
}
|
||||
export async function waveRectangle<T extends SVGGraphicsElement>(
|
||||
parent: D3Selection<T>,
|
||||
node: Node
|
||||
@ -53,12 +61,7 @@ export async function waveRectangle<T extends SVGGraphicsElement>(
|
||||
options.fillStyle = 'solid';
|
||||
}
|
||||
|
||||
const points = [
|
||||
{ x: -w / 2, y: finalH / 2 },
|
||||
...generateFullSineWavePoints(-w / 2, finalH / 2, w / 2, finalH / 2, waveAmplitude, 1),
|
||||
{ x: w / 2, y: -finalH / 2 },
|
||||
...generateFullSineWavePoints(w / 2, -finalH / 2, -w / 2, -finalH / 2, waveAmplitude, -1),
|
||||
];
|
||||
const points = getPoints(w, finalH, waveAmplitude);
|
||||
|
||||
const waveRectPath = createPathFromPoints(points);
|
||||
const waveRectNode = rc.path(waveRectPath, options);
|
||||
@ -78,9 +81,14 @@ export async function waveRectangle<T extends SVGGraphicsElement>(
|
||||
updateNodeBounds(node, waveRect);
|
||||
|
||||
node.calcIntersect = function (bounds: Bounds, point: Point) {
|
||||
// TODO: Implement intersect for this shape
|
||||
const radius = bounds.width / 2;
|
||||
return intersect.circle(bounds, radius, point);
|
||||
const w = bounds.width;
|
||||
const h = bounds.height;
|
||||
|
||||
const waveAmplitude = Math.min(h * 0.2, h / 4);
|
||||
const finalH = h + waveAmplitude * 2;
|
||||
|
||||
const points = getPoints(w, finalH, waveAmplitude);
|
||||
return intersect.polygon(node, points, point);
|
||||
};
|
||||
|
||||
node.intersect = function (point) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user