feat(lib): add support for presenter notes (#322)

* feat(lib): add support for presenter notes

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix(test): typo

* Update test_slide.py

* Update convert.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Jérome Eertmans
2023-11-23 18:20:10 +01:00
committed by GitHub
parent b09a000c17
commit f898dd3054
7 changed files with 94 additions and 9 deletions

View File

@ -144,6 +144,7 @@ class BaseSlideConfig(BaseModel): # type: ignore
auto_next: bool = False
playback_rate: float = 1.0
reversed_playback_rate: float = 1.0
notes: str = ""
@classmethod
def wrapper(cls, arg_name: str) -> Callable[..., Any]:

View File

@ -406,9 +406,16 @@ class RevealJS(Converter):
options = self.dict()
options["assets_dir"] = assets_dir
has_notes = any(
slide_config.notes != ""
for presentation_config in self.presentation_configs
for slide_config in presentation_config.slides
)
content = revealjs_template.render(
file_to_data_uri=file_to_data_uri,
get_duration_ms=get_duration_ms,
has_notes=has_notes,
**options,
)

View File

@ -5,7 +5,7 @@ from PySide6.QtCore import Qt, QUrl, Signal, Slot
from PySide6.QtGui import QCloseEvent, QIcon, QKeyEvent, QScreen
from PySide6.QtMultimedia import QMediaPlayer
from PySide6.QtMultimediaWidgets import QVideoWidget
from PySide6.QtWidgets import QDialog, QGridLayout, QLabel, QMainWindow
from PySide6.QtWidgets import QDialog, QGridLayout, QLabel, QMainWindow, QVBoxLayout
from ..config import Config, PresentationConfig, SlideConfig
from ..logger import logger
@ -18,17 +18,25 @@ class Info(QDialog): # type: ignore[misc]
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
layout = QGridLayout()
main_layout = QVBoxLayout()
labels_layout = QGridLayout()
notes_layout = QVBoxLayout()
self.scene_label = QLabel()
self.slide_label = QLabel()
self.slide_notes = QLabel("")
self.slide_notes.setWordWrap(True)
layout.addWidget(QLabel("Scene:"), 1, 1)
layout.addWidget(QLabel("Slide:"), 2, 1)
layout.addWidget(self.scene_label, 1, 2)
layout.addWidget(self.slide_label, 2, 2)
self.setLayout(layout)
self.setFixedWidth(150)
self.setFixedHeight(80)
labels_layout.addWidget(QLabel("Scene:"), 1, 1)
labels_layout.addWidget(QLabel("Slide:"), 2, 1)
labels_layout.addWidget(self.scene_label, 1, 2)
labels_layout.addWidget(self.slide_label, 2, 2)
notes_layout.addWidget(self.slide_notes)
main_layout.addLayout(labels_layout)
main_layout.addLayout(notes_layout)
self.setLayout(main_layout)
if parent := self.parent():
self.closeEvent = parent.closeEvent
@ -312,6 +320,7 @@ class Player(QMainWindow): # type: ignore[misc]
index = self.current_slide_index
count = self.current_slides_count
self.info.slide_label.setText(f"{index+1:4d}/{count:4<d}")
self.info.slide_notes.setText(self.current_slide_config.notes)
def show(self) -> None:
super().show()

View File

@ -288,6 +288,11 @@ class BaseSlide:
Playback rate at which the reversed video is played.
Note that this is only supported by ``manim-slides present``.
:param notes:
Presenter notes, in HTML format.
Note that this is only supported by ``manim-slides present``
and ``manim-slides convert --to=html``.
:param kwargs:
Keyword arguments to be passed to
:meth:`Scene.next_section<manim.scene.scene.Scene.next_section>`,
@ -372,6 +377,29 @@ class BaseSlide:
self.next_slide()
self.wipe(square)
The following contains speaker notes. On the webbrowser,
the speaker view can be triggered by pressing :kbd:`S`.
.. manim-slides:: SpeakerNotesExample
from manim import *
from manim_slides import Slide
class SpeakerNotesExample(Slide):
def construct(self):
self.next_slide(notes="Some introduction")
square = Square(color=GREEN, side_length=2)
self.play(GrowFromCenter(square))
self.next_slide(notes="We now rotate the slide")
self.play(Rotate(square, PI / 2))
self.next_slide(notes="Bye bye")
self.zoom(square)
"""
if self._current_animation > self._start_animation:
if self.wait_time_between_slides > 0.0:

View File

@ -40,6 +40,9 @@
{% if slide_config.auto_next -%}
data-autoslide="{{ get_duration_ms(slide_config.file) }}"
{%- endif -%}>
{% if slide_config.notes != "" -%}
<aside class="notes">{{ slide_config.notes }}</aside>
{%- endif %}
</section>
{%- endfor -%}
{%- endfor -%}
@ -50,9 +53,16 @@
<!-- To include plugins, see: https://revealjs.com/plugins/ -->
{% if has_notes -%}
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{{ reveal_version }}/plugin/notes/notes.min.js"></script>
{%- endif -%}
<!-- <script src="index.js"></script> -->
<script>
Reveal.initialize({
{% if has_notes -%}
plugins: [ RevealNotes ],
{%- endif %}
// The "normal" size of the presentation, aspect ratio will
// be preserved when the presentation is scaled to fit different
// resolutions. Can be specified using percentage units.