Skip to content

Commit

Permalink
add scrolling to page or to annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
lfoppiano committed Aug 16, 2024
1 parent 7aea669 commit 6f0ee0f
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 34 deletions.
78 changes: 67 additions & 11 deletions streamlit_pdf_viewer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import streamlit.components.v1 as components
import json

_RELEASE = True
_RELEASE = False
RENDERING_EMBED = "legacy_embed"
RENDERING_IFRAME = "legacy_iframe"
RENDERING_UNWRAP = "unwrap"
Expand Down Expand Up @@ -35,7 +35,9 @@ def pdf_viewer(input: Union[str, Path, bytes],
rendering: str = RENDERING_UNWRAP,
pages_to_render: List[int] = (),
render_text: bool = False,
resolution_boost: int = 1
resolution_boost: int = 1,
scroll_to_page: int = None,
scroll_to_annotation: int = None,
):
"""
pdf_viewer function to display a PDF file in a Streamlit app.
Expand All @@ -54,6 +56,8 @@ def pdf_viewer(input: Union[str, Path, bytes],
working to implement for the "unwrap" method.
:param render_text: Whether to enable selection of text in the PDF viewer. Defaults to False.
:param resolution_boost: Boost the resolution by a factor from 2 to 10. Defaults to 1.
:param scroll_to_page: Scroll to a specific page in the PDF. The parameter is an integer, which represent the positional value of the page. E.g. 1, will be the first page. Defaults to None.
:param scroll_to_annotation: Scroll to a specific annotation in the PDF. The parameter is an integer, which represent the positional value of the annotation. E.g. 1, will be the first annotation. Defaults to None.
The function reads the PDF file (from a file path, URL, or binary data), encodes it in base64,
and uses a Streamlit component to render it in the app. It supports optional annotations and adjustable margins.
Expand All @@ -74,6 +78,16 @@ def pdf_viewer(input: Union[str, Path, bytes],
elif resolution_boost > 10:
raise ValueError("ratio_boost must be lower than 10")

if scroll_to_page:
if scroll_to_annotation:
raise ValueError("scroll_to_page and scroll_to_annotation cannot be used together")
if scroll_to_page < 1:
scroll_to_page = None

else:
if scroll_to_annotation < 1:
scroll_to_annotation = None

if type(input) is not bytes:
with open(input, 'rb') as fo:
binary = fo.read()
Expand All @@ -99,13 +113,16 @@ def pdf_viewer(input: Union[str, Path, bytes],
rendering=rendering,
pages_to_render=pages_to_render,
render_text=render_text,
resolution_boost=resolution_boost
resolution_boost=resolution_boost,
scroll_to_page=scroll_to_page,
scroll_to_annotation=scroll_to_annotation
)
return component_value


if not _RELEASE:
import streamlit as st
from streamlit import markdown

# from glob import glob

Expand All @@ -117,6 +134,29 @@ def pdf_viewer(input: Union[str, Path, bytes],
# with st.container(height=600):
# pdf_viewer(path, width=800, render_text=True, resolution_boost=values[id])
#
# def scroll_to_page(page):
# st.markdown(
# """
# function(){
# document.getElementById(""" + page + """).scrollIntoView({behavior: 'smooth'})
# };
#
# function()
# """, unsafe_allow_html=True)

# print(page)
# st.components.v1.html(
# """
# <script>
# function scrollDown(){
# page_canvas = document.getElementById('""" + page + """')
# console.log(page_canvas)
# page_canvas.scrollIntoView({behavior: 'smooth'})
# }
# scrollDown()
# </script>
# """
# )

with open("resources/test.pdf", 'rb') as fo:
binary = fo.read()
Expand All @@ -129,20 +169,34 @@ def pdf_viewer(input: Union[str, Path, bytes],

tab1, tab2 = st.tabs(["tab1", "tab2"])

# st.markdown("""
# <style>
# * {
# overflow-anchor: none !important;
# }
# </style>""", unsafe_allow_html=True)
# @st.fragment
# def show_buttons_scrolling(pages_id: List):
# for page in pages_id:
# print(page)
# st.button(f"Page {page}", key=f"page_{page}", on_click=scroll_to_page, args=(page,))

with tab1:
st.markdown("tab 1")
with st.container(height=300):
with st.container(height=400):
viewer = pdf_viewer(
binary,
annotations=annotations,
render_text=True,
key="bao"
key="bao",
scroll_to_page=3
)
st.markdown(viewer)
st.markdown(type(viewer))

annotations_id = viewer['annotations']
pages_id = viewer['pages']
# st.markdown(viewer)
# st.markdown(type(viewer))
# if type(viewer) == dict:
# annotations_id = viewer['annotations']
# pages_id = viewer['pages']
# show_buttons_scrolling(pages_id)

with tab2:
st.markdown("tab 2")
Expand All @@ -152,5 +206,7 @@ def pdf_viewer(input: Union[str, Path, bytes],
annotations=annotations,
render_text=True,
key="miao",
resolution_boost=4
resolution_boost=4,
scroll_to_annotation=2
)

58 changes: 35 additions & 23 deletions streamlit_pdf_viewer/frontend/src/PdfViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
<div id="pdfViewer" :style="pdfViewerStyle">
<div id="pdfAnnotations" v-if="args.annotations">
<div v-for="(annotation, index) in filteredAnnotations" :key="index" :style="getPageStyle">
<!-- <div :style="getAnnotationStyle(annotation)" :id="`annotation-${index}`"></div>-->
<div :style="getAnnotationStyle(annotation, index)"></div>
<div :style="getAnnotationStyle(annotation, index)" :id="`annotation-${index}`"></div>
</div>
</div>
</div>
Expand Down Expand Up @@ -97,8 +96,7 @@ export default {
'z-index': 10
};
if (index) {
obj['id'] = `annotation-${index}`;
loadedAnnotations.value.push(obj['id'])
loadedAnnotations.value.push(`annotation-${index}`);
}
return obj
};
Expand Down Expand Up @@ -232,7 +230,6 @@ export default {
totalHeight.value += canvas.height / ratio
await renderPage(page, canvas, viewport)
if (canvas.id !== undefined) {
console.log(canvas.id)
loadedPages.value.push(canvas.id)
}
}
Expand Down Expand Up @@ -266,6 +263,36 @@ export default {
}
};
const scrollToItem = () => {
if (props.args.scroll_to_page) {
const page = document.getElementById(`canvas_page_${props.args.scroll_to_page}`);
if (page) {
page.scrollIntoView({behavior: "smooth"});
}
} else if (props.args.scroll_to_annotation) {
const annotation = document.getElementById(`annotation-${props.args.scroll_to_annotation}`);
if (annotation) {
annotation.scrollIntoView({behavior: "smooth", block: "center"});
}
}
};
const collectAndReturnIds = () => {
const pages_ids = new Set()
const annotations_ids = new Set()
let j
for (j = 0; j < loadedAnnotations.value.length; j++) {
annotations_ids.add(loadedAnnotations.value[j]);
}
for (j = 0; j < loadedPages.value.length; j++) {
pages_ids.add(loadedPages.value[j]);
}
Streamlit.setComponentValue({"pages": Array.from(pages_ids), "annotations": Array.from(annotations_ids)})
}
const setFrameHeight = () => {
Streamlit.setFrameHeight(props.args.height || totalHeight.value);
Expand Down Expand Up @@ -293,24 +320,8 @@ export default {
if (props.args.rendering === "unwrap") {
loadPdfs(binaryDataUrl)
.then(setFrameHeight)
.then(Streamlit.setComponentReady)
.then(
function() {
const pages_ids = new Set()
const annotations_ids = new Set()
let j = 0
for(j=0; j < loadedAnnotations.value.length; j++) {
annotations_ids.add(loadedAnnotations.value[j]);
}
for(j=0; j < loadedPages.value.length; j++) {
pages_ids.add(loadedPages.value[j]);
}
Streamlit.setComponentValue({"pages": Array.from(pages_ids), "annotations": Array.from(annotations_ids)})
}
);
.then(collectAndReturnIds)
.then(Streamlit.setComponentReady);
} else {
setFrameHeight();
Streamlit.setComponentReady();
Expand All @@ -319,6 +330,7 @@ export default {
onUpdated(() => {
setFrameHeight();
scrollToItem();
});
Expand Down

0 comments on commit 6f0ee0f

Please sign in to comment.