| @@ -28,6 +28,7 @@ body { | |||
| -moz-user-drag: none; | |||
| -o-user-drag: none; | |||
| transform: translate(-50%, -100%); | |||
| pointer-events: fill; | |||
| } | |||
| .selected { | |||
| @@ -128,4 +129,4 @@ body { | |||
| .options-row .options-field-unit { | |||
| flex: 1; | |||
| font-size: 150%; | |||
| } | |||
| } | |||
| @@ -35,25 +35,25 @@ function snapRel(coords) { | |||
| } | |||
| function adjustAbs(coords, oldHeight, newHeight) { | |||
| return {x: coords.x, y: 1 + (coords.y - 1) * math.divide(oldHeight, newHeight)}; | |||
| return { x: coords.x, y: 1 + (coords.y - 1) * math.divide(oldHeight, newHeight) }; | |||
| } | |||
| function rel2abs(coords) { | |||
| const canvasWidth = document.querySelector("#display").clientWidth - 50; | |||
| const canvasHeight = document.querySelector("#display").clientHeight - 50; | |||
| return {x: coords.x * canvasWidth, y: coords.y * canvasHeight}; | |||
| return { x: coords.x * canvasWidth, y: coords.y * canvasHeight }; | |||
| } | |||
| function abs2rel(coords) { | |||
| const canvasWidth = document.querySelector("#display").clientWidth - 50; | |||
| const canvasHeight = document.querySelector("#display").clientHeight - 50; | |||
| return {x: coords.x / canvasWidth, y: coords.y / canvasHeight}; | |||
| return { x: coords.x / canvasWidth, y: coords.y / canvasHeight }; | |||
| } | |||
| function updateEntityElement(entity, element) { | |||
| const position = rel2abs({x: element.dataset.x, y: element.dataset.y}); | |||
| const position = rel2abs({ x: element.dataset.x, y: element.dataset.y }); | |||
| const view = element.dataset.view; | |||
| element.style.left = position.x + "px"; | |||
| @@ -109,12 +109,12 @@ function drawScale() { | |||
| ctx.fillStyle = "#dddddd"; | |||
| ctx.beginPath(); | |||
| ctx.fillText(value.format({precision: 3}), x+20, y+35); | |||
| ctx.fillText(value.format({ precision: 3 }), x + 20, y + 35); | |||
| ctx.font = oldFont; | |||
| ctx.strokeStyle = oldStroke; | |||
| ctx.fillStyle = oldFill; | |||
| } | |||
| } | |||
| const canvas = document.querySelector("#display"); | |||
| /** @type {CanvasRenderingContext2D} */ | |||
| @@ -168,7 +168,7 @@ function makeEntity() { | |||
| } | |||
| } | |||
| }, | |||
| init: function() { | |||
| init: function () { | |||
| console.log(this); | |||
| Object.entries(this.views).forEach(([key, val]) => { | |||
| val.parent = this; | |||
| @@ -188,7 +188,7 @@ function clickDown(e) { | |||
| let entY = document.querySelector("#entities").getBoundingClientRect().y; | |||
| dragOffsetX = e.clientX - rect.left + entX - rect.width / 2; | |||
| dragOffsetY = e.clientY - rect.top + entY - rect.height; | |||
| clickTimeout = setTimeout(() => {dragging = true}, 100) | |||
| clickTimeout = setTimeout(() => { dragging = true }, 100) | |||
| } | |||
| function clickUp() { | |||
| @@ -202,7 +202,7 @@ function clickUp() { | |||
| } | |||
| clicked = null; | |||
| } | |||
| } | |||
| function deselect() { | |||
| @@ -251,7 +251,7 @@ function configEntityOptions(entity) { | |||
| entity.scale = e.target.value; | |||
| updateSizes(); | |||
| }); | |||
| scaleInput.setAttribute("min", 1); | |||
| scaleInput.setAttribute("type", "number"); | |||
| scaleInput.value = entity.scale; | |||
| @@ -275,17 +275,57 @@ function clearViewOptions(entity, view) { | |||
| } | |||
| // this is a crime against humanity, and also stolen from | |||
| // stack overflow | |||
| // https://stackoverflow.com/questions/38487569/click-through-png-image-only-if-clicked-coordinate-is-transparent | |||
| const testCtx = document.createElement("canvas").getContext("2d"); | |||
| function testClick(event) { | |||
| const target = event.target; | |||
| // Get click coordinates | |||
| var x = event.clientX - target.getBoundingClientRect().x, | |||
| y = event.clientY - target.getBoundingClientRect().y, | |||
| w = testCtx.canvas.width = target.width, | |||
| h = testCtx.canvas.height = target.height, | |||
| alpha; | |||
| console.log(x, y); | |||
| // Draw image to canvas | |||
| // and read Alpha channel value | |||
| testCtx.drawImage(target, 0, 0, w, h); | |||
| alpha = testCtx.getImageData(x, y, 1, 1).data[3]; // [0]R [1]G [2]B [3]A | |||
| console.log(alpha) | |||
| // If pixel is transparent, | |||
| // retrieve the element underneath and trigger it's click event | |||
| if (alpha === 0) { | |||
| const oldDisplay = target.style.display; | |||
| target.style.display = "none"; | |||
| const newTarget = document.elementFromPoint(event.clientX, event.clientY); | |||
| newTarget.dispatchEvent(new MouseEvent("mousedown", { | |||
| "clientX": event.clientX, | |||
| "clientY": event.clientY | |||
| })); | |||
| target.style.display = oldDisplay; | |||
| } else { | |||
| clickDown(event); | |||
| } | |||
| } | |||
| function displayEntity(entity, view, x, y) { | |||
| const location = entity.location; | |||
| const img = document.createElement("img"); | |||
| img.src = "./pepper.png" | |||
| img.src = "./man.svg" | |||
| img.classList.add("entity"); | |||
| img.dataset.x = x; | |||
| img.dataset.y = y; | |||
| img.addEventListener("mousedown", e => {clickDown(e); e.stopPropagation()}); | |||
| img.addEventListener("mousedown", e => { testClick(e); e.stopPropagation() }); | |||
| img.id = "entity-" + entityIndex; | |||
| img.dataset.key = entityIndex; | |||
| @@ -303,12 +343,13 @@ function displayEntity(entity, view, x, y) { | |||
| document.addEventListener("DOMContentLoaded", () => { | |||
| for (let x = 0; x < 5; x++) { | |||
| const entity = makeEntity(); | |||
| entity.name = "Green is my pepper"; | |||
| entity.name = "Dude"; | |||
| entity.author = "Fen" | |||
| const x = 0.25 + Math.random() * 0.5; | |||
| const y = 0.25 + Math.random() * 0.5; | |||
| displayEntity(entity, "body", x, y); | |||
| } | |||
| document.querySelector("body").appendChild(testCtx.canvas); | |||
| updateSizes(); | |||
| @@ -319,7 +360,7 @@ document.addEventListener("DOMContentLoaded", () => { | |||
| document.querySelector("#options-height-unit").addEventListener("input", e => { | |||
| updateWorldHeight(); | |||
| }) | |||
| world.addEventListener("mousedown", e => deselect()); | |||
| document.addEventListener("mouseup", e => clickUp()); | |||
| }); | |||
| @@ -330,7 +371,7 @@ window.addEventListener("resize", () => { | |||
| document.addEventListener("mousemove", (e) => { | |||
| if (clicked) { | |||
| const position = snapRel(abs2rel({x: e.clientX - dragOffsetX, y: e.clientY - dragOffsetY})); | |||
| const position = snapRel(abs2rel({ x: e.clientX - dragOffsetX, y: e.clientY - dragOffsetY })); | |||
| clicked.dataset.x = position.x; | |||
| clicked.dataset.y = position.y; | |||
| updateEntityElement(entities[clicked.dataset.key], clicked); | |||
| @@ -343,10 +384,10 @@ function updateWorldHeight() { | |||
| const oldHeight = config.height; | |||
| config.height = math.unit(value + " " + unit) | |||
| Object.entries(entities).forEach(([key, entity]) => { | |||
| const element = document.querySelector("#entity-" + key); | |||
| const newPosition = adjustAbs({x: element.dataset.x, y: element.dataset.y}, oldHeight, config.height); | |||
| const newPosition = adjustAbs({ x: element.dataset.x, y: element.dataset.y }, oldHeight, config.height); | |||
| element.dataset.x = newPosition.x; | |||
| element.dataset.y = newPosition.y; | |||
| }); | |||
| @@ -0,0 +1,272 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | |||
| <svg | |||
| xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||
| xmlns="http://www.w3.org/2000/svg" | |||
| xmlns:cc="http://creativecommons.org/ns#" | |||
| xmlns:xlink="http://www.w3.org/1999/xlink" | |||
| xmlns:dc="http://purl.org/dc/elements/1.1/" | |||
| xmlns:svg="http://www.w3.org/2000/svg" | |||
| xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||
| xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||
| xmlns:ns1="http://sozi.baierouge.fr" | |||
| id="svg59707" | |||
| viewBox="0 0 313.87 910.03" | |||
| version="1.0" | |||
| > | |||
| <defs | |||
| id="defs59709" | |||
| > | |||
| <linearGradient | |||
| id="linearGradient60580" | |||
| x1="-140" | |||
| xlink:href="#linearGradient60449" | |||
| gradientUnits="userSpaceOnUse" | |||
| x2="-140" | |||
| y1="209" | |||
| y2="325.47" | |||
| /> | |||
| <linearGradient | |||
| id="linearGradient60582" | |||
| x1="342.86" | |||
| xlink:href="#linearGradient60459" | |||
| gradientUnits="userSpaceOnUse" | |||
| x2="342.86" | |||
| y1="308.44" | |||
| y2="220.44" | |||
| /> | |||
| <linearGradient | |||
| id="linearGradient60584" | |||
| x1="51.429" | |||
| xlink:href="#linearGradient60471" | |||
| gradientUnits="userSpaceOnUse" | |||
| x2="51.429" | |||
| y1="949.51" | |||
| y2="869.51" | |||
| /> | |||
| <linearGradient | |||
| id="linearGradient60588" | |||
| x1="101.02" | |||
| xlink:href="#linearGradient60490" | |||
| gradientUnits="userSpaceOnUse" | |||
| x2="101.02" | |||
| y1="488" | |||
| y2="662.95" | |||
| /> | |||
| <linearGradient | |||
| id="linearGradient60594" | |||
| x1="51.429" | |||
| xlink:href="#linearGradient60471" | |||
| gradientUnits="userSpaceOnUse" | |||
| x2="51.429" | |||
| gradientTransform="matrix(-.55163 0 0 .83470 508.65 -107.03)" | |||
| y1="949.51" | |||
| y2="869.51" | |||
| /> | |||
| <linearGradient | |||
| id="linearGradient60596" | |||
| x1="33.265" | |||
| xlink:href="#linearGradient60471" | |||
| gradientUnits="userSpaceOnUse" | |||
| x2="51.429" | |||
| y1="996.38" | |||
| y2="869.51" | |||
| /> | |||
| </defs | |||
| > | |||
| <g | |||
| id="layer1" | |||
| transform="translate(-229.62 -12.421)" | |||
| > | |||
| <g | |||
| id="g60563" | |||
| transform="translate(42.426 -50.508)" | |||
| > | |||
| <path | |||
| id="path12233" | |||
| fill-rule="evenodd" | |||
| d="m226.64 277.38c-21.86 0-39.45 17.59-39.45 39.45v328.18c0 21.86 17.59 39.45 39.45 39.45h7.15v-316.79h19.62v316.79h186.41v-316.79h19.62v316.79h2.17c21.86 0 39.45-17.59 39.45-39.45v-328.18c0-21.86-17.59-39.45-39.45-39.45h-234.97z" | |||
| /> | |||
| <path | |||
| id="path12235" | |||
| fill-rule="evenodd" | |||
| d="m253.41 655.09v269.76h83.78v-265.32h19.62v265.32h83.01v-269.76h-186.41z" | |||
| /> | |||
| <polygon | |||
| id="polygon12237" | |||
| points="9140 10547 8547 10557 7983 10466 7463 10281 6998 10013 6600 9670 6285 9260 6063 8795 5948 8282 5951 7755 6068 7253 6290 6786 6604 6366 7002 6004 7471 5713 8002 5504 8584 5389 9176 5378 9740 5469 10260 5654 10726 5922 11123 6265 11438 6675 11660 7140 11776 7654 11772 8180 11655 8682 11433 9149 11119 9569 10721 9931 10252 10222 9721 10431" | |||
| transform="matrix(.031352 .010901 -.0090796 .038159 142.1 -234.33)" | |||
| /> | |||
| <path | |||
| id="path12239" | |||
| fill-rule="evenodd" | |||
| transform="matrix(3.0336 0 0 3.4682 -2930.8 -819.23)" | |||
| d="m1077.3 502.66a13.789 13.965 0 1 1 -27.6 0" | |||
| /> | |||
| <path | |||
| id="path12241" | |||
| fill-rule="evenodd" | |||
| transform="matrix(3.0058 0 0 3.4682 -2798.3 -818.78)" | |||
| d="m1077.3 502.66a13.789 13.965 0 1 1 -27.6 0" | |||
| /> | |||
| <path | |||
| id="path59721" | |||
| transform="matrix(1 0 0 1.0695 487.14 -193.99)" | |||
| fill="url(#linearGradient60580)" | |||
| d="m-51.429 375.93a88.571 133.57 0 1 1 -177.14 0 88.571 133.57 0 1 1 177.14 0z" | |||
| /> | |||
| <path | |||
| id="path60457" | |||
| transform="matrix(.93333 0 0 1.1039 30 -27.407)" | |||
| fill="url(#linearGradient60582)" | |||
| d="m428.57 208.79a85.714 55 0 1 1 -171.43 0 85.714 55 0 1 1 171.43 0z" | |||
| /> | |||
| <path | |||
| id="path60469" | |||
| transform="matrix(.87097 0 0 1 251.64 37.857)" | |||
| fill="url(#linearGradient60584)" | |||
| d="m95.714 877.36a44.286 55 0 1 1 -88.571 0 44.286 55 0 1 1 88.571 0z" | |||
| /> | |||
| <path | |||
| id="path60484" | |||
| transform="matrix(.87097 0 0 1 353.78 37.857)" | |||
| fill="url(#linearGradient60584)" | |||
| d="m95.714 877.36a44.286 55 0 1 1 -88.571 0 44.286 55 0 1 1 88.571 0z" | |||
| /> | |||
| <path | |||
| id="path60488" | |||
| transform="matrix(0 -3.64 .42515 0 13.112 915.49)" | |||
| fill="url(#linearGradient60588)" | |||
| d="m151.52 578.6a50.508 168.7 0 1 1 -101.01 0h50.51z" | |||
| /> | |||
| <path | |||
| id="path60518" | |||
| transform="matrix(0 -3.64 -.42515 0 679.85 915.49)" | |||
| fill="url(#linearGradient60588)" | |||
| d="m151.52 578.6a50.508 168.7 0 1 1 -101.01 0h50.51z" | |||
| /> | |||
| <path | |||
| id="path60542" | |||
| transform="matrix(.55163 0 0 .83470 183.21 -105.01)" | |||
| fill="url(#linearGradient60584)" | |||
| d="m86.558 928.19c0 30.36-72.09 1.32-72.09-29.04s12.515-76.79 36.961-76.79c24.445 0 35.129 75.47 35.129 105.83z" | |||
| /> | |||
| <path | |||
| id="path60549" | |||
| fill="url(#linearGradient60594)" | |||
| d="m460.9 667.73c0 25.34 39.77 1.1 39.77-24.24s-6.91-64.09-20.39-64.09c-13.49 0-19.38 62.99-19.38 88.33z" | |||
| /> | |||
| <path | |||
| id="path60555" | |||
| transform="matrix(-.6201 .50511 -.67127 -.36457 861.7 607.05)" | |||
| fill="url(#linearGradient60596)" | |||
| d="m95.714 877.36a44.286 55 0 1 1 -88.571 0 44.286 55 0 1 1 88.571 0z" | |||
| /> | |||
| <path | |||
| id="path60559" | |||
| transform="matrix(.6201 .50511 .67127 -.36457 -177.93 605.03)" | |||
| fill="url(#linearGradient60596)" | |||
| d="m95.714 877.36a44.286 55 0 1 1 -88.571 0 44.286 55 0 1 1 88.571 0z" | |||
| /> | |||
| </g | |||
| > | |||
| </g | |||
| > | |||
| <metadata | |||
| > | |||
| <rdf:RDF | |||
| > | |||
| <cc:Work | |||
| > | |||
| <dc:format | |||
| >image/svg+xml</dc:format | |||
| > | |||
| <dc:type | |||
| rdf:resource="http://purl.org/dc/dcmitype/StillImage" | |||
| /> | |||
| <cc:license | |||
| rdf:resource="http://creativecommons.org/licenses/publicdomain/" | |||
| /> | |||
| <dc:publisher | |||
| > | |||
| <cc:Agent | |||
| rdf:about="http://openclipart.org/" | |||
| > | |||
| <dc:title | |||
| >Openclipart</dc:title | |||
| > | |||
| </cc:Agent | |||
| > | |||
| </dc:publisher | |||
| > | |||
| <dc:title | |||
| >Man silhouette</dc:title | |||
| > | |||
| <dc:date | |||
| >2009-04-02T08:29:11</dc:date | |||
| > | |||
| <dc:description | |||
| >Man silhouette by Felipe Maciel, originally named "man_crystal". Contact: ffmaciel <at> gmail <dot> com. From old OCAL website.</dc:description | |||
| > | |||
| <dc:source | |||
| >https://openclipart.org/detail/23760/man-silhouette-by-anonymous-23760</dc:source | |||
| > | |||
| <dc:creator | |||
| > | |||
| <cc:Agent | |||
| > | |||
| <dc:title | |||
| >Anonymous</dc:title | |||
| > | |||
| </cc:Agent | |||
| > | |||
| </dc:creator | |||
| > | |||
| <dc:subject | |||
| > | |||
| <rdf:Bag | |||
| > | |||
| <rdf:li | |||
| >black</rdf:li | |||
| > | |||
| <rdf:li | |||
| >man</rdf:li | |||
| > | |||
| <rdf:li | |||
| >people</rdf:li | |||
| > | |||
| <rdf:li | |||
| >sign</rdf:li | |||
| > | |||
| <rdf:li | |||
| >silhouette</rdf:li | |||
| > | |||
| <rdf:li | |||
| >symbol</rdf:li | |||
| > | |||
| </rdf:Bag | |||
| > | |||
| </dc:subject | |||
| > | |||
| </cc:Work | |||
| > | |||
| <cc:License | |||
| rdf:about="http://creativecommons.org/licenses/publicdomain/" | |||
| > | |||
| <cc:permits | |||
| rdf:resource="http://creativecommons.org/ns#Reproduction" | |||
| /> | |||
| <cc:permits | |||
| rdf:resource="http://creativecommons.org/ns#Distribution" | |||
| /> | |||
| <cc:permits | |||
| rdf:resource="http://creativecommons.org/ns#DerivativeWorks" | |||
| /> | |||
| </cc:License | |||
| > | |||
| </rdf:RDF | |||
| > | |||
| </metadata | |||
| > | |||
| </svg | |||
| > | |||