zoomLink: function (link) {
+ var $this = this,
+ $link = $(link),
+ links = [],
+ zoomMargin = 50,
+ zoomZonesGap = 30, // Space between grouped zoom links
+ gapsTotal,
+ availableWidth = $(window).width() - (2 * zoomMargin),
+ availableHeight = $(window).height() - (2 * zoomMargin);
+
// If the interface is zoomed in, we must zoom out first
if (this.fluidbook.zoom.zoom > 1) {
- //currentScale = this.fluidbook.desktop.desktopScale; // Get current scale so the size of the popup can be calculated correctly
+
+ // Zoom out
+ this.fluidbook.zoom.resetZoom();
// Wait for clickZoom out to finish before trying again to open zoom link
$(this.fluidbook).one('fluidbook.zoom.out.end', function () {
$this.zoomLink(link);
});
- // Zoom out
- this.fluidbook.zoom.resetZoom();
return false;
}
-
-
- var $this = this,
- $link = $(link),
- links = [],
- zoomMargin = 50,
- zoomZonesGap = 30, // Space between grouped zoom links
- availableWidth = $(window).width() - (2 * zoomMargin),
- availableHeight = $(window).height() - (2 * zoomMargin);
-
// Add clicked zoom link to the collection
links.push($link);
}
}
- // Sort links so topmost (lowest Y value) link is first. This allows it to be first/top when placed.
- links.sort(function(a, b) {
- return a.data('y') - b.data('y');
- });
+ //===============
+ // Calculate space taken by between blocks (always 1 less gap than total blocks)
+ gapsTotal = (links.length - 1) * zoomZonesGap;
// Calculate positions and scaling for all zoomLink blocks
- // First, get max height of all zoomLink blocks
- var zoomGroupHeight = links.reduce(function(sum, zoomLink) {
+ // First, calculate stacked height of all zoomLink blocks
+ var stackedHeight = gapsTotal + links.reduce(function(sum, zoomLink) {
return sum + (zoomLink.data('height') * zoomLink.data('maxzoom'));
}, 0);
+ // Calculate side-by-side width of all zoomLink blocks
+ var sideBySideWidth = gapsTotal + links.reduce(function(sum, zoomLink) {
+ return sum + (zoomLink.data('width') * zoomLink.data('maxzoom'));
+ }, 0);
+
// Find widest element in collection
- var zoomGroupMaxWidth = links.reduce(function(maxWidth, zoomLink) {
+ var widestLink = links.reduce(function(maxWidth, zoomLink) {
var width = (zoomLink.data('width') * zoomLink.data('maxzoom'));
return (width > maxWidth) ? width : maxWidth;
}, 0);
+ // Find tallest element in collection
+ var tallestLink = links.reduce(function(maxHeight, zoomLink) {
+ var height = (zoomLink.data('height') * zoomLink.data('maxzoom'));
+ return (height > maxHeight) ? height : maxHeight;
+ }, 0);
- // Todo: figure out which will offer best fit: stacked or side-by-side blocks
-
- // Count gaps between blocks (always 1 less gap than total blocks)
- // For now we're assuming blocks are stacked, not side-by-side...
- zoomGroupHeight += (links.length - 1) * zoomZonesGap;
-
- var zoomGroupScale = Math.min(availableHeight / zoomGroupHeight, availableWidth / zoomGroupMaxWidth, 1);
+ // Compare scaling required for each layout of blocks
+ var stackedScale = Math.min(availableHeight / stackedHeight, availableWidth / widestLink, 1),
+ sideBySideScale = Math.min(availableHeight / tallestLink, availableWidth / sideBySideWidth, 1),
+ groupScale = (stackedScale > sideBySideScale) ? stackedScale : sideBySideScale,
+ layout = (stackedScale > sideBySideScale) ? 'stacked' : 'side-by-side';
- zoomGroupHeight = zoomGroupHeight * zoomGroupScale;
+ // Apply scaling for the group so it is accounted for in later calculations
+ stackedHeight *= groupScale;
+ sideBySideWidth *= groupScale;
+ // Sort links so they are displayed in a natural order when zooming
+ // When stacked: highest link on page will come first
+ // When side-by-side: leftmost link on page will come first
+ links.sort(function(a, b) {
+ if (layout == 'stacked') {
+ return a.data('y') - b.data('y'); // Lowest Y co-ordinates first
+ } else {
+ return a.offset().left - b.offset().left; // Lowest X co-ordinates first
+ }
+ });
- // Y position of first block (so both blocks are vertically centred)
- var zoomGroupY = Math.round((availableHeight - zoomGroupHeight) / 2);
links.forEach(function(zoomLink, index) {
// console.log(index, 'Found link with ID: ' + zoomLink.attr('id'));
// link editor width (baseWidth) and comparing it to the actual link width.
//maxZoom = maxZoom / (box.width / baseWidth); // Adjusted maxZoom level...
- // Apply any necessary group scaling to the individual element
- baseHeight = baseHeight * zoomGroupScale;
- baseWidth = baseWidth * zoomGroupScale;
+ // Apply any necessary group scaling to the individual element...
+ baseHeight *= groupScale;
+ baseWidth *= groupScale;
- // Calculate best scale factor to fit and also to honour the maxZoom level
+ // Then calculate best scale factor to fit and also to honour the maxZoom level
zoomScale = Math.min((availableWidth / baseWidth), (availableHeight / baseHeight), maxZoom);
// Dimensions of the final popup
zoomWidth = baseWidth * zoomScale;
zoomHeight = baseHeight * zoomScale;
- // Calculate translate co-ordinates so image is centred correctly
- // Values are rounded so we don't end up with image being positioned between pixels, which causes blurring
- zoomX = Math.round((availableWidth / 2) - parent.offset().left - (zoomWidth / 2) + zoomMargin);
- // zoomY = Math.round((availableHeight / 2) - parent.offset().top - (zoomHeight / 2) + zoomMargin);
+ //=========
+ // Position elements based on the layout
+ // There are two possible layouts: stacked or side-by-side
+ if (layout == 'stacked') {
+ // Calculate translate co-ordinates so image is centred correctly
+ // Values are rounded so we don't end up with image being positioned between pixels, which causes blurring
+ zoomX = Math.round((availableWidth / 2) - parent.offset().left - (zoomWidth / 2) + zoomMargin);
+
+ // Y position of first block (so both blocks are vertically centred)
+ var groupY = Math.round((availableHeight - stackedHeight) / 2);
- // If this is the first / only block, use calculated zoomGroupY position
- if (index == 0) {
- zoomY = zoomGroupY - parent.offset().top + zoomMargin;
+ // If this is the first / only block, use calculated groupY position
+ if (index == 0) {
+ zoomY = groupY - parent.offset().top + zoomMargin;
- // Otherwise, calculateY position based on first element position
+ // Otherwise, calculate Y position based on first element position
+ } else {
+ zoomY = Math.round(groupY + links[0].data('height') * links[0].data('maxzoom') * groupScale + zoomZonesGap + zoomMargin - parent.offset().top);
+ }
} else {
- zoomY = Math.round(zoomGroupY + links[0].data('height') * links[0].data('maxzoom') * zoomGroupScale + zoomZonesGap + zoomMargin - parent.offset().top);
+ // Side-by-side layout
+ // Vertically centre each block
+ zoomY = Math.round((availableHeight / 2) - parent.offset().top - (zoomHeight / 2) + zoomMargin);
+
+ // X position of first block (so both blocks are horizontally centred)
+ var groupX = Math.round((availableWidth - sideBySideWidth) / 2);
+
+ // If this is the first / only block, use calculated groupX position
+ if (index == 0) {
+ zoomX = groupX - parent.offset().left + zoomMargin;
+
+ // Otherwise, calculate X position based on first element position
+ } else {
+ zoomX = Math.round(groupX + (links[0].data('width') * links[0].data('maxzoom') * groupScale) + zoomZonesGap + zoomMargin - parent.offset().left);
+ }
}
// Keep starting scale with zoom element so it can be used when zooming back out
// Initial position of the zoom box - should sit over the link and match
// size and position so that the element appears to zoom from the link
z.css({
- transform: 'translateX(0) translateY(0) scale(' + z.data('starting-scale') + ')',
- width: zoomWidth,
- height: zoomHeight,
- left: Math.round(box.left),
- top: Math.round(box.top)
+ transform: 'translateX(0) translateY(0) scale(' + z.data('starting-scale') + ')',
+ width: zoomWidth,
+ height: zoomHeight,
+ left: Math.round(box.left),
+ top: Math.round(box.top)
});
- // z.find('img').remove();
// Load image before running zoom up animation
this.fluidbook.displayLoader();
loadImage(zoomImage, function (img) {
- //z.append(img);
-
- // Image is set as a background for better scaling / fitting via CSS
- z.css('background-image', 'url(' + img.src + ')');
- this.fluidbook.hideLoader();
- z.show();
- $this.showOverlay();
- // Trigger zoom up animation just after showing zoom element
- setTimeout(function () {
- z.css({
- boxShadow: '0 0 100px rgba(0,0,0,0.3)',
- transform: 'translateX(' + zoomX + 'px) translateY(' + zoomY + 'px) scale(1)'
- });
- }, 50);
-
- // Hide close button initially so it only shows when zoom finishes.
- $(".zoomPopupClose").css('opacity', 0);
-
- $this.fluidbook.stats.track(2, $this.fluidbook.currentPage);
-
- // Display close button after zoom animation has finished
- setTimeout(function () {
- $(".zoomPopupClose").css('opacity', 1);
- }, 500);
+ // Image is set as a background for better scaling / fitting via CSS
+ z.css('background-image', 'url(' + img.src + ')');
+ this.fluidbook.hideLoader();
+ z.show();
+ $this.showOverlay();
+
+ // Trigger zoom up animation just after showing zoom element
+ setTimeout(function () {
+ z.css({
+ boxShadow: '0 0 100px rgba(0,0,0,0.3)',
+ transform: 'translateX(' + zoomX + 'px) translateY(' + zoomY + 'px) scale(1)'
+ });
+ }, 50);
+
+ // Hide close button initially so it only shows when zoom finishes.
+ $('.zoomPopupClose').css('opacity', 0);
+
+ $this.fluidbook.stats.track(2, $this.fluidbook.currentPage);
+
+ // Display close button after zoom animation has finished
+ setTimeout(function () {
+ $('.zoomPopupClose').css('opacity', 1);
+ }, 500);
});
});