Skip to content

Commit

Permalink
wip layers
Browse files Browse the repository at this point in the history
  • Loading branch information
denishov committed Dec 16, 2023
1 parent 3519237 commit 8279571
Show file tree
Hide file tree
Showing 8 changed files with 385 additions and 185 deletions.
187 changes: 10 additions & 177 deletions app/public/js/tools/layers.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,10 @@
/* global Microdraw */

window.ToolLayers = { layers : (function() {
const {dom} = Microdraw;
const tool = {
layers: [],
rowTemplate: `
<ul class="layer-item">
<li><span style="width:300px;overflow-wrap:anywhere">layer.url</span></li>
<li><b class="layer-item">Name:</b> <span style="width:70px">layer.name</span></li>
<li><b class="layer-item"> Opacity (%):</b>
<input class="layer-value" value="layer.opacity" onchange="Microdraw.tools.layers.changeOpacity(event)" />
<input type="range" value="layer.opacity" min="0" max="100" oninput="Microdraw.tools.layers.changeOpacity(event)" style="width:100px"/>
</li>
<li><b class="layer-item">Position (%)</b>
<input class="layer-value" value="0" onchange="Microdraw.tools.layers.changeX(event)" />
<input class="layer-value" value="0" onchange="Microdraw.tools.layers.changeY(event)" /></li>
<li><b class="layer-item">Rotation (deg):</b> <input class="layer-value" value="0" onchange="Microdraw.tools.layers.changeRotation(event)" /></li>
<li><b class="layer-item"> First slice:</b> <input class="layer-value" value="0" min="0" max="layer.maxSlice" onchange="Microdraw.tools.layers.changeFirstSlice(event)" /> (0 - layer.maxSlice)</li>
<li><b class="layer-item"> Last slice:</b> <input class="layer-value" value="layer.maxSlice" min="0" max="layer.maxSlice" onchange="Microdraw.tools.layers.changeLastSlice(event)" /> (0 - layer.maxSlice)</li>
<li><button onclick="Microdraw.tools.layers.deleteLayer(event)">Delete layer</button></li>
</ul>
`,
fetchDZI: async (url) => {
let dzi = null;

try {
// const _ = new URL(url);
const response0 = await fetch(url, { method: 'HEAD' });
if (response0.ok) {
const response = await fetch(url);
dzi = await response.json();
}
} catch (error) {
console.log('Error:', error);
}

return dzi;
},
addRow: () => {
dom.querySelector("#add-layer-panel").style.display = "block";
dom.querySelector("#add-layer-button").style.display = "none";
dom.querySelector("#layers-list").classList.add("small");
console.log("addRow");
},
deleteLayer: (e) => {
console.log("deleteLayer", e);

// get layer from UI
const el = e.target;
const div = el.closest("div.layer");

// get layer data before deleting
const url = div.querySelectorAll("span")[0].innerText;
// const name = div.querySelectorAll("span")[1].innerText;

// delete layer from UI
div.remove();
deleteLayer: (url) => {
console.log('deleteLayer');

// delete layer from layers array
const index = tool.layers.findIndex((layer) => layer.url === url);
Expand All @@ -68,10 +17,10 @@ window.ToolLayers = { layers : (function() {
changeOpacity: (e) => {
const {value} = e.target;

if (e.target.type === "range") {
e.target.parentElement.parentElement.querySelectorAll("input")[0].value = value;
if (e.target.type === 'range') {
e.target.parentElement.parentElement.querySelectorAll('input')[0].value = value;
} else {
e.target.parentElement.parentElement.querySelectorAll("input")[1].value = value;
e.target.parentElement.parentElement.querySelectorAll('input')[1].value = value;
}

tool.layers[0].opacity = value / 100;
Expand Down Expand Up @@ -104,56 +53,22 @@ window.ToolLayers = { layers : (function() {
},
_addLayerToViewer: (url, tileIndex, imageSources, opacity) => {
let tileSource = imageSources.tileSources[tileIndex];
if (tileSource[0] === "/") {
if (tileSource[0] === '/') {
const tmp = new URL(url);
tileSource = tmp.origin + tileSource;
}
const options = {
tileSource,
opacity,
compositeOperation: "source-over"
compositeOperation: 'source-over'
};
Microdraw.viewer.addTiledImage(options);
},

addLayer: (name, url, opacityPercent, dzi) => {
const el = document.createElement("div");
el.className = "layer";
const rowInstance = tool.rowTemplate
.replace("layer.name", name)
.replace("layer.url", url)
.replaceAll("layer.opacity", opacityPercent)
.replaceAll("layer.maxSlice", dzi.tileSources.length - 1);
el.innerHTML = rowInstance;
dom.querySelector("#layers-list").appendChild(el);

tool.layers.push({
name,
url,
el,
x: 0,
y: 0,
rotation: 0,
opacity: 0.5,
imageSources: dzi,
firstSlice: 0,
lastSlice: dzi.tileSources.length - 1
});

tool.updateLayers();
addLayer: () => {
},
_updateLayersFromTable: () => {
// update layer slice
const arr = dom.querySelectorAll("#layers-panel table tr");
for (let i = 1; i < arr.length; i++) {
const tr = arr[i];
const name = tr.querySelectorAll("span")[0].innerText;
const url = tr.querySelectorAll("span")[1].innerText;
const index = tool.layers.findIndex((layer) => layer.name === name && layer.url === url);
const opacity = tr.querySelectorAll("input")[0].value / 100;
tool.layers[index].opacity = opacity;
Microdraw.viewer.world.getItemAt(index + 1).setOpacity(opacity);
}
Microdraw.viewer.world.getItemAt(index + 1).setOpacity(opacity);
},
// eslint-disable-next-line max-statements
updateLayers: () => {
Expand Down Expand Up @@ -184,90 +99,8 @@ window.ToolLayers = { layers : (function() {

// add layer to viewer
tool._addLayerToViewer(url, tileIndex, imageSources, opacity);

// update the layer
tool._updateLayersFromTable();
},

// eslint-disable-next-line max-statements
addLayerUI: async () => {
const arr = dom.querySelectorAll("#add-layer-panel input");
const name = arr[0].value;
const url = arr[1].value;

// check if url resolves and contains a good json
const dzi = await tool.fetchDZI(url);
if (!dzi) {
arr[1].style.backgroundColor = "#fcc";

return;
}

// cleanup the UI
arr[1].parentElement.style.backgroundColor = "none";
arr[0].value = "";
arr[1].value = "";
dom.querySelector("#add-layer-panel").style.display = "none";
dom.querySelector("#add-layer-button").style.display = "block";
dom.querySelector("#layers-list").classList.remove("small");

// add the layer
tool.addLayer(name, url, 0.5 * 100, dzi);
},
cancelAddLayerUI: () => {
dom.querySelector("#add-layer-panel").style.display = "none";
dom.querySelector("#add-layer-button").style.display = "block";
dom.querySelector("#layers-list").classList.remove("small");
console.log("cancelAddLayerUI");
},
_detachLayersContainer: () => {
const obj = dom.querySelector("#layers-panel");
obj.style.display = "none";
},
_isDragging: false,
_offsetX: 0,
_offsetY: 0,
_attachLayersContainer: () => {
const obj = dom.querySelector("#layers-panel");
obj.style.display = "block";

obj.addEventListener('mousedown', function(e) {
if (e.target.id !== "layers-panel") { return; }
tool._isDragging = true;
const {top, left, width, height} = obj.getBoundingClientRect();
tool._offsetX = e.clientX - left - width/2;
tool._offsetY = e.clientY - top - (height)/2;
obj.classList.add('dragging');
});

dom.addEventListener('mousemove', function(e) {
if (!tool._isDragging) { return; }
obj.style.left = (e.clientX - tool._offsetX) + 'px';
obj.style.top = (e.clientY - tool._offsetY) + 'px';
});

dom.addEventListener('mouseup', function() {
if (!tool._isDragging) { return; }
tool._isDragging = false;
obj.classList.remove('dragging');
});
},

_attachLayer: () => {
const obj = dom.querySelector("#layers-panel");
obj.style.display = "block";
},

/**
* @desc Add layers of deep zoom images
* @param {string} prevTool The previous tool to which the selection goes back
* @returns {void}
*/
click: function (prevTool) {
tool._attachLayersContainer();
Microdraw.selectedTool = prevTool;
}

};

return tool;
}())};
11 changes: 10 additions & 1 deletion app/views/scripts/components/Data.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<Header v-if="!fullscreen">
<span class="title">MicroDraw</span>
</Header>
<main :class="{ fullscreen }">
<main
class="editor"
:class="{ fullscreen }"
>
<OntologySelector
:ontology="ontology"
:open="displayOntology"
Expand All @@ -18,6 +21,10 @@
<Tools />
</template>
<template #content>
<LayersManager
:open="displayLayers"
@on-close="displayLayers = false"
/>
<div
id="microdraw"
style="width: 100%; height: 100%"
Expand All @@ -37,13 +44,15 @@ import * as Vue from 'vue';
import useVisualization from '../store/visualization';
import LayersManager from './LayersManager.vue';
import Tools from './Tools.vue';
const {
title,
displayChat,
displayScript,
displayOntology,
displayLayers,
currentLabel,
ontology,
fullscreen,
Expand Down
9 changes: 8 additions & 1 deletion app/views/scripts/components/Embed.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<main>
<main class="editor">
<OntologySelector
:ontology="ontology"
:open="displayOntology"
Expand All @@ -15,6 +15,11 @@
<Tools />
</template>
<template #content>
<LayersManager
:open="displayLayers"
@on-close="displayLayers = false"
/>

<div
id="microdraw"
style="width: 100%; height: 100%"
Expand Down Expand Up @@ -46,6 +51,7 @@ import * as Vue from 'vue';
import useVisualization from '../store/visualization';
import LayersManager from './LayersManager.vue';
import Tools from './Tools.vue';
Expand All @@ -70,6 +76,7 @@ const {
displayChat,
displayScript,
displayOntology,
displayLayers,
currentLabel,
ontology,
fullscreen,
Expand Down
Loading

0 comments on commit 8279571

Please sign in to comment.