From 36f86f523fb280f3e8947f9e43eb03408efde808 Mon Sep 17 00:00:00 2001 From: Francesco Luzzana Date: Mon, 11 Apr 2022 20:02:16 +0200 Subject: [PATCH] init --- README.md | 7 ++ cables.js | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++ cover.jpg | Bin 0 -> 33668 bytes index.html | 64 +++++++++++++++++++ style.css | 110 ++++++++++++++++++++++++++++++++ 5 files changed, 365 insertions(+) create mode 100644 README.md create mode 100644 cables.js create mode 100644 cover.jpg create mode 100644 index.html create mode 100644 style.css diff --git a/README.md b/README.md new file mode 100644 index 0000000..60858a9 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Spaghetti Cables + +![spaghetti forgetti rigretti svg cables](cover.jpg) + +First attempt of using a cable-based interaction for web dasein. Research for the [mod cms](https://pad.xpub.nl/p/modcms) (workin title) + +See also the implementation in [panel](https://git.xpub.nl/kamo/panel)! diff --git a/cables.js b/cables.js new file mode 100644 index 0000000..530f4df --- /dev/null +++ b/cables.js @@ -0,0 +1,184 @@ +// Great resource from https://stackoverflow.com/a/40700068 +// Thank you ConnorFan + +var strokeWidth = 10; +var bufferSize; + +var svgElement = document.getElementById("svgElement"); +var rect = svgElement.getBoundingClientRect(); +var path = null; +var strPath; +var buffer = []; // Contains the last positions of the mouse cursor +var cable; + +const logs = document.getElementById("logs"); + +class Cable { + start = ""; + end = ""; + path = ""; + color = ""; + + constructor(start) { + this.start = start; + } +} + +svgElement.addEventListener("mousedown", function (e) { + bufferSize = document.getElementById("cmbBufferSize").value; + path = document.createElementNS("http://www.w3.org/2000/svg", "path"); + path.setAttribute("fill", "none"); + + let color = randomColor(); + path.setAttribute("stroke", color); + path.setAttribute("stroke-width", strokeWidth); + path.setAttribute("stroke-linecap", "round"); + buffer = []; + var pt = getMousePosition(e); + appendToBuffer(pt); + strPath = "M" + pt.x + " " + pt.y; + path.setAttribute("d", strPath); + svgElement.appendChild(path); + + let socket = getSocket(pt); + if (socket) { + cable = new Cable(socket.querySelector("input").getAttribute("name")); + cable.color = color; + } +}); + +svgElement.addEventListener("mousemove", function (e) { + if (path) { + appendToBuffer(getMousePosition(e)); + updateSvgPath(); + } +}); + +svgElement.addEventListener("mouseup", function (e) { + if (path) { + let pt = getMousePosition(e); + let socket = getSocket(pt); + if (socket) { + cable.end = socket.querySelector("input").getAttribute("name"); + cable.path = path.getAttribute("d"); + logCable(cable); + } + + path = null; + } +}); + +svgElement.addEventListener("mouseleave", function (e) { + if (path) { + let pt = getMousePosition(e); + let socket = getSocket(pt); + if (socket) { + cable.end = socket.querySelector("input").getAttribute("name"); + cable.path = path.getAttribute("d"); + logCable(cable); + } + + path = null; + } +}); + +// ok +var getMousePosition = function (e) { + return { + x: e.pageX - rect.left, + y: e.pageY - rect.top, + }; +}; + +var appendToBuffer = function (pt) { + buffer.push(pt); + while (buffer.length > bufferSize) { + buffer.shift(); + } +}; + +// ok +// Calculate the average point, starting at offset in the buffer +var getAveragePoint = function (offset) { + var len = buffer.length; + if (len % 2 === 1 || len >= bufferSize) { + var totalX = 0; + var totalY = 0; + var pt, i; + var count = 0; + for (i = offset; i < len; i++) { + count++; + pt = buffer[i]; + totalX += pt.x; + totalY += pt.y; + } + return { + x: totalX / count, + y: totalY / count, + }; + } + return null; +}; + +// ok +var updateSvgPath = function () { + var pt = getAveragePoint(0); + + if (pt) { + // Get the smoothed part of the path that will not change + strPath += " L" + pt.x + " " + pt.y; + + // Get the last part of the path (close to the current mouse position) + // This part will change if the mouse moves again + var tmpPath = ""; + for (var offset = 2; offset < buffer.length; offset += 2) { + pt = getAveragePoint(offset); + tmpPath += " L" + pt.x + " " + pt.y; + } + + // Set the complete current path coordinates + path.setAttribute("d", strPath + tmpPath); + } +}; + +// ok +var randomColor = function () { + const hue = Math.floor(Math.random() * 360); + const saturation = Math.floor(50 + Math.random() * (50 + 1)) + "%"; + const lightness = "75%"; + return "hsl(" + hue + ", " + saturation + ", " + lightness + ")"; +}; + +// ok +var getSocket = function (position) { + precision = 8; + size = 24; + + const sockets = document.querySelectorAll(".socket"); + sock = Array.from(sockets).filter((socket) => { + input = socket.querySelector("input"); + return ( + position.x >= input.offsetLeft - precision + size / 2 && + position.x <= input.offsetLeft + precision + size / 2 && + position.y >= input.offsetTop - precision + size / 2 && + position.y <= input.offsetTop + precision + size / 2 + ); + })[0]; + return sock; +}; + +let logCable = function (cable) { + let entry = document.createElement("li"); + let marker = document.createElement("span"); + marker.classList.add("marker"); + marker.style.backgroundColor = cable.color; + + entry.appendChild(marker); + + let text = document.createElement("span"); + text.innerHTML = `connects ${cable.start} with ${cable.end}`; + + entry.appendChild(text); + + logs.appendChild(entry); +}; diff --git a/cover.jpg b/cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..37645f6362c074dcd03a5a5ff755c85f2a6f7e90 GIT binary patch literal 33668 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..1092e8f --- /dev/null +++ b/index.html @@ -0,0 +1,64 @@ + + + + + + + Document + + + + +
+ + +
+ +
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+
+ +
    + + diff --git a/style.css b/style.css new file mode 100644 index 0000000..8f71117 --- /dev/null +++ b/style.css @@ -0,0 +1,110 @@ +* { + box-sizing: border-box; + font-family: 'Courier New', Courier, monospace; +} + +:root { + --radius: 2px; + +} + + +.control { + position: relative; + display: inline-flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.control label { + margin-top: 8px; +} + +.control+.control { + margin-left: 8px; +} + +.module input[type='submit'] { + position: absolute; + right: 32px; + bottom: 32px; + border: 1px solid currentColor; + background: none; + border-radius: var(--radius); + padding: 4px 8px; +} + +.module #name { + position: absolute; + bottom: 32px; + left: 32px; + padding: 4px 8px; + border-radius: var(--radius); + border: 1px solid currentColor; +} + + + +.module { + display: inline-flex; + justify-content: space-between; + position: relative; + min-width: 500px; + min-height: 500px; + border-radius: var(--radius); + + padding: 32px; + border: 1px solid currentColor; + + margin: 8px; +} + + +.socket + .socket { + margin-top: 64px; +} + +.socket input[type='text'] { + display: inline-block; + width: 24px; + height: 24px; + border-radius: 50%; + border: 1px solid currentColor; + cursor: alias; + position: relative; + z-index: 50; + background: none; + pointer-events: none; +} + +#svgElement { + z-index: 10; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + mix-blend-mode: multiply; +} + +#logs { + list-style: none; + margin: 8px; + padding: 0; +} + +.marker { + display: inline-block; + margin-right: 8px; + width: 0.75em; + height: 0.75em; + border-radius: 50%; + vertical-align: middle; +} + + + + + +