Typora使用技巧之结合LightBox点击图片放大查看

在Typora中,图片一旦插入,最大宽度只能是页面宽度,而无法放大查看,有时,原图片比较大,放到Typora中,完全无法看清内容。

这里使用LightBox,来实现类似WPS放大预览图片的功能。

通过更改部分代码实现自定义的需求:双击图片查看大图,鼠标移动到大图上面,按住Ctrl+滚动滑轮实现对图片进行放大缩小。点击✖️或者底部空白关闭大图。

当前环境:

  • Typora版本:1.2.4

  • LightBox版本:2.11.4

效果预览

宽图

把鼠标移动到图片上,按Ctrl+滚动滑轮实现图片放大缩小,在加载一些比较宽的图片时,滚动滑轮,会扩大图片在竖方向的显示范围,当图片在整个平面铺满全屏时,不再进行扩大显示范围,效果如下。

宽图gif效果

窄图

在加载一些比较窄的图片时,滚动滑轮,会扩大图片在横方向的显示范围,当图片在整个平面铺满全屏时,不再进行扩大显示范围,效果如下。图片太大,csdn上传失败,点击下方链接查看效果

gif动图

正常图片

正常显示。图片太大,csdn上传失败,点击下方链接查看效果
gif动图

下载LightBox

可以从Github下载,链接👉https://github.com/lokesh/lightbox2

下载之后解压,然后跟着下面步骤移动文件并对文件代码进行修改,以符合typora使用。

移动文件

找到typora的安装路径(D:\Program Files\Typora),在如下目录下新建一个lightbox文件夹,并把解压后的dist目录下的文件夹放到里面。

这里的新建路径可以自定义,但一定要把dist目录下的文件夹复制到同一个路径下,供后面window.html调用。

image-20240329164950713

下面要修改的js和css文件都在对应的js和css文件夹中

修改 lightbox.js 文件

为img标签绑定双击事件

修改enable函数,增添部分如下代码。

  // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes
  // that contain 'lightbox'. When these are clicked, start lightbox.
  Lightbox.prototype.enable = function() {
    var self = this;
    $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {
      self.start($(event.currentTarget));
      return false;
    });
    // 给img标签加上双击属性,要排除本就是双击放大的图片。
    $('body').on('dblclick', "img:not([class='lb-image'])", function(event) {
      self.start($(event.currentTarget));
      return false;
    });    
  };
修改start函数

修改start函数中的属性值,换成img对应属性,并重置imagezoom属性。

关于为何在start函数中重置imagezoom属性:

  • 我们在mousewheel事件中给image增加了的zoom属性,用于放大缩小图像
  • LightBox在打开图像后,可以通过点击✖️关闭图像,也可以点击空白关闭图像,如果不进行重置,下一次打开图像会跟随上一次打开图像的zoom属性
  // Show overlay and lightbox. If the image is part of a set, add siblings to album array.
  Lightbox.prototype.start = function($link) {
    var self    = this;
    var $window = $(window);

    $window.on('resize', $.proxy(this.sizeOverlay, this));

    this.sizeOverlay();

    this.album = [];
    var imageNumber = 0;
    // 重置image的zoom属性
    self.$image.css("zoom", "100%")
	// 修改alt 和 link
    function addToAlbum($link) {
      self.album.push({
        alt: $link.attr('data-alt') || $link.attr('alt'),
        link: $link.attr('href') || $link.attr('src'),
        title: $link.attr('data-title') || $link.attr('title')
      });
    }

还有另外一个属性data-lightbox,img没有该属性,因此这里不使用,lightbox中有一段判断是否有该属性的代码,修改不存在该属性时的逻辑代码(注释掉原有的,添加addToAlbum($link)

image-20240329164042229

修改滚动滑轮放大图片

增加mousewheel事件,当按住Ctrl+滚动滑轮实现给放大的图片再进行放大缩小。

可以搜索mousedown,在它的后面添加:

	//给放大的图片另外绑定滚轮放大缩小事件
    this.$container.on('mousewheel', function(event) {
      // 检查是否按下了Ctrl键
      if(event.ctrlKey) {
        event.delta = (event.originalEvent.wheelDelta) ? event.originalEvent.wheelDelta / 120 : -(event.originalEvent.detail || 0) / 3;
        
        var zoom = self.$image.css("zoom")
        zoom = zoom ? zoom * 100 : 100;
        zoom += event.delta * 10;
        if(zoom > 0)
          self.$image.css("zoom", zoom + "%")
                
        var imageWidth = self.$image.width();
        var imageHeight = self.$image.height();
        imageWidth = imageWidth * zoom * 0.01;
        imageHeight = imageHeight * zoom * 0.01;
        self.sizeContainer(imageWidth, imageHeight);
        
        // 阻止默认事件和事件冒泡
        event.preventDefault();
        return false;
      }
      // 如果没有按下Ctrl键,不执行缩放操作
    });
修改sizeContainer函数

对比屏幕大小,当图片大小超过屏幕大小时,显示滚动条,隐藏图片部分内容。

Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {
    var self = this;

    var oldWidth  = this.$outerContainer.outerWidth();
    var oldHeight = this.$outerContainer.outerHeight();
    var newWidth  = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right;
    var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;

    // 获取屏幕宽度和高度
    var screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    var screenHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

    function postResize() {
      // 当新尺寸适合屏幕时才调整 lb-dataContainer 尺寸
      if (newWidth <= screenWidth) {
        self.$lightbox.find('.lb-dataContainer').width(newWidth);
      }
      self.$lightbox.find('.lb-prevLink').height(newHeight);
      self.$lightbox.find('.lb-nextLink').height(newHeight);

      // Set focus on one of the two root nodes so keyboard events are captured.
      self.$overlay.trigger('focus');

      self.showImage();
    }
    // 更改outerContainer的宽和高,为后续在css文件中使用overflow做铺垫。
    if ((oldWidth !== newWidth || oldHeight !== newHeight)) {
      var newStyles = {};
    
      if (newWidth < screenWidth) {
        newStyles.width = newWidth * 1.01;
      }
      // × 关闭图标高度为30
      if (newHeight < screenHeight-35) {
        newStyles.height = newHeight * 1.01;
      }
    
      if (newStyles.width || newStyles.height) {
        this.$outerContainer.animate(newStyles, this.options.resizeDuration, 'swing', function() {
          postResize();
        });
      } else {
        postResize();
      }
  };

👻记得保存哦~

修改lightbox.css文件

lb-outerContainer增加overflow: auto;

.lb-outerContainer {
  position: relative;
  *zoom: 1;
  width: 250px;
  height: 250px;
  margin: 0 auto;
  border-radius: 4px;
  overflow: auto;
  /* Background color behind image.
     This is visible during transitions. */
  background-color: white;
}

修改window.html文件

位置:Typora安装目录\resources\window.html(这个文件实际就是Typora的主界面),如果找不到对应位置,直接在安装目录下搜索window.html

引入 css 文件

可以搜索</head>,在它的前面添加:

<!-- 在<head>标签里引入lightbox.css -->
<link rel="stylesheet" href="./style/lightbox/css/lightbox.css" crossorigin="anonymous">

image-20240330183206818

引入 js 文件

可以搜索frame.js,然后在它的后面添加:

<!-- 在文件的最后,引入lightbox.js -->
<script type="text/javascript" src="./style/lightbox/js/lightbox.js" defer="defer"></script>

image-20240329165836967

修改完成,保存。

🍻重新打开typora,快去试试吧

完整代码

下面给出对应完整的js代码

lightbox.js

/*!
 * Lightbox v2.11.4
 * by Lokesh Dhakar
 *
 * More info:
 * http://lokeshdhakar.com/projects/lightbox2/
 *
 * Copyright Lokesh Dhakar
 * Released under the MIT license
 * https://github.com/lokesh/lightbox2/blob/master/LICENSE
 *
 * @preserve
 */

// Uses Node, AMD or browser globals to create a module.
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory(require('jquery'));
    } else {
        // Browser globals (root is window)
        root.lightbox = factory(root.jQuery);
    }
}(this, function ($) {

  function Lightbox(options) {
    this.album = [];
    this.currentImageIndex = void 0;
    this.init();

    // options
    this.options = $.extend({}, this.constructor.defaults);
    this.option(options);
  }

  // Descriptions of all options available on the demo site:
  // http://lokeshdhakar.com/projects/lightbox2/index.html#options
  Lightbox.defaults = {
    albumLabel: 'Image %1 of %2',
    alwaysShowNavOnTouchDevices: false,
    fadeDuration: 600,
    fitImagesInViewport: true,
    imageFadeDuration: 600,
    // maxWidth: 800,
    // maxHeight: 600,
    positionFromTop: 50,
    resizeDuration: 700,
    showImageNumberLabel: true,
    wrapAround: false,
    disableScrolling: false,
    /*
    Sanitize Title
    If the caption data is trusted, for example you are hardcoding it in, then leave this to false.
    This will free you to add html tags, such as links, in the caption.

    If the caption data is user submitted or from some other untrusted source, then set this to true
    to prevent xss and other injection attacks.
     */
    sanitizeTitle: false
  };

  Lightbox.prototype.option = function(options) {
    $.extend(this.options, options);
  };

  Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) {
    return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages);
  };

  Lightbox.prototype.init = function() {
    var self = this;
    // Both enable and build methods require the body tag to be in the DOM.
    $(document).ready(function() {
      self.enable();
      self.build();
    });
  };

  // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes
  // that contain 'lightbox'. When these are clicked, start lightbox.
  Lightbox.prototype.enable = function() {
    var self = this;
    $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {
      self.start($(event.currentTarget));
      return false;
    });
    // 给img标签加上双击属性,要排除本就是双击放大的图片
    $('body').on('dblclick', "img:not([class='lb-image'])", function(event) {
      self.start($(event.currentTarget));
      return false;
    });    
  };

  // Build html for the lightbox and the overlay.
  // Attach event handlers to the new DOM elements. click click click
  Lightbox.prototype.build = function() {
    if ($('#lightbox').length > 0) {
        return;
    }

    var self = this;

    // The two root notes generated, #lightboxOverlay and #lightbox are given
    // tabindex attrs so they are focusable. We attach our keyboard event
    // listeners to these two elements, and not the document. Clicking anywhere
    // while Lightbox is opened will keep the focus on or inside one of these
    // two elements.
    //
    // We do this so we can prevent propogation of the Esc keypress when
    // Lightbox is open. This prevents it from intefering with other components
    // on the page below.
    //
    // Github issue: https://github.com/lokesh/lightbox2/issues/663
    $('<div id="lightboxOverlay" tabindex="-1" class="lightboxOverlay"></div><div id="lightbox" tabindex="-1" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt=""/><div class="lb-nav"><a class="lb-prev" role="button" tabindex="0" aria-label="Previous image" href="" ></a><a class="lb-next" role="button" tabindex="0" aria-label="Next image" href="" ></a></div><div class="lb-loader"><a class="lb-cancel" role="button" tabindex="0"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close" role="button" tabindex="0"></a></div></div></div></div>').appendTo($('body'));

    // Cache jQuery objects
    this.$lightbox       = $('#lightbox');
    this.$overlay        = $('#lightboxOverlay');
    this.$outerContainer = this.$lightbox.find('.lb-outerContainer');
    this.$container      = this.$lightbox.find('.lb-container');
    this.$image          = this.$lightbox.find('.lb-image');
    this.$nav            = this.$lightbox.find('.lb-nav');

    // Store css values for future lookup
    this.containerPadding = {
      top: parseInt(this.$container.css('padding-top'), 10),
      right: parseInt(this.$container.css('padding-right'), 10),
      bottom: parseInt(this.$container.css('padding-bottom'), 10),
      left: parseInt(this.$container.css('padding-left'), 10)
    };

    this.imageBorderWidth = {
      top: parseInt(this.$image.css('border-top-width'), 10),
      right: parseInt(this.$image.css('border-right-width'), 10),
      bottom: parseInt(this.$image.css('border-bottom-width'), 10),
      left: parseInt(this.$image.css('border-left-width'), 10)
    };

    // Attach event handlers to the newly minted DOM elements
    this.$overlay.hide().on('click', function() {
      self.end();
      return false;
    });

    this.$lightbox.hide().on('click', function(event) {
      if ($(event.target).attr('id') === 'lightbox') {
        self.end();
      }
    });

    this.$outerContainer.on('click', function(event) {
      if ($(event.target).attr('id') === 'lightbox') {
        self.end();
      }
      return false;
    });

    this.$lightbox.find('.lb-prev').on('click', function() {
      if (self.currentImageIndex === 0) {
        self.changeImage(self.album.length - 1);
      } else {
        self.changeImage(self.currentImageIndex - 1);
      }
      return false;
    });

    this.$lightbox.find('.lb-next').on('click', function() {
      if (self.currentImageIndex === self.album.length - 1) {
        self.changeImage(0);
      } else {
        self.changeImage(self.currentImageIndex + 1);
      }
      return false;
    });

    /*
      Show context menu for image on right-click

      There is a div containing the navigation that spans the entire image and lives above of it. If
      you right-click, you are right clicking this div and not the image. This prevents users from
      saving the image or using other context menu actions with the image.

      To fix this, when we detect the right mouse button is pressed down, but not yet clicked, we
      set pointer-events to none on the nav div. This is so that the upcoming right-click event on
      the next mouseup will bubble down to the image. Once the right-click/contextmenu event occurs
      we set the pointer events back to auto for the nav div so it can capture hover and left-click
      events as usual.
     */
    this.$nav.on('mousedown', function(event) {
      if (event.which === 3) {
        self.$nav.css('pointer-events', 'none');

        self.$lightbox.one('contextmenu', function() {
          setTimeout(function() {
              this.$nav.css('pointer-events', 'auto');
          }.bind(self), 0);
        });
      }
    });

	  //给放大的图片另外绑定滚轮放大缩小事件
    this.$container.on('mousewheel', function(event) {
      // 检查是否按下了Ctrl键
      if(event.ctrlKey) {
        event.delta = (event.originalEvent.wheelDelta) ? event.originalEvent.wheelDelta / 120 : -(event.originalEvent.detail || 0) / 3;
        
        var zoom = self.$image.css("zoom")
        zoom = zoom ? zoom * 100 : 100;
        zoom += event.delta * 10;
        if(zoom > 0)
          self.$image.css("zoom", zoom + "%")
        
               
        var imageWidth = self.$image.width();
        var imageHeight = self.$image.height();
        imageWidth = imageWidth * zoom * 0.01;
        imageHeight = imageHeight * zoom * 0.01;
        // 如果你希望容器的大小根据图片大小变化而自动调整(而不是固定为视口大小),可以取消注释下面的代码
        self.sizeContainer(imageWidth, imageHeight);
        
        // 阻止默认事件和事件冒泡
        event.preventDefault();

      }
      // 如果没有按下Ctrl键,不执行缩放操作
    });
    
    this.$lightbox.find('.lb-loader, .lb-close').on('click keyup', function(e) {
      // If mouse click OR 'enter' or 'space' keypress, close LB
      if (
        e.type === 'click' || (e.type === 'keyup' && (e.which === 13 || e.which === 32))) {
        self.end();
        return false;
      }
    });
  };

  // Show overlay and lightbox. If the image is part of a set, add siblings to album array.
  Lightbox.prototype.start = function($link) {
    var self    = this;
    var $window = $(window);

    $window.on('resize', $.proxy(this.sizeOverlay, this));

    this.sizeOverlay();

    this.album = [];
    var imageNumber = 0;
    // 重置image的zoom属性
    self.$image.css("zoom", "100%")
    function addToAlbum($link) {
      self.album.push({
        alt: $link.attr('data-alt') || $link.attr('alt'),
        link: $link.attr('href') || $link.attr('src'),
        title: $link.attr('data-title') || $link.attr('title')
      });
    }

    // Support both data-lightbox attribute and rel attribute implementations
    var dataLightboxValue = $link.attr('data-lightbox');
    var $links;

    if (dataLightboxValue) {
      $links = $($link.prop('tagName') + '[data-lightbox="' + dataLightboxValue + '"]');
      for (var i = 0; i < $links.length; i = ++i) {
        addToAlbum($($links[i]));
        if ($links[i] === $link[0]) {
          imageNumber = i;
        }
      }
    } else {
      // if ($link.attr('rel') === 'lightbox') {
      //   // If image is not part of a set
      //   addToAlbum($link);
      // } else {
      //   // If image is part of a set
      //   $links = $($link.prop('tagName') + '[rel="' + $link.attr('rel') + '"]');
      //   for (var j = 0; j < $links.length; j = ++j) {
      //     addToAlbum($($links[j]));
      //     if ($links[j] === $link[0]) {
      //       imageNumber = j;
      //     }
      //   }
      // }
      addToAlbum($link);
    }

    // Position Lightbox
    var top  = $window.scrollTop() + this.options.positionFromTop;
    var left = $window.scrollLeft();
    this.$lightbox.css({
      top: top + 'px',
      left: left + 'px'
    }).fadeIn(this.options.fadeDuration);

    // Disable scrolling of the page while open
    if (this.options.disableScrolling) {
      $('body').addClass('lb-disable-scrolling');
    }

    this.changeImage(imageNumber);
  };

  // Hide most UI elements in preparation for the animated resizing of the lightbox.
  Lightbox.prototype.changeImage = function(imageNumber) {
    var self = this;
    var filename = this.album[imageNumber].link;
    var filetype = filename.split('.').slice(-1)[0];
    var $image = this.$lightbox.find('.lb-image');

    // Disable keyboard nav during transitions
    this.disableKeyboardNav();

    // Show loading state
    this.$overlay.fadeIn(this.options.fadeDuration);
    $('.lb-loader').fadeIn('slow');
    this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();
    this.$outerContainer.addClass('animating');

    // When image to show is preloaded, we send the width and height to sizeContainer()
    var preloader = new Image();
    preloader.onload = function() {
      var $preloader;
      var imageHeight;
      var imageWidth;
      var maxImageHeight;
      var maxImageWidth;
      var windowHeight;
      var windowWidth;

      $image.attr({
        'alt': self.album[imageNumber].alt,
        'src': filename
      });

      $preloader = $(preloader);

      $image.width(preloader.width);
      $image.height(preloader.height);

      var aspectRatio = preloader.width / preloader.height;

      windowWidth = $(window).width();
      windowHeight = $(window).height();

      // Calculate the max image dimensions for the current viewport.
      // Take into account the border around the image and an additional 10px gutter on each side.
      maxImageWidth  = windowWidth - self.containerPadding.left - self.containerPadding.right - self.imageBorderWidth.left - self.imageBorderWidth.right - 20;
      maxImageHeight = windowHeight - self.containerPadding.top - self.containerPadding.bottom - self.imageBorderWidth.top - self.imageBorderWidth.bottom - self.options.positionFromTop - 70;

      /*
      Since many SVGs have small intrinsic dimensions, but they support scaling
      up without quality loss because of their vector format, max out their
      size inside the viewport.
      */
      if (filetype === 'svg') {
        if (aspectRatio >= 1) {
          imageWidth = maxImageWidth;
          imageHeight = parseInt(maxImageWidth / aspectRatio, 10);
        } else {
          imageWidth = parseInt(maxImageHeight / aspectRatio, 10);
          imageHeight = maxImageHeight;
        }
        $image.width(imageWidth);
        $image.height(imageHeight);

      } else {

        // Fit image inside the viewport.
        if (self.options.fitImagesInViewport) {

          // Check if image size is larger then maxWidth|maxHeight in settings
          if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {
            maxImageWidth = self.options.maxWidth;
          }
          if (self.options.maxHeight && self.options.maxHeight < maxImageHeight) {
            maxImageHeight = self.options.maxHeight;
          }

        } else {
          maxImageWidth = self.options.maxWidth || preloader.width || maxImageWidth;
          maxImageHeight = self.options.maxHeight || preloader.height || maxImageHeight;
        }

        // Is the current image's width or height is greater than the maxImageWidth or maxImageHeight
        // option than we need to size down while maintaining the aspect ratio.
        if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {
          if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {
            imageWidth  = maxImageWidth;
            imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);
            $image.width(imageWidth);
            $image.height(imageHeight);
          } else {
            imageHeight = maxImageHeight;
            imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);
            $image.width(imageWidth);
            $image.height(imageHeight);
          }
        }
      }

      self.sizeContainer($image.width(), $image.height());
    };

    // Preload image before showing
    preloader.src = this.album[imageNumber].link;
    this.currentImageIndex = imageNumber;
  };

  // Stretch overlay to fit the viewport
  Lightbox.prototype.sizeOverlay = function() {
    var self = this;
    /*
    We use a setTimeout 0 to pause JS execution and let the rendering catch-up.
    Why do this? If the `disableScrolling` option is set to true, a class is added to the body
    tag that disables scrolling and hides the scrollbar. We want to make sure the scrollbar is
    hidden before we measure the document width, as the presence of the scrollbar will affect the
    number.
    */
    setTimeout(function() {
      self.$overlay
        .width($(document).width())
        .height($(document).height());

    }, 0);
  };

  // Animate the size of the lightbox to fit the image we are showing
  // This method also shows the the image.
  Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {
    var self = this;

    var oldWidth  = this.$outerContainer.outerWidth();
    var oldHeight = this.$outerContainer.outerHeight();
    var newWidth  = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right;
    var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;

    // 获取屏幕宽度和高度
    var screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
    var screenHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

    function postResize() {
      // 当新尺寸适合屏幕时才调整 lb-dataContainer 尺寸
      if (newWidth <= screenWidth) {
        self.$lightbox.find('.lb-dataContainer').width(newWidth);
      }
      self.$lightbox.find('.lb-prevLink').height(newHeight);
      self.$lightbox.find('.lb-nextLink').height(newHeight);

      // Set focus on one of the two root nodes so keyboard events are captured.
      self.$overlay.trigger('focus');

      self.showImage();
    }
    // 更改outerContainer的宽和高
    if ((oldWidth !== newWidth || oldHeight !== newHeight)) {
      var newStyles = {};
    
      if (newWidth < screenWidth) {
        newStyles.width = newWidth * 1.01;
      }
      // × 关闭图标高度为30
      if (newHeight < screenHeight-35) {
        newStyles.height = newHeight * 1.01;
      }
    
      if (newStyles.width || newStyles.height) {
        this.$outerContainer.animate(newStyles, this.options.resizeDuration, 'swing', function() {
          postResize();
        });
      } else {
        postResize();
      }
    }
  };

  // Display the image and its details and begin preload neighboring images.
  Lightbox.prototype.showImage = function() {
    this.$lightbox.find('.lb-loader').stop(true).hide();
    this.$lightbox.find('.lb-image').fadeIn(this.options.imageFadeDuration);

    this.updateNav();
    this.updateDetails();
    this.preloadNeighboringImages();
    this.enableKeyboardNav();
  };

  // Display previous and next navigation if appropriate.
  Lightbox.prototype.updateNav = function() {
    // Check to see if the browser supports touch events. If so, we take the conservative approach
    // and assume that mouse hover events are not supported and always show prev/next navigation
    // arrows in image sets.
    var alwaysShowNav = false;
    try {
      document.createEvent('TouchEvent');
      alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;
    } catch (e) {}

    this.$lightbox.find('.lb-nav').show();

    if (this.album.length > 1) {
      if (this.options.wrapAround) {
        if (alwaysShowNav) {
          this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');
        }
        this.$lightbox.find('.lb-prev, .lb-next').show();
      } else {
        if (this.currentImageIndex > 0) {
          this.$lightbox.find('.lb-prev').show();
          if (alwaysShowNav) {
            this.$lightbox.find('.lb-prev').css('opacity', '1');
          }
        }
        if (this.currentImageIndex < this.album.length - 1) {
          this.$lightbox.find('.lb-next').show();
          if (alwaysShowNav) {
            this.$lightbox.find('.lb-next').css('opacity', '1');
          }
        }
      }
    }
  };

  // Display caption, image number, and closing button.
  Lightbox.prototype.updateDetails = function() {
    var self = this;

    // Enable anchor clicks in the injected caption html.
    // Thanks Nate Wright for the fix. @https://github.com/NateWr
    if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&
      this.album[this.currentImageIndex].title !== '') {
      var $caption = this.$lightbox.find('.lb-caption');
      if (this.options.sanitizeTitle) {
        $caption.text(this.album[this.currentImageIndex].title);
      } else {
        $caption.html(this.album[this.currentImageIndex].title);
      }
      $caption.fadeIn('fast');
    }

    if (this.album.length > 1 && this.options.showImageNumberLabel) {
      var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);
      this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');
    } else {
      this.$lightbox.find('.lb-number').hide();
    }

    this.$outerContainer.removeClass('animating');

    this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {
      return self.sizeOverlay();
    });
  };

  // Preload previous and next images in set.
  Lightbox.prototype.preloadNeighboringImages = function() {
    if (this.album.length > this.currentImageIndex + 1) {
      var preloadNext = new Image();
      preloadNext.src = this.album[this.currentImageIndex + 1].link;
    }
    if (this.currentImageIndex > 0) {
      var preloadPrev = new Image();
      preloadPrev.src = this.album[this.currentImageIndex - 1].link;
    }
  };

  Lightbox.prototype.enableKeyboardNav = function() {
    this.$lightbox.on('keyup.keyboard', $.proxy(this.keyboardAction, this));
    this.$overlay.on('keyup.keyboard', $.proxy(this.keyboardAction, this));
  };

  Lightbox.prototype.disableKeyboardNav = function() {
    this.$lightbox.off('.keyboard');
    this.$overlay.off('.keyboard');
  };

  Lightbox.prototype.keyboardAction = function(event) {
    var KEYCODE_ESC        = 27;
    var KEYCODE_LEFTARROW  = 37;
    var KEYCODE_RIGHTARROW = 39;

    var keycode = event.keyCode;
    if (keycode === KEYCODE_ESC) {
      // Prevent bubbling so as to not affect other components on the page.
      event.stopPropagation();
      this.end();
    } else if (keycode === KEYCODE_LEFTARROW) {
      if (this.currentImageIndex !== 0) {
        this.changeImage(this.currentImageIndex - 1);
      } else if (this.options.wrapAround && this.album.length > 1) {
        this.changeImage(this.album.length - 1);
      }
    } else if (keycode === KEYCODE_RIGHTARROW) {
      if (this.currentImageIndex !== this.album.length - 1) {
        this.changeImage(this.currentImageIndex + 1);
      } else if (this.options.wrapAround && this.album.length > 1) {
        this.changeImage(0);
      }
    }
  };

  // Closing time. :-(
  Lightbox.prototype.end = function() {
    this.disableKeyboardNav();
    $(window).off('resize', this.sizeOverlay);
    this.$lightbox.fadeOut(this.options.fadeDuration);
    this.$overlay.fadeOut(this.options.fadeDuration);

    if (this.options.disableScrolling) {
      $('body').removeClass('lb-disable-scrolling');
    }
  };

  return new Lightbox();
}));

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值