PhotoSwipe: closing gallery animates wrong rectangle (thumbnail)

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-13 05:57:59

问题


I'm new to Javascript and I have a problem implementing PhotoSwipe plugin:

I'm trying to implement PhotoSwipe plugin for a web page using jQuery. Most of it is working correctly (opening a gallery, navigating slides). The problem happens when I close the gallery. The problem:

I click on image 1, this opens PhotoSwipe lightbox, I navigate to slide 2, and then close the gallery. This closes the gallery. But closing animation is played for image 1, while I am expecting it to be played for Image 2.

It works correctly on PhotoSwipe demo page, so it is an error in my code. If I copy/paste demo page Javascript code, it works correctly.

I believe I am missing some code that binds currently shown slide with respective thumbnail. My main issue with demo page is: I have a hard time understanding vanilla JS demo, what part is responsible for what action. Please help me find missing functionality.

Here's my code for PhotoSwipe "click to start gallery" event:

$('.my-gallery').each( function() {
    var $pic     = $(this);
    var items = itemArray;

    var $pswp = $('.pswp')[0];
    $pic.on('click', 'figure', function(event) {
        event.preventDefault();

        var $index = $(this).index();
        var options = {
            index: $index,
            getThumbBoundsFn: function(index) {
                // get element we clicked on to determine its position in window
                var thumbnail = event.target;
                // get position of element relative to viewport
                var rect = thumbnail.getBoundingClientRect();
                // get window scroll Y
                var pageYScroll = window.pageYOffset ||
                    document.documentElement.scrollTop; 
                return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
            }
        }
        // Initialize PhotoSwipe
        var lightBox = new PhotoSwipe($pswp, PhotoSwipeUI_Default, items, options);
        lightBox.init();
    });
});

My gallery (stripped down to 2 slides):

<div class="row my-gallery" itemscope itemtype="http://schema.org/ImageGallery" id="img-gallery">
    <figure itemprop="associatedMedia" itemscope="" itemtype="http://schema.org/ImageObject">
        <a href="images/nature/DSC_7216.jpg" itemprop="contentUrl" data-size="1200x795">
            <img src="images/nature/DSC_7216_t.jpg" itemprop="thumbnail">
        </a>
    </figure>
    <figure itemprop="associatedMedia" itemscope="" itemtype="http://schema.org/ImageObject">
        <a href="images/nature/DSC_7218.jpg" itemprop="contentUrl" data-size="1200x795">
            <img src="images/nature/DSC_7218_t.jpg" itemprop="thumbnail">
        </a>
    </figure>
</div>

Item array is generated from JSON:

[
    {
        "src": "images/nature/DSC_7216.jpg",
        "msrc": "images/nature/DSC_7216_t.jpg",
        "w":1200,
        "h":795
    },
    {
        "src": "images/nature/DSC_7218.jpg",
        "msrc": "images/nature/DSC_7218_t.jpg",
        "w":1200,
        "h":795
    }
]

JSON is hardcoded into a p element, is parsed using jQuery parser:

var itemArray = jQuery.parseJSON($(imageListSelector).html());

You can find the full page with problem on GitHub

PhotoSwipe demo on Codepen

Can you help me find what I am missing?

Edit: I've tracked the issue down to this part of code in the original PhotoSwipe demo:

var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail

If I replace this part with a fixed thumbnail selector (like I have in my jQuery - it contains "event target" reference), I can force PhotoSwipe demo to repeat my behavior - zoom out gets performed on same image. Not exactly the same thing that happens in my case, but close enough.

Now I just need to figure out how to change my getThumbBoundsFn to use actual thumbnail reference instead of event.target... I'll probably have to update my itemArray to include links to figure element, like the original PhotoSwipe demo. As I wrote earlier, I'm still new to Javascript, so figuring out some things takes time. Any help will be appreciated.


回答1:


Figured it out myself. I really screwed things up by using event.target. The correct way of working with PhotoSwipe requires me to provide actual DOM element instead of a fixed one (like event target).

The correct way of doing this is just like demo: save DOM element (selector) when creating itemArray use DOM element from itemArray in order to provide correct element to calculate bounding rectangle.

Correct jQuery code:

var gallerySelector = "#img-gallery";
var imageListSelector = "#imageList";
// parse server reply (JSON, imitated, saved into a tag)
var itemArray = jQuery.parseJSON($(imageListSelector).html());

var index = 1;
// HTML structure of gallery image
var imageHTML = "<figure class=\"col-xs-12 col-sm-6 col-md-4\" " + 
    "itemprop=\"associatedMedia\" itemscope " + 
    "itemtype=\"http://schema.org/ImageObject\">\n" +
    "<a href=\"{imageSource}\" itemprop=\"contentUrl\" data-size=\"{imageSize}\">\n" +
    "<img class=\"img-responsive\" src=\"{imageThumb}\" itemprop=\"thumbnail\" />\n" +
    "</a>\n</figure>";
// generate images based on JSON request (imitated) and appended them to the page
itemArray.forEach(function(item) {
    var imageTags = imageHTML.replace("{imageSource}", item.src);
    var imageTags = imageTags.replace("{imageSize}", (""+item.w+"x"+item.h));
    var imageTags = imageTags.replace("{imageThumb}", item.msrc);
    $(gallerySelector).append(imageTags);
    item.el = $(gallerySelector + " figure:last img")[0];
});

$('.my-gallery').each( function() {
    var $pic     = $(this);
    var $pswp = $('.pswp')[0];
    $pic.on('click', 'figure', function(event) {
        event.preventDefault();
        var $index = $(this).index();
        var options = {
            index: $index,
            getThumbBoundsFn: function(index) {
                // get element we clicked on to determine its position in window
                //var thumbnail = event.target;
                var thumbnail = itemArray[index].el;
                // get position of element relative to viewport
                var rect = thumbnail.getBoundingClientRect();
                // get window scroll Y
                var pageYScroll = window.pageYOffset ||
                    document.documentElement.scrollTop; 
                return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
            }
        }
        // Initialize PhotoSwipe
        var lightBox = new PhotoSwipe($pswp, PhotoSwipeUI_Default, itemArray, options);
        lightBox.init();
    });
});

Summary of changes:

added item.el property, which saves last added element when it is appended to the gallery (in my case - figure img, since I need the img object to calculate its bounding rectangle).

Replaced event.target with respective itemArray[index].el (previously saved node).

Hope this helps! It took me a couple of hours and some trial and error with PhotoSwipe demo page to figure this out.



来源:https://stackoverflow.com/questions/36899680/photoswipe-closing-gallery-animates-wrong-rectangle-thumbnail

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!