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())
|
||||
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')) {
|
||||
defaultOptions.dependencies.push({
|
||||
src: `${serverurl}/build/reveal.js/plugin/elapsed-time-bar/elapsed-time-bar.js`
|
||||
});
|
||||
})
|
||||
if (options.hasOwnProperty('allottedMinutes')) {
|
||||
options.allottedTime = options.allottedMinutes * 60 * 1000;
|
||||
options.allottedTime = options.allottedMinutes * 60 * 1000
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue