From 4265737690aa0790bef02e0949324957065495d1 Mon Sep 17 00:00:00 2001 From: Fen Dweller Date: Thu, 23 Apr 2020 16:14:11 -0400 Subject: [PATCH] Add basic screenshot functionality All of the entities are rendered to the canvas. It only renders images, so there are no names, height bars, etc. --- macrovision.css | 25 +++++++++++++++++++ macrovision.html | 5 ++++ macrovision.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/macrovision.css b/macrovision.css index ba06b2eb..3c9b48b4 100644 --- a/macrovision.css +++ b/macrovision.css @@ -779,4 +779,29 @@ button:hover { button:enabled:active { border-style: inset; background: #aaa; +} + +.toast { + position: absolute; + bottom: 10%; + left: 50%; + animation-name: toast-animation; + animation-duration: 5s; + animation-timing-function: linear; + z-index: 1001; +} + +@keyframes toast-animation { + 0% { + transform: translate(-50%, 0); + opacity: 1; + } + 50% { + transform: translate(-50%, -10vh); + opacity: 1; + } + 100% { + transform: translate(-50%, -20vh); + opacity: 0; + } } \ No newline at end of file diff --git a/macrovision.html b/macrovision.html index 22f9e949..1528b484 100644 --- a/macrovision.html +++ b/macrovision.html @@ -63,6 +63,11 @@ + + + diff --git a/macrovision.js b/macrovision.js index bc56bbda..679c08fe 100644 --- a/macrovision.js +++ b/macrovision.js @@ -325,10 +325,16 @@ function drawScale(ifDirty = false) { } heightPer = math.unit(heightPer, config.height.units[0].unit.name) - ctx.clearRect(0, 0, canvas.width, canvas.height); + + ctx.scale(1, 1); ctx.canvas.width = canvas.clientWidth; ctx.canvas.height = canvas.clientHeight; + + ctx.beginPath(); + ctx.rect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = "#333"; + ctx.fill(); ctx.beginPath(); ctx.moveTo(50, 50); @@ -1359,6 +1365,10 @@ document.addEventListener("DOMContentLoaded", () => { prepareMenu(); prepareEntities(); + document.querySelector("#screenshot").addEventListener("click", e => { + copyScreenshot(); + toast("Copied to clipboard!"); + }); document.querySelector("#toggle-menu").addEventListener("click", e => { const popoutMenu = document.querySelector("#popout-menu"); if (popoutMenu.classList.contains("visible")) { @@ -2265,3 +2275,56 @@ function importScene(data) { updateSizes(); } + +function renderToCanvas() { + const ctx = document.querySelector("#display").getContext("2d"); + Object.entries(entities).forEach(([id, entity]) => { + element = document.querySelector("#entity-" + id); + img = element.querySelector("img"); + + let x = parseFloat(element.dataset.x); + let y = parseFloat(element.dataset.y); + + let coords = rel2abs({x: x, y: y}); + + let offset = img.style.getPropertyValue("--offset"); + offset = parseFloat(offset.substring(0, offset.length-1)) + x = coords.x - img.getBoundingClientRect().width/2; + y = coords.y - img.getBoundingClientRect().height * (-offset/100); + + let xSize = img.getBoundingClientRect().width; + let ySize = img.getBoundingClientRect().height; + + ctx.drawImage(img, x, y, xSize, ySize); + }); +} + +function exportCanvas(callback) { + /** @type {CanvasRenderingContext2D} */ + const ctx = document.querySelector("#display").getContext("2d"); + const blob = ctx.canvas.toBlob(callback); +} + +function copyScreenshot() { + renderToCanvas(); + exportCanvas(blob => { + navigator.clipboard.write([ + new ClipboardItem({ + "image/png": blob + }) + ]); + }); + drawScale(false); +} + +function toast(msg) { + div = document.createElement("div"); + div.innerHTML = msg; + div.classList.add("toast"); + + document.body.appendChild(div); + + setTimeout(() => { + document.body.removeChild(div); + }, 5000) +} \ No newline at end of file