Skip to content

Commit

Permalink
Merge pull request #14 from ian-fox/click_drag
Browse files Browse the repository at this point in the history
feat: add click_and_drag option
  • Loading branch information
blackary authored Jun 4, 2024
2 parents 98c46e4 + 4afdba4 commit bb7dc6e
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 11 deletions.
2 changes: 1 addition & 1 deletion pages/dynamic_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ def get_ellipse_coords(point: tuple[int, int]) -> tuple[int, int, int, int]:

if point not in st.session_state["points"]:
st.session_state["points"].append(point)
st.experimental_rerun()
st.rerun()
59 changes: 59 additions & 0 deletions pages/rectangle_select.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import streamlit as st
from PIL import Image, ImageDraw
from streamlit_image_coordinates import streamlit_image_coordinates

st.set_page_config(
page_title="Streamlit Image Coordinates: Rectangle Select",
layout="wide",
page_icon="🪟",
)

"# 🪟 Streamlit Image Coordinates: Rectangle Select"

"## Click and drag on the image"


if "coordinates" not in st.session_state:
st.session_state["coordinates"] = None


def get_rectangle_coords(
points: tuple[tuple[int, int], tuple[int, int]],
) -> tuple[int, int, int, int]:
point1, point2 = points
return (
point1[0],
point1[1],
point2[0],
point2[1],
)


with st.echo("below"), Image.open("kitty.jpeg") as img:
draw = ImageDraw.Draw(img)

if st.session_state["coordinates"]:
coords = get_rectangle_coords(st.session_state["coordinates"])
draw.rectangle(coords, fill=None, outline="red", width=2)

cols = st.columns([1, 1, 4])
with cols[0]:
value = streamlit_image_coordinates(img, key="rectangle", click_and_drag=True)

if value is not None:
point1 = value["x1"], value["y1"]
point2 = value["x2"], value["y2"]

if point1 != point2 and st.session_state["coordinates"] != (point1, point2):
st.session_state["coordinates"] = (point1, point2)
st.rerun()

# Enlarge the rectangle selected between point1 and point2
if st.session_state["coordinates"]:
coords = get_rectangle_coords(st.session_state["coordinates"])
new_image = img.crop(coords)
new_image = new_image.resize(
(int(new_image.width * 1.5), int(new_image.height * 1.5))
)
with cols[1]:
st.image(new_image, use_column_width=False)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

setuptools.setup(
name="streamlit-image-coordinates",
version="0.1.7",
version="0.1.8",
author="Zachary Blackwood",
author_email="[email protected]",
description=(
Expand Down
16 changes: 11 additions & 5 deletions src/streamlit_image_coordinates/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def streamlit_image_coordinates(
width: int | None = None,
key: str | None = None,
use_column_width: UseColumnWith | str | None = None,
click_and_drag: bool = False,
):
"""
Take an image source and return the coordinates of the image clicked
Expand All @@ -38,11 +39,15 @@ def streamlit_image_coordinates(
width : int | None
The width of the image. If None, the width will be the original width
use_column_width : "auto", "always", "never", or bool
If "auto", set the image's width to its natural size,
but do not exceed the width of the column.
If "always" or True, set the image's width to the column width.
If "never" or False, set the image's width to its natural size.
Note: if set, `use_column_width` takes precedence over the `width` parameter.
If "auto", set the image's width to its natural size,
but do not exceed the width of the column.
If "always" or True, set the image's width to the column width.
If "never" or False, set the image's width to its natural size.
Note: if set, `use_column_width` takes precedence over the `width` parameter.
click_and_drag: bool
If true, the event is not sent until the user releases the mouse. The
mouse down event is returned as x1, y1 and the mouse up event is returned
as x2, y2. Note that x2 and y2 may be outside the image.
"""

if isinstance(source, (Path, str)):
Expand Down Expand Up @@ -73,6 +78,7 @@ def streamlit_image_coordinates(
width=width,
use_column_width=use_column_width,
key=key,
click_and_drag=click_and_drag,
)


Expand Down
2 changes: 1 addition & 1 deletion src/streamlit_image_coordinates/frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<img id="image" />
<img id="image" draggable="false" />
</body>
</html>
20 changes: 18 additions & 2 deletions src/streamlit_image_coordinates/frontend/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,20 @@ function clickListener(event) {
sendValue({x: offsetX, y: offsetY, width: img.width, height: img.height});
}

function mouseDownListener(downEvent) {
const [x1, y1] = [downEvent.offsetX, downEvent.offsetY];

window.addEventListener("mouseup", (upEvent) => {
const [x2, y2] = [upEvent.clientX, upEvent.clientY];
const img = document.getElementById("image");
const rect = img.getBoundingClientRect();

sendValue({x1: x1, y1: y1, x2: x2 - rect.left, y2: y2 - rect.top, width: img.width, height: img.height});
}, {once: true})
}

function onRender(event) {
let {src, height, width, use_column_width} = event.detail.args;
let {src, height, width, use_column_width, click_and_drag} = event.detail.args;

const img = document.getElementById("image");

Expand Down Expand Up @@ -59,7 +71,11 @@ function onRender(event) {
window.addEventListener("resize", resizeImage);

// When image is clicked, send the coordinates to Python through sendValue
if (!img.onclick) {
if (click_and_drag) {
img.onclick = null;
img.onmousedown = mouseDownListener;
} else {
img.onmousedown = null;
img.onclick = clickListener;
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/streamlit_image_coordinates/frontend/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
width: 100%;
height: auto;
}

img {
user-select: none;
}
3 changes: 2 additions & 1 deletion streamlit_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@

st.write(value)

st.write("## Full width example")
st.write("## Full width example with click and drag")

with st.echo("below"):
value = streamlit_image_coordinates(
"kitty.jpeg",
key="local4",
use_column_width="always",
click_and_drag=True,
)

st.write(value)

0 comments on commit bb7dc6e

Please sign in to comment.