roundabout,
created on Monday, 19 August 2024, 08:43:40 (1724057020),
received on Monday, 19 August 2024, 08:43:57 (1724057037)
Author identity: vlad <vlad.muntoiu@gmail.com>
4d06b95659ab76a41c25254296ea4e7eeec63d8d
static/picture-annotation.py
@@ -0,0 +1,53 @@
from pyscript import document
from pyodide.ffi import create_proxy
# Remove the loading message
document.getElementById("python-loading").remove()
document.getElementById("shape-options").style.display = "flex"
image = document.getElementById("annotation-image")
zone = document.getElementById("annotation-zone")
shape_type = ""
def switch_shape(event):
global shape_type
shape = event.currentTarget.id
shape_type = shape
print("Shape is now of type:", shape)
def open_shape(event):
print("Creating a new shape of type:", shape_type)
new_shape = document.createElementNS("http://www.w3.org/2000/svg", "svg")
new_shape.setAttribute("width", image.width)
new_shape.setAttribute("height", image.height)
if shape_type == "shape-bbox":
rectangle = document.createElementNS("http://www.w3.org/2000/svg", "rect")
rectangle.setAttribute("x", "10")
rectangle.setAttribute("y", "10")
rectangle.setAttribute("width", "100")
rectangle.setAttribute("height", "100")
rectangle.setAttribute("fill", "hotPink")
new_shape.appendChild(rectangle)
zone.appendChild(new_shape)
for button in list(document.getElementById("shape-selector").children):
button.addEventListener(
"click",
create_proxy(switch_shape)
)
print("Shape", button.id, "is available")
zone.addEventListener(
"click",
create_proxy(open_shape)
)
static/style.css
@@ -3,4 +3,25 @@
:root {
--gap-navbar: 1rem;
--width-navbar-button: 0;
}
}
iconify-icon {
display: inline-block;
width: 1em;
height: 1em;
}
:is(#shape-selector, #shape-options) > button > iconify-icon {
font-size: 2rem;
}
#annotation-zone {
position: relative;
}
#annotation-zone > svg {
z-index: 1;
position: absolute;
top: 0;
left: 0;
}
templates/default.html
@@ -7,6 +7,7 @@
<link rel="stylesheet" href="/static/style.css">
<script src="/static/efficient-ui/dialogs.js"></script>
<script src="/static/efficient-ui/toasts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/iconify-icon@2.1.0/dist/iconify-icon.min.js"></script>
</head>
<body>
<header>
templates/picture-annotation.html
@@ -1,9 +1,59 @@
{% extends "default.html" %}
{% block title %}Picture | gigadata{% endblock %}
{% block content %}
<style>
py-script {
display: none;
}
/* Full PyScript style is too much, but we still need to hide the Python code */
</style>
<script type="module" src="https://pyscript.net/releases/2024.8.2/core.js"></script>
<x-frame style="--width: 768px">
<h1>Annotating: {{ resource.title }}</h1>
<img src="/raw/picture/{{ resource.id }}" alt="{{ resource.title }}">
<p id="python-loading">Please wait for Python to load...</p>
</x-frame>
<x-frame is="main-area">
<x-buttonbox id="shape-selector">
<button class="button-flat" title="rectangle" id="shape-bbox">
<iconify-icon icon="mdi:square"></iconify-icon>
</button>
<button class="button-flat" title="oriented rectangle" id="shape-o-bbox">
<iconify-icon icon="mdi:rhombus"></iconify-icon>
</button>
<button class="button-flat" title="ellipse" id="shape-ellipse">
<iconify-icon icon="mdi:circle"></iconify-icon>
</button>
<button class="button-flat" title="polygon" id="shape-polygon">
<iconify-icon icon="mdi:pentagon"></iconify-icon>
</button>
<button class="button-flat" title="freehand closed" id="shape-freehand-polygon">
<iconify-icon icon="mdi:lasso"></iconify-icon>
</button>
<button class="button-flat" title="line" id="shape-line">
<iconify-icon icon="mdi:graph-line-variant"></iconify-icon>
</button>
<button class="button-flat" title="freehand open" id="shape-freehand-line">
<iconify-icon icon="mdi:gesture"></iconify-icon>
</button>
<button class="button-flat" title="point" id="shape-point">
<iconify-icon icon="mdi:circle"></iconify-icon>
</button>
<button class="button-flat" title="whole picture" id="shape-all">
<iconify-icon icon="mdi:image"></iconify-icon>
</button>
</x-buttonbox>
<div id="annotation-zone">
<img id="annotation-image" src="/raw/picture/{{ resource.id }}" alt="">
</div>
<x-buttonbox style="display: none;" id="shape-options">
<button class="button-flat" title="cancel" disabled>
<iconify-icon icon="mdi:close"></iconify-icon>
</button>
<button class="button-flat" title="apply" disabled>
<iconify-icon icon="mdi:check"></iconify-icon>
</button>
</x-buttonbox>
</x-frame>
<script type="py" src="/static/picture-annotation.py"></script>
{% endblock %}