mirror of https://github.com/status-im/codimd.git
Merge pull request #1169 from pastleo/feature/slides-spotlight
add spotlight feature
This commit is contained in:
commit
d5f60d8c63
|
@ -0,0 +1,283 @@
|
||||||
|
var RevealSpotlight = window.RevealSpotlight || (function () {
|
||||||
|
|
||||||
|
//configs
|
||||||
|
var spotlightSize;
|
||||||
|
var toggleOnMouseDown;
|
||||||
|
var spotlightOnKeyPressAndHold;
|
||||||
|
var presentingCursor;
|
||||||
|
var spotlightCursor;
|
||||||
|
var initialPresentationMode;
|
||||||
|
var disablingUserSelect;
|
||||||
|
var fadeInAndOut;
|
||||||
|
var style;
|
||||||
|
var lockPointerInsideCanvas;
|
||||||
|
var getMousePos;
|
||||||
|
|
||||||
|
var drawBoard;
|
||||||
|
var isSpotlightOn = true;
|
||||||
|
var isCursorOn = true;
|
||||||
|
|
||||||
|
var lastMouseMoveEvent;
|
||||||
|
|
||||||
|
function onRevealJsReady(event) {
|
||||||
|
configure();
|
||||||
|
drawBoard = setupCanvas();
|
||||||
|
|
||||||
|
addWindowResizeListener();
|
||||||
|
|
||||||
|
addMouseMoveListener();
|
||||||
|
|
||||||
|
if (toggleOnMouseDown) {
|
||||||
|
addMouseToggleSpotlightListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spotlightOnKeyPressAndHold) {
|
||||||
|
addKeyPressAndHoldSpotlightListener(spotlightOnKeyPressAndHold);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCursor(!initialPresentationMode);
|
||||||
|
setSpotlight(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure() {
|
||||||
|
var config = Reveal.getConfig().spotlight || {};
|
||||||
|
spotlightSize = config.size || 60;
|
||||||
|
presentingCursor = config.presentingCursor || "none";
|
||||||
|
spotlightCursor = config.spotlightCursor || "none";
|
||||||
|
var useAsPointer = config.useAsPointer || false;
|
||||||
|
var pointerColor = config.pointerColor || 'red';
|
||||||
|
lockPointerInsideCanvas = config.lockPointerInsideCanvas || false;
|
||||||
|
|
||||||
|
if(lockPointerInsideCanvas){
|
||||||
|
getMousePos = getMousePosByMovement;
|
||||||
|
} else {
|
||||||
|
getMousePos = getMousePosByBoundingClientRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If using as pointer draw a transparent background and
|
||||||
|
// the mouse pointer in the specified color or default
|
||||||
|
var pointerStyle = {
|
||||||
|
backgroundFillStyle : "rgba(0, 0, 0, 0)",
|
||||||
|
mouseFillStyle : pointerColor
|
||||||
|
};
|
||||||
|
|
||||||
|
var spotlightStyle = {
|
||||||
|
backgroundFillStyle : "#000000A8",
|
||||||
|
mouseFillStyle : "#FFFFFFFF"
|
||||||
|
};
|
||||||
|
|
||||||
|
style = useAsPointer ? pointerStyle : spotlightStyle;
|
||||||
|
|
||||||
|
if (config.hasOwnProperty("toggleSpotlightOnMouseDown")) {
|
||||||
|
toggleOnMouseDown = config.toggleSpotlightOnMouseDown;
|
||||||
|
} else {
|
||||||
|
toggleOnMouseDown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.hasOwnProperty("initialPresentationMode")) {
|
||||||
|
initialPresentationMode = config.initialPresentationMode;
|
||||||
|
} else {
|
||||||
|
initialPresentationMode = toggleOnMouseDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.hasOwnProperty("spotlightOnKeyPressAndHold")) {
|
||||||
|
spotlightOnKeyPressAndHold = config.spotlightOnKeyPressAndHold;
|
||||||
|
} else {
|
||||||
|
spotlightOnKeyPressAndHold = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.hasOwnProperty("disablingUserSelect")) {
|
||||||
|
disablingUserSelect = config.disablingUserSelect;
|
||||||
|
} else {
|
||||||
|
disablingUserSelect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.hasOwnProperty("fadeInAndOut")) {
|
||||||
|
fadeInAndOut = config.fadeInAndOut;
|
||||||
|
} else {
|
||||||
|
fadeInAndOut = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupCanvas() {
|
||||||
|
var container = document.createElement('div');
|
||||||
|
container.id = "spotlight";
|
||||||
|
container.style.cssText = "position:absolute;top:0;left:0;bottom:0;right:0;z-index:99;";
|
||||||
|
if (fadeInAndOut) {
|
||||||
|
container.style.cssText += "transition: " + fadeInAndOut + "ms opacity;";
|
||||||
|
}
|
||||||
|
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
var context = canvas.getContext("2d");
|
||||||
|
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
|
||||||
|
container.appendChild(canvas);
|
||||||
|
document.body.appendChild(container);
|
||||||
|
container.style.opacity = 0;
|
||||||
|
container.style['pointer-events'] = 'none';
|
||||||
|
return {
|
||||||
|
container,
|
||||||
|
canvas,
|
||||||
|
context
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addWindowResizeListener() {
|
||||||
|
window.addEventListener('resize', function (e) {
|
||||||
|
var canvas = drawBoard.canvas;
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMouseMoveListener() {
|
||||||
|
document.body.addEventListener('mousemove', function (e) {
|
||||||
|
if(isSpotlightOn) {
|
||||||
|
showSpotlight(e);
|
||||||
|
}
|
||||||
|
lastMouseMoveEvent = e;
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMouseToggleSpotlightListener() {
|
||||||
|
|
||||||
|
window.addEventListener("mousedown", function (e) {
|
||||||
|
if (!isCursorOn) {
|
||||||
|
setSpotlight(true, e);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
window.addEventListener("mouseup", function (e) {
|
||||||
|
if (!isCursorOn) {
|
||||||
|
setSpotlight(false, e);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addKeyPressAndHoldSpotlightListener(keyCode) {
|
||||||
|
|
||||||
|
window.addEventListener("keydown", function (e) {
|
||||||
|
if (!isCursorOn && !isSpotlightOn && e.keyCode === keyCode) {
|
||||||
|
setSpotlight(true, lastMouseMoveEvent);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
window.addEventListener("keyup", function (e) {
|
||||||
|
if (!isCursorOn && e.keyCode === keyCode) {
|
||||||
|
setSpotlight(false);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleSpotlight() {
|
||||||
|
setSpotlight(!isSpotlightOn, lastMouseMoveEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSpotlight(isOn, mouseEvt) {
|
||||||
|
isSpotlightOn = isOn;
|
||||||
|
var container = drawBoard.container;
|
||||||
|
if (isOn) {
|
||||||
|
if (lockPointerInsideCanvas && document.pointerLockElement != drawBoard.canvas) {
|
||||||
|
drawBoard.canvas.requestPointerLock();
|
||||||
|
}
|
||||||
|
container.style.opacity = 1;
|
||||||
|
container.style['pointer-events'] = null;
|
||||||
|
document.body.style.cursor = spotlightCursor;
|
||||||
|
if (mouseEvt) {
|
||||||
|
showSpotlight(mouseEvt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
container.style.opacity = 0;
|
||||||
|
container.style['pointer-events'] = 'none';
|
||||||
|
document.body.style.cursor = presentingCursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function togglePresentationMode() {
|
||||||
|
setCursor(!isCursorOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCursor(isOn) {
|
||||||
|
isCursorOn = isOn;
|
||||||
|
if (isOn) {
|
||||||
|
if (disablingUserSelect) {
|
||||||
|
document.body.style.userSelect = null;
|
||||||
|
}
|
||||||
|
document.body.style.cursor = null;
|
||||||
|
} else {
|
||||||
|
if (disablingUserSelect) {
|
||||||
|
document.body.style.userSelect = "none";
|
||||||
|
}
|
||||||
|
document.body.style.cursor = presentingCursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSpotlight(mouseEvt) {
|
||||||
|
var canvas = drawBoard.canvas;
|
||||||
|
var context = drawBoard.context;
|
||||||
|
var mousePos = getMousePos(canvas, mouseEvt);
|
||||||
|
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// Create a canvas mask
|
||||||
|
var maskCanvas = document.createElement('canvas');
|
||||||
|
maskCanvas.width = canvas.width;
|
||||||
|
maskCanvas.height = canvas.height;
|
||||||
|
|
||||||
|
var maskCtx = maskCanvas.getContext('2d');
|
||||||
|
|
||||||
|
maskCtx.fillStyle = style.backgroundFillStyle;
|
||||||
|
maskCtx.fillRect(0, 0, maskCanvas.width, maskCanvas.height);
|
||||||
|
maskCtx.globalCompositeOperation = 'xor';
|
||||||
|
|
||||||
|
maskCtx.fillStyle = style.mouseFillStyle;
|
||||||
|
maskCtx.arc(mousePos.x, mousePos.y, spotlightSize, 0, 2 * Math.PI);
|
||||||
|
maskCtx.fill();
|
||||||
|
|
||||||
|
context.drawImage(maskCanvas, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mX = 0;
|
||||||
|
var mY = 0;
|
||||||
|
|
||||||
|
function getMousePosByMovement(canvas, evt) {
|
||||||
|
var movementX = evt.movementX || 0;
|
||||||
|
var movementY = evt.movementY || 0;
|
||||||
|
mX += movementX;
|
||||||
|
mY += movementY;
|
||||||
|
|
||||||
|
if (mX > canvas.clientWidth) {
|
||||||
|
mX = canvas.clientWidth;
|
||||||
|
}
|
||||||
|
if (mY > canvas.clientHeight) {
|
||||||
|
mY = canvas.clientHeight;
|
||||||
|
}
|
||||||
|
if (mX < 0) {
|
||||||
|
mX = 0;
|
||||||
|
}
|
||||||
|
if (mY < 0) {
|
||||||
|
mY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: mX,
|
||||||
|
y: mY
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMousePosByBoundingClientRect(canvas, evt) {
|
||||||
|
var rect = canvas.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
x: evt.clientX - rect.left,
|
||||||
|
y: evt.clientY - rect.top
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Reveal.addEventListener('ready', onRevealJsReady);
|
||||||
|
|
||||||
|
this.toggleSpotlight = toggleSpotlight;
|
||||||
|
this.togglePresentationMode = togglePresentationMode;
|
||||||
|
return this;
|
||||||
|
})();
|
|
@ -74,12 +74,18 @@ const defaultOptions = {
|
||||||
const meta = JSON.parse($('#meta').text())
|
const meta = JSON.parse($('#meta').text())
|
||||||
var options = meta.slideOptions || {}
|
var options = meta.slideOptions || {}
|
||||||
|
|
||||||
|
if (options.hasOwnProperty('spotlight')) {
|
||||||
|
defaultOptions.dependencies.push({
|
||||||
|
src: `${serverurl}/build/reveal.js/plugin/spotlight/spotlight.js`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (options.hasOwnProperty('allottedTime') || options.hasOwnProperty('allottedMinutes')) {
|
if (options.hasOwnProperty('allottedTime') || options.hasOwnProperty('allottedMinutes')) {
|
||||||
defaultOptions.dependencies.push({
|
defaultOptions.dependencies.push({
|
||||||
src: `${serverurl}/build/reveal.js/plugin/elapsed-time-bar/elapsed-time-bar.js`
|
src: `${serverurl}/build/reveal.js/plugin/elapsed-time-bar/elapsed-time-bar.js`
|
||||||
});
|
})
|
||||||
if (options.hasOwnProperty('allottedMinutes')) {
|
if (options.hasOwnProperty('allottedMinutes')) {
|
||||||
options.allottedTime = options.allottedMinutes * 60 * 1000;
|
options.allottedTime = options.allottedMinutes * 60 * 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue