]> _ Git - fluidbook-html5.git/commitdiff
Dynamic layout selection + code refactoring. WIP #2087 @5
authorStephen Cameron <stephen@cubedesigners.com>
Thu, 30 Aug 2018 13:05:37 +0000 (15:05 +0200)
committerStephen Cameron <stephen@cubedesigners.com>
Thu, 30 Aug 2018 13:05:37 +0000 (15:05 +0200)
js/libs/fluidbook/fluidbook.bookmarks.js
js/libs/fluidbook/fluidbook.links.js

index dc46359490e1d2c542ce7c123e9a7a2c99c33c23..7d65ddd24b6291280a9e6eec015761779ba3e49f 100644 (file)
@@ -24,7 +24,6 @@ function FluidbookBookmarks(fluidbook) {
 FluidbookBookmarks.prototype = {
     init: function () {
         var $this = this;
-        console.log('init');
         $(document).on('click touchend', '.bookmark', function () {
             $this.toggleBookmark(parseInt($(this).attr('data-page')));
             $this.fluidbook.tooltip.hideTooltip();
@@ -484,4 +483,4 @@ FluidbookBookmarks.prototype = {
         index += '</div>';
         return index;
     }
-};
\ No newline at end of file
+};
index 048621e0b2aa16a214a4d0466aadbf4094456318..5e9f64a13f51cc5b4fb5b9d2e0ffe0515313390e 100644 (file)
@@ -189,30 +189,29 @@ FluidbookLinks.prototype = {
 
     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);
 
@@ -229,38 +228,55 @@ FluidbookLinks.prototype = {
             }
         }
 
-        // 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'));
@@ -301,29 +317,52 @@ FluidbookLinks.prototype = {
             // 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
@@ -332,42 +371,40 @@ FluidbookLinks.prototype = {
             // 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);
             });
 
         });