1
0
Fork 0
why-cant-we-deploy-today/plugin/zoom/plugin.js

288 lines
7.4 KiB
JavaScript

/*!
* reveal.js Zoom plugin
*/
const Plugin = {
id: "zoom",
init: function (reveal) {
reveal.getRevealElement().addEventListener("mousedown", function (event) {
var defaultModifier = /Linux/.test(window.navigator.platform)
? "ctrl"
: "alt";
var modifier =
(reveal.getConfig().zoomKey
? reveal.getConfig().zoomKey
: defaultModifier) + "Key";
var zoomLevel = reveal.getConfig().zoomLevel
? reveal.getConfig().zoomLevel
: 2;
if (event[modifier] && !reveal.isOverview()) {
event.preventDefault();
zoom.to({
x: event.clientX,
y: event.clientY,
scale: zoomLevel,
pan: false,
});
}
});
},
destroy: () => {
zoom.reset();
},
};
export default () => Plugin;
/*!
* zoom.js 0.3 (modified for use with reveal.js)
* http://lab.hakim.se/zoom-js
* MIT licensed
*
* Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
*/
var zoom = (function () {
// The current zoom level (scale)
var level = 1;
// The current mouse position, used for panning
var mouseX = 0,
mouseY = 0;
// Timeout before pan is activated
var panEngageTimeout = -1,
panUpdateInterval = -1;
// Check for transform support so that we can fallback otherwise
var supportsTransforms = "transform" in document.body.style;
if (supportsTransforms) {
// The easing that will be applied when we zoom in/out
document.body.style.transition = "transform 0.8s ease";
}
// Zoom out if the user hits escape
document.addEventListener("keyup", function (event) {
if (level !== 1 && event.keyCode === 27) {
zoom.out();
}
});
// Monitor mouse movement for panning
document.addEventListener("mousemove", function (event) {
if (level !== 1) {
mouseX = event.clientX;
mouseY = event.clientY;
}
});
/**
* Applies the CSS required to zoom in, prefers the use of CSS3
* transforms but falls back on zoom for IE.
*
* @param {Object} rect
* @param {Number} scale
*/
function magnify(rect, scale) {
var scrollOffset = getScrollOffset();
// Ensure a width/height is set
rect.width = rect.width || 1;
rect.height = rect.height || 1;
// Center the rect within the zoomed viewport
rect.x -= (window.innerWidth - rect.width * scale) / 2;
rect.y -= (window.innerHeight - rect.height * scale) / 2;
if (supportsTransforms) {
// Reset
if (scale === 1) {
document.body.style.transform = "";
}
// Scale
else {
var origin = scrollOffset.x + "px " + scrollOffset.y + "px",
transform =
"translate(" +
-rect.x +
"px," +
-rect.y +
"px) scale(" +
scale +
")";
document.body.style.transformOrigin = origin;
document.body.style.transform = transform;
}
} else {
// Reset
if (scale === 1) {
document.body.style.position = "";
document.body.style.left = "";
document.body.style.top = "";
document.body.style.width = "";
document.body.style.height = "";
document.body.style.zoom = "";
}
// Scale
else {
document.body.style.position = "relative";
document.body.style.left = -(scrollOffset.x + rect.x) / scale + "px";
document.body.style.top = -(scrollOffset.y + rect.y) / scale + "px";
document.body.style.width = scale * 100 + "%";
document.body.style.height = scale * 100 + "%";
document.body.style.zoom = scale;
}
}
level = scale;
if (document.documentElement.classList) {
if (level !== 1) {
document.documentElement.classList.add("zoomed");
} else {
document.documentElement.classList.remove("zoomed");
}
}
}
/**
* Pan the document when the mosue cursor approaches the edges
* of the window.
*/
function pan() {
var range = 0.12,
rangeX = window.innerWidth * range,
rangeY = window.innerHeight * range,
scrollOffset = getScrollOffset();
// Up
if (mouseY < rangeY) {
window.scroll(
scrollOffset.x,
scrollOffset.y - (1 - mouseY / rangeY) * (14 / level)
);
}
// Down
else if (mouseY > window.innerHeight - rangeY) {
window.scroll(
scrollOffset.x,
scrollOffset.y +
(1 - (window.innerHeight - mouseY) / rangeY) * (14 / level)
);
}
// Left
if (mouseX < rangeX) {
window.scroll(
scrollOffset.x - (1 - mouseX / rangeX) * (14 / level),
scrollOffset.y
);
}
// Right
else if (mouseX > window.innerWidth - rangeX) {
window.scroll(
scrollOffset.x +
(1 - (window.innerWidth - mouseX) / rangeX) * (14 / level),
scrollOffset.y
);
}
}
function getScrollOffset() {
return {
x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset,
};
}
return {
/**
* Zooms in on either a rectangle or HTML element.
*
* @param {Object} options
* - element: HTML element to zoom in on
* OR
* - x/y: coordinates in non-transformed space to zoom in on
* - width/height: the portion of the screen to zoom in on
* - scale: can be used instead of width/height to explicitly set scale
*/
to: function (options) {
// Due to an implementation limitation we can't zoom in
// to another element without zooming out first
if (level !== 1) {
zoom.out();
} else {
options.x = options.x || 0;
options.y = options.y || 0;
// If an element is set, that takes precedence
if (!!options.element) {
// Space around the zoomed in element to leave on screen
var padding = 20;
var bounds = options.element.getBoundingClientRect();
options.x = bounds.left - padding;
options.y = bounds.top - padding;
options.width = bounds.width + padding * 2;
options.height = bounds.height + padding * 2;
}
// If width/height values are set, calculate scale from those values
if (options.width !== undefined && options.height !== undefined) {
options.scale = Math.max(
Math.min(
window.innerWidth / options.width,
window.innerHeight / options.height
),
1
);
}
if (options.scale > 1) {
options.x *= options.scale;
options.y *= options.scale;
magnify(options, options.scale);
if (options.pan !== false) {
// Wait with engaging panning as it may conflict with the
// zoom transition
panEngageTimeout = setTimeout(function () {
panUpdateInterval = setInterval(pan, 1000 / 60);
}, 800);
}
}
}
},
/**
* Resets the document zoom state to its default.
*/
out: function () {
clearTimeout(panEngageTimeout);
clearInterval(panUpdateInterval);
magnify({ x: 0, y: 0 }, 1);
level = 1;
},
// Alias
magnify: function (options) {
this.to(options);
},
reset: function () {
this.out();
},
zoomLevel: function () {
return level;
},
};
})();