Skip to content

Commit

Permalink
draw svg
Browse files Browse the repository at this point in the history
  • Loading branch information
metaforpro committed Dec 22, 2023
1 parent 3657030 commit ceea967
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 8 deletions.
7 changes: 6 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
color: #edf8fc;
/* --color-tertiary-900: 255 141 141; */
}
body {
margin: 0;
padding: 0;
height: 100svh;
width: 100svw;
}
</style>
<script type="module">
// await new Promise((res) => import("https://zavx0z.github.io/dev-tools/index.js").then(() => setTimeout(res, 200)))
import("./src/index.js")
console.log(window.location.href)
</script>
<dev-tools mobile></dev-tools>
</head>
Expand Down
4 changes: 4 additions & 0 deletions src/actions/layout.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* @typedef { import("elkjs").ElkNode & { absolutePosition: { x: number, y: number } } } ELKNode
*/

async function algorithm(GraphBounding, MachineRelation, GraphRelation) {

}
2 changes: 1 addition & 1 deletion src/actions/compound.js → src/actions/svgPath.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* @typedef {[Point, Point]} LineSegment
* @typedef {Point[]} Path
* @typedef {"top"| "right" | "bottom" | "left"} Sides
* @typedef {MPathParam | LPathParam | ZPathParam | CPathParam | QPathParam} PathParam
* @typedef { MPathParam | LPathParam | ZPathParam | CPathParam | QPathParam } PathParam
* @typedef {[MPathParam, ...PathParam[]]} SvgPath
* @typedef {["M", Point]} MPathParam
* @typedef {["L", Point]} LPathParam
Expand Down
59 changes: 57 additions & 2 deletions src/core/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { representation } from "../actions/repr.js"
import { createSimulator } from "./simulator.js"
import { machineToGraphRelation } from "../actions/relation.js"
import "https://cdn.jsdelivr.net/npm/[email protected]/lib/elk-api.min.js"
import { getPath, pathToD } from "../actions/svgPath.js"

/**
* @typedef {Object} Size
Expand Down Expand Up @@ -65,9 +66,11 @@ onmessage = async ({ data: { type, params } }) => {
// simulator.send({ type: "PREVIEW.CLEAR" })
break
case "DOM.BOUNDED":
// ======================= SET DOM BOUNDING SIZE ======================
const /** @type {import("types").GraphSize}}*/ { edges, nodes } = params
for (let [id, size] of nodes) GraphBounding.nodes.set(id, { size })
for (let [id, size] of edges) GraphBounding.edges.set(id, { size })
// ======================= ELK ALGORITHM ======================
/**
* @param {string} nodeID
* @returns {import("elkjs").ElkNode}
Expand Down Expand Up @@ -114,6 +117,7 @@ onmessage = async ({ data: { type, params } }) => {
],
}
}
// ==================== LAYOUT EDGES/NODES ======================
const rootEdges = GraphRelation.nodes.has(undefined) ? GraphRelation.nodes.get(undefined) : []
const layoutElkNode = await elk.layout({
id: "root",
Expand All @@ -130,7 +134,6 @@ onmessage = async ({ data: { type, params } }) => {
/** @param {import("elkjs").ElkExtendedEdge} elkEdge */
const setEdgeLayout = (elkEdge) => {
const lca = GraphRelation.edges.get(elkEdge.id)
// if (!lca) return
const elkLca = stateNodeToElkNodeMap.get(lca)
const edge = GraphBounding.edges.get(elkEdge.id)
if (elkEdge.sections) {
Expand Down Expand Up @@ -186,8 +189,60 @@ onmessage = async ({ data: { type, params } }) => {
}
layoutElkNode.edges.forEach(setEdgeLayout)
setLayout(layoutElkNode.children[0], undefined)
console.log("[worker]", GraphBounding)
postMessage({ type: "DOM.LAYOUT", params: GraphBounding })
// ======================= LINES =================================
const lines = new Map()

for (const [id, edge] of MachineRelation.edges) {
const sourceBound = GraphBounding.nodes.get(edge.source)
const edgeBound = GraphBounding.edges.get(id)
const targetBound = GraphBounding.nodes.get(edge.target)
const sections = edgeBound.sections || []
const sourceRect = {
...sourceBound.position,
...sourceBound.size,
top: sourceBound.position.y,
bottom: sourceBound.position.y + sourceBound.size.height,
left: sourceBound.position.x,
right: sourceBound.position.x + sourceBound.size.width,
toJSON: () => {},
}
const edgeRect = {
...edgeBound.position,
...edgeBound.size,
top: edgeBound.position.y,
bottom: edgeBound.position.y + edgeBound.size.height,
left: edgeBound.position.x,
right: edgeBound.position.x + edgeBound.size.width,
toJSON: () => {},
}
const targetRect = {
...targetBound.position,
...targetBound.size,
top: targetBound.position.y,
bottom: targetBound.position.y + targetBound.size.height,
left: targetBound.position.x,
right: targetBound.position.x + targetBound.size.width,
toJSON: () => {},
}
if (sourceRect && edgeRect && targetRect) {
/** @type {import("src/actions/svgPath.js").SvgPath | undefined} */
let path
if (sections.length) {
const section = sections[0]
path = [["M", section.startPoint], ...(section.bendPoints?.map((point) => ["L", point]) || [])]
const preLastPoint = path[path.length - 1][1]
const xSign = Math.sign(section.endPoint.x - preLastPoint.x)
const ySign = Math.sign(section.endPoint.y - preLastPoint.y)
const endPoint = { x: section.endPoint.x - 5 * xSign, y: section.endPoint.y - 5 * ySign }
path.push(["L", endPoint])
} else path = getPath(sourceRect, edgeRect, targetRect)
if (path) {
lines.set(id, pathToD(path))
}
}
}
postMessage({ type: "LINES.INIT", params: lines })
break
default:
console.log("[worker]", type, params)
Expand Down
9 changes: 6 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import Node from "./templates/Node.js"
import Edge from "./templates/Edge.js"
import Line from "./templates/Line.js"
// import Line from "./templates/Line.js"
const template = document.createElement("template")
template.innerHTML = /*html*/ `
<link rel="stylesheet" href="./src/styles.css" type="text/css">
Expand Down Expand Up @@ -60,9 +61,11 @@ class StateMachine extends HTMLElement {
element.style.top = `${edge.position.y}px`
element.style.visibility = "visible"
}
for (const [id, edge] of GraphBounding.edges) {
// Line({id, sourceRect: GraphBounding.nodes.get())})
}
break
case "LINES.INIT":
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
for (const [id, path] of params) svg.innerHTML += Line(id, path)
this.#shadowRoot.append(svg)
break
default:
console.log("[shadow]", type, params)
Expand Down
17 changes: 16 additions & 1 deletion src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
.edge {
visibility: hidden;
position: fixed;
z-index: 40;
z-index: 9999;
display: flex;
cursor: pointer;
align-items: center;
Expand Down Expand Up @@ -149,3 +149,18 @@
.edge-cond::after {
content: "]";
}

svg {
pointer-events: none;
position: fixed;
left: 0px;
top: 0px;
height: 100%;
width: 100%;
overflow: visible;
z-index: 9999;
}
.line {
fill: rgb(var(--tertiary-900) / 1);
stroke: rgb(var(--tertiary-900) / 1);
}
16 changes: 16 additions & 0 deletions src/templates/Line.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const svg = String.raw
/**
* @param {string} id
* @param {string} path
* @returns {string}
*/
export default (id, path) => svg`
<g stroke="#fff" class="line">
<defs>
<marker id="marker-${id}" viewBox="0 0 10 10" markerWidth="5" markerHeight="5" refX="0" refY="5" markerUnits="strokeWidth" orient="auto">
<path d="M0,0 L0,10 L10,5 z" />
</marker>
</defs>
<path d="${path}" id="path-${id}" stroke-width="2" fill="none" marker-end="url(#marker-${id})" opacity="1"/>
</g>
`

0 comments on commit ceea967

Please sign in to comment.