Merge pull request #1169 from pastleo/feature/slides-spotlight

add spotlight feature
This commit is contained in:
Raccoon 2019-06-27 17:37:33 +08:00 committed by GitHub
commit d5f60d8c63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 291 additions and 2 deletions

View File

@ -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;
})();

View File

@ -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
} }
} }