From 447ad917da78126acab9b529fe7254074336aa72 Mon Sep 17 00:00:00 2001 From: pacien Date: Wed, 18 Jul 2018 21:57:35 +0200 Subject: First working prototype --- pointless/viewer/presentation.js | 46 +++++++++++++++++++++++++++++++++ pointless/viewer/screen.js | 56 ++++++++++++++++++++++++++++++++++++++++ pointless/viewer/stage.js | 54 ++++++++++++++++++++++++++++++++++++++ pointless/viewer/viewer.css | 19 ++++++++++++++ pointless/viewer/viewer.js | 23 +++++++++++++++++ viewer.html | 26 +++++++++++++++++++ 6 files changed, 224 insertions(+) create mode 100644 pointless/viewer/presentation.js create mode 100644 pointless/viewer/screen.js create mode 100644 pointless/viewer/stage.js create mode 100644 pointless/viewer/viewer.css create mode 100644 pointless/viewer/viewer.js create mode 100644 viewer.html diff --git a/pointless/viewer/presentation.js b/pointless/viewer/presentation.js new file mode 100644 index 0000000..853d764 --- /dev/null +++ b/pointless/viewer/presentation.js @@ -0,0 +1,46 @@ +/* + * presentation.js + * Part of Pointless Viewer, a Beamer presentation viewer + * Copyright 2018 Pacien TRAN-GIRARD + * License: GNU GPL v3 + */ + +"use strict"; + +class Presentation { + constructor(pdf) { + this.pdf = pdf; + this.currentPageIndex = 1; + this.stage = this._setupStage(); + } + + _setupStage() { + var self = this; + var onStageReadyCallback = function() { self._onStageReady(); }; + var onNextCallback = function() { self._onNext(); }; + var onPreviousCallback = function() { self._onPrevious(); }; + return new Stage(onStageReadyCallback, onNextCallback, onPreviousCallback); + } + + _onStageReady() { + this._setPage(this.currentPageIndex); + } + + _onNext() { + if (this.currentPageIndex === this.pdf.numPages) return; + this._setPage(this.currentPageIndex + 1); + } + + _onPrevious() { + if (this.currentPageIndex === 1) return; + this._setPage(this.currentPageIndex - 1); + } + + _setPage(pageIndex) { + var self = this; + this.currentPageIndex = pageIndex; + this.pdf.getPage(this.currentPageIndex).then(function(page) { + self.stage.setPage(page); + }) + } +} diff --git a/pointless/viewer/screen.js b/pointless/viewer/screen.js new file mode 100644 index 0000000..8a6891c --- /dev/null +++ b/pointless/viewer/screen.js @@ -0,0 +1,56 @@ +/* + * screen.js + * Part of Pointless Viewer, a Beamer presentation viewer + * Copyright 2018 Pacien TRAN-GIRARD + * License: GNU GPL v3 + */ + +"use strict"; + +class Screen { + constructor(window, secondary=false) { + this.window = window; + this.secondary = secondary; + this.canvas = window.document.getElementById("screen"); + this.context = this.canvas.getContext("2d"); + this.page = null; + + var self = this; + this.window.addEventListener("resize", function() { + self._refreshPage(); + }); + } + + setPage(page) { + this.page = page; + this._refreshPage(); + } + + _resizeScreen(ratio) { + var windowRatio = this.window.innerWidth / this.window.innerHeight; + var scaleFactor = ratio / windowRatio; + this.canvas.width = this.window.innerWidth * Math.min(scaleFactor, 1); + this.canvas.height = this.window.innerHeight / Math.max(scaleFactor, 1); + } + + _setOffset() { + var xOffset = this.secondary ? -this.canvas.width : 0; + this.context.transform(1, 0, 0, 1, xOffset, 0); + } + + _paintPage() { + var renderRatio = this.canvas.height / this.page.getViewport(1).height; + var renderViewport = this.page.getViewport(renderRatio); + var renderContext = { canvasContext: this.context, viewport: renderViewport }; + this.page.render(renderContext); + } + + _refreshPage() { + if (this.page == null) return; + var viewport = this.page.getViewport(1); + var ratio = (viewport.width / 2) / viewport.height; + this._resizeScreen(ratio); + this._setOffset(); + this._paintPage(); + } +} diff --git a/pointless/viewer/stage.js b/pointless/viewer/stage.js new file mode 100644 index 0000000..fa984fe --- /dev/null +++ b/pointless/viewer/stage.js @@ -0,0 +1,54 @@ +/* + * stage.js + * Part of Pointless Viewer, a Beamer presentation viewer + * Copyright 2018 Pacien TRAN-GIRARD + * License: GNU GPL v3 + */ + +"use strict"; + +class Stage { + constructor(onReady, onNext, onPrevious) { + this.onNext = onNext; + this.onPrevious = onPrevious; + this.projector = window.open(window.location.href); + this.audienceScreen = null; + this.presenterScreen = null; + + var self = this; + this.projector.addEventListener("load", function() { + self.audienceScreen = new Screen(self.projector, false); + self.presenterScreen = new Screen(window, true); + onReady(); + }); + + this._registerEventHandler(window); + this._registerEventHandler(this.projector); + } + + setPage(page) { + this.audienceScreen.setPage(page); + this.presenterScreen.setPage(page); + } + + _registerEventHandler(window) { + var self = this; + window.addEventListener("keypress", function(event) { + self._onCommand(event); + }) + } + + _onCommand(keyboardEvent) { + switch (keyboardEvent.key) { + case "Enter": + case " ": + case "ArrowRight": + case "n": + return this.onNext(); + + case "ArrowLeft": + case "p": + return this.onPrevious(); + } + } +} diff --git a/pointless/viewer/viewer.css b/pointless/viewer/viewer.css new file mode 100644 index 0000000..dee9802 --- /dev/null +++ b/pointless/viewer/viewer.css @@ -0,0 +1,19 @@ +/* + * viewer.css + * Part of Pointless Viewer, a Beamer presentation viewer + * Copyright 2018 Pacien TRAN-GIRARD + * License: GNU GPL v3 + */ + +body { + background-color: black; + color: white; + overflow: hidden; +} + +#screen { + position: absolute; + top: 50%; + left: 50%; + transform: translateX(-50%) translateY(-50%); +} diff --git a/pointless/viewer/viewer.js b/pointless/viewer/viewer.js new file mode 100644 index 0000000..00c6f76 --- /dev/null +++ b/pointless/viewer/viewer.js @@ -0,0 +1,23 @@ +/* + * viewer.js + * Part of Pointless Viewer, a Beamer presentation viewer + * Copyright 2018 Pacien TRAN-GIRARD + * License: GNU GPL v3 + */ + +"use strict"; + +var params = function() { + var queryDict = {}; + location.search.substr(1).split("&").forEach(function(item) { + var pair = item.split("="); + queryDict[pair[0]] = pair[1]; + }); + return queryDict; +}(); + +if (window.opener == null) { + pdfjsLib.getDocument(params["file"]).then(function(pdf) { + var presentation = new Presentation(pdf); + }); +} diff --git a/viewer.html b/viewer.html new file mode 100644 index 0000000..88e4f2e --- /dev/null +++ b/viewer.html @@ -0,0 +1,26 @@ + + + + + +
+ + +