PhotoSwipe视频

3
我想在我的 PhotoSwipe 相册中添加视频。
我阅读了这里的文档: http://photoswipe.com/documentation/custom-html-in-slides.html 不幸的是,我不明白这是什么意思: “如果您真的需要在 PhotoSwipe 中添加视频,则可以将其作为模态框添加,该模态框将在用户点击当前幻灯片时出现,您可以动态创建 DOM 中的模态框,并将其附加到 .pswp__scroll-wrap 元素之后。”
有人成功地使视频与 PhotoSwipe 可靠地工作吗?
编辑:我尝试了这个(最后一个幻灯片是视频):http://pixelkrams.de/2015/artspin 在桌面上有效,但在移动设备上破裂(视频无法启动,大小错误)。 相关代码:http://pixelkrams.de/js/main.js PhotoSwipe 初始化的片段:
    // Pass data to PhotoSwipe and initialize it
    gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, dataLarge, options);
    gallery.init();
    gallery.listen('afterChange', function() {
        detectVideo(gallery);
    });

    gallery.listen('beforeChange', function() {
       removeVideo();
    });
   gallery.listen('resize', function() { 
       if ($('.videoHolder').length > 0) updateVideoPosition(gallery);
   });
   gallery.listen('close', function() {
       removeVideo();
   });

   detectVideo(gallery);

同时提供与视频相关的功能:

function removeVideo() {
    if ($('.videoHolder').length > 0) { 
        if ($('#video').length > 0) {
            $('video')[0].pause();
            $('video')[0].src = "";
            $('.videoHolder').remove();
            $('.pswp__img').css('visibility','visible');
        } else {
            $('.videoHolder').remove();
        }
    }
}

function detectVideo(gallery) {
    var src = gallery.currItem.src;
    if (src.indexOf('video')>= 0) {
        addVideo(gallery.currItem);
        updateVideoPosition(gallery);
    }
}
function addVideo(item, vp) {
    var videofile = item.src.split(".");
    var v = $('<div />', {
                class:'videoHolder',
                css : ({'position': 'absolute','width':item.w, 'height':item.h})

    });
    v.one('click touchstart', (function() {
        var playerCode = '<video id="video" width="'+item.w+'" height="'+item.h+'" autoplay controls>' +
        '<source src="'+videofile[0]+'.mp4" type="video/mp4"></source>' +
        '<source src="'+videofile[0]+'.webm" type="video/webm"></source>' +
        '</video>';
         $(this).html(playerCode);
         $('.pswp__img').css('visibility','hidden');

    }));
    v.appendTo('.pswp__scroll-wrap');
}

function updateVideoPosition(o) {
    var item = o.currItem;
    var vp = o.viewportSize;
    var top = (vp.y - item.h)/2;
    var left = (vp.x - item.w)/2;
    $('.videoHolder').css({position:'absolute',top:top, left:left});

}

通常情况下,如果您提供您尝试过的代码和具体的错误示例,那么更容易得到好的答案。 - Marshall Davis
我已经尝试过这个(最后一张幻灯片是一个视频):http://pixelkrams.de/2015/artspin/ 可以在桌面上工作,但在移动设备上出现问题(视频无法启动,大小错误)。 - John Kornick
很好,我建议将其附加到您的实际问题中,并尽可能复制并粘贴实际代码。人们必须挖掘信息并单击未知URL链接会使他们不太可能回答。 - Marshall Davis
更新了原始问题。 - John Kornick
或者你可以直接切换到Fancybox。 - Andrew
3个回答

4

针对移动端尺寸问题,我使用了一个额外的函数,根据画廊视口大小和视频宽高比计算视频尺寸。

function setVideoSize(item, vp) {
    var w = item.w,
        h = item.h,
        vw = vp.x,
        r,
        vh;
    if (vw < w) {
        r = w/h;
        vh = vw/r;
        w = vw;
        h = vh;
    }
    return {
            w: w,
            h: h
    };
}

然后将detectVideo()中的addVideo调用更改为

addVideo(gallery.currItem, gallery.viewportSize);

将其用于现有的addVideo(item, vp)函数中。

var vsize = setVideoSize(item, vp);
var v = $('<div />', {
            class:'.videoHolder',
            css : ({'position': 'absolute','width':vsize.w, 'height':vsize.h})

同时也需要更新视频位置:updateVideoPosition(o)

var item = o.currItem;
var vp = o.viewportSize;
var vsize = setVideoSize(item, vp);
var top = (vp.y - vsize.h)/2;
var left = (vp.x - vsize.w)/2;
$('.videoHolder').css({position:'absolute',top:top, left:left});

1
这是我使用Photoswipe和YouTube&Vimeo视频的解决方案。
它是我在Stackoverflow和网上看到的JavaScript库和解决方案的混合。
样式:
<link href="photoswipe.css" rel="stylesheet">
<link href="default-skin/default-skin.css" rel="stylesheet">
<style>
  .gallery-viewer-play-video-btn-container {
    position: relative;
    cursor: pointer;
  }
  .gallery-viewer-play-video-btn-container button {
    pointer-events: none;
    position: absolute;
    outline: 0;
    border: none;
    background-color: transparent;
    padding: 0;
    color: inherit;
    text-align: inherit;
    font-size: 100%;
    font-family: inherit;
    cursor: pointer;
    line-height: inherit;    
    left: 50%;
    top: 50%;
    width: 68px;
    height: 48px;
    margin-left: -34px;
    margin-top: -24px;
    -moz-transition: opacity .25s cubic-bezier(0.0,0.0,0.2,1);
    -webkit-transition: opacity .25s cubic-bezier(0.0,0.0,0.2,1);
    transition: opacity .25s cubic-bezier(0.0,0.0,0.2,1);
  }

  .gallery-viewer-play-video-btn-container .ytp-large-play-button-bg {
    -moz-transition: fill .1s cubic-bezier(0.4,0.0,1,1),fill-opacity .1s cubic-bezier(0.4,0.0,1,1);
    -webkit-transition: fill .1s cubic-bezier(0.4,0.0,1,1),fill-opacity .1s cubic-bezier(0.4,0.0,1,1);
    transition: fill .1s cubic-bezier(0.4,0.0,1,1),fill-opacity .1s cubic-bezier(0.4,0.0,1,1);
    fill: #cc181e;
    fill-opacity: 1;
  }

  .YouTubePopUp-Wrap .loading {
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -13px;
    margin-left: -36px;
    color: #fff;
  }
</style>

标记语言(标准)

<div class="pswp pswp-chat" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe.
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides.
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>                
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>

项目

<div class="list">
    <div class="element">      
        <a data-index="0" class="media" href="file58dc530580a94.jpg" target="_blank">            
            <img src="thumb/file58dc530580a94.jpg" itemprop="thumbnail"/>
        </a>
    </div>  

    <div class="element">      
        <a data-index="1" class="media" href="file58dc530580a94.jpg" target="_blank">            
            <img src="thumb/file58dc530580a94.jpg" itemprop="thumbnail"/>
        </a>
    </div>  

    <div class="element">      
        <a data-index="2" class="media" href="file58dc530580a94.jpg" target="_blank">            
            <img src="thumb/file58dc530580a94.jpg" itemprop="thumbnail"/>
        </a>
    </div>  

    <div class="element">      
        <a data-index="3" class="media" href="file58dc530580a94.jpg" target="_blank">            
            <img src="thumb/file58dc530580a94.jpg" itemprop="thumbnail"/>
        </a>
    </div>  
</div>

脚本

<script src="photoswipe.js"></script>
<script src="photoswipe-ui-default.js"></script>
<script src="jquery.min.js"></script>
<script src="jquery-ui.min.js"></script>
<script src="YouTubePopUp.jquery.js"></script>
<script src="custom.js"></script>

YouTubePopUp.jquery.js(这是由Qassim Hassan开发的jQuery插件)。您也需要下载它。我对它进行了一些自定义更改,因此在下载后只需用我的js代码替换即可。

/*
    Name: YouTubePopUp
    Description: jQuery plugin to display YouTube or Vimeo video in PopUp, responsive and retina, easy to use.
    Version: 1.0.1
    Plugin URL: http://wp-time.com/youtube-popup-jquery-plugin/
    Written By: Qassim Hassan
    Twitter: @QQQHZ
    Websites: wp-time.com | qass.im | wp-plugins.in
    Dual licensed under the MIT and GPL licenses:
        http://www.opensource.org/licenses/mit-license.php
        http://www.gnu.org/licenses/gpl.html
    Copyright (c) 2016 - Qassim Hassan


    Mod by MaximusBaton
*/

(function ( $ ) {

    $.fn.YouTubePopUp = function(options) {

        var YouTubePopUpOptions = $.extend({
                autoplay       : 1,
                controls       : 1,
                cc_load_policy : 0,
                iv_load_policy : 3,
                rel            : 0,
                showinfo       : 0
        }, options );

        $(this).on('click', function (e) {

            var youtubeLink = $(this).attr("href");

            if( youtubeLink.match(/(youtube.com)/) ){
                var split_c = "v=";
                var split_n = 1;
            }

            if( youtubeLink.match(/(youtu.be)/) || youtubeLink.match(/(vimeo.com\/)+[0-9]/) ){
                var split_c = "/";
                var split_n = 3;
            }

            if( youtubeLink.match(/(vimeo.com\/)+[a-zA-Z]/) ){
                var split_c = "/";
                var split_n = 5;
            }

            var getYouTubeVideoID = youtubeLink.split(split_c)[split_n];

            var cleanVideoID = getYouTubeVideoID.replace(/(&)+(.*)/, "");

            if( youtubeLink.match(/(youtu.be)/) || youtubeLink.match(/(youtube.com)/) ){
                var videoEmbedLink = "https://www.youtube.com/embed/"+cleanVideoID+"?autoplay="+YouTubePopUpOptions.autoplay+"&controls="+ YouTubePopUpOptions.controls +"&cc_load_policy="+ YouTubePopUpOptions.cc_load_policy +"&iv_load_policy="+ YouTubePopUpOptions.iv_load_policy +"&rel="+ YouTubePopUpOptions.rel +"&showinfo="+ YouTubePopUpOptions.showinfo +"";
            }

            if( youtubeLink.match(/(vimeo.com\/)+[0-9]/) || youtubeLink.match(/(vimeo.com\/)+[a-zA-Z]/) ){
                var videoEmbedLink = "https://player.vimeo.com/video/"+cleanVideoID+"?autoplay="+YouTubePopUpOptions.autoplay+"";
            }

            $("body").append('<div class="YouTubePopUp-Wrap YouTubePopUp-animation"><div class="YouTubePopUp-Content"><span class="loading">Loading...</span><span class="YouTubePopUp-Close"></span><iframe src="'+videoEmbedLink+'" allowfullscreen></iframe></div></div>');
            $('.YouTubePopUp-Content iframe')[0].onload = function() {
                $('.YouTubePopUp-Wrap .loading').hide();
                $('.YouTubePopUp-Wrap iframe').show();
            };

            if( $('.YouTubePopUp-Wrap').hasClass('YouTubePopUp-animation') ){
                setTimeout(function() {
                    $('.YouTubePopUp-Wrap').removeClass("YouTubePopUp-animation");
                }, 600);
            }

            $(".YouTubePopUp-Wrap, .YouTubePopUp-Close").click(function(){
                $.event.trigger({type : 'youtubeVideoBeforeClose', link : youtubeLink});
                $(".YouTubePopUp-Wrap").addClass("YouTubePopUp-Hide").delay(515).queue(function() { $(this).remove(); });
            });

            $.event.trigger({type : 'youtubeVideoStarted', link : youtubeLink});

            e.preventDefault();

        });

        $(document).keyup(function(e) {

            if ( e.keyCode == 27 ){
                $('.YouTubePopUp-Wrap, .YouTubePopUp-Close').click();
            }

        });

    };

}( jQuery ));

custom.js(主要的js文件:)

$(document).ready(function () {

    var mediaList              = [];

    var interval,
        intervalTries = 0,
        maxIntervalTries = 40;

    mediaList.push({
        'src'   : 'file58dc530580a94.jpg',
        'w'     : 1726,
        'h'     : 2506
    });

    mediaList.push({
        'src'   : 'file58dae7f57ea15.jpg',
        'w'     : 4032,
        'h'     : 3024
    });

    mediaList.push({
        'src'   : 'file58daa7b097cc2.jpg',
        'w'     : 3799,
        'h'     : 2849
    });

    mediaList.push({
        'src'      : 'file58dc530580a94.jpg',
        'w'        : 1000,
        'h'        : 667,
        'videoSrc' : '//www.youtube.com/watch?v=a_Ypr_uV-mw'
    });


    var pswpElement = $('.pswp.pswp-chat')[0];
    $(document).on("click", ".media", function(e){
        e.preventDefault();
        var index   = $(this).data("index"),
            options = {
                index           : index,
                bgOpacity       : 0.7,
                overlayIcon     : true,
                showHideOpacity : true
            },
            gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, mediaList, options);

        gallery.init();

        gallery.listen('close', function() {
            removeVideo(gallery);
        });

        gallery.listen('beforeChange', function() {
            removeVideo(gallery);
        });

        gallery.listen('afterChange', function() { 
            detectVideo(gallery.currItem);
        });

        gallery.listen('resize', function() {
            resizeItem(gallery.currItem);
        });        

        gallery.listen('imageLoadComplete', function(index, item) { 
            resizeItem(gallery.currItem);
        });


        detectVideo(gallery.currItem);


        $(document).off('pswpTap').on('pswpTap', function(e){
            var container = $(gallery.currItem.container),
                img       = container.find('img.youtubeClass');

            if (img.length) {
                if (typeof(img.data('youtubeVideoStarted')) == 'undefined') {
                    img.data('youtubeVideoStarted', false);
                }

                if (img.data('youtubeVideoStarted') === false) {
                    img.data('youtubeVideoStarted', true);

                    if (typeof(img.data('youtubeInitialed')) == 'undefined') {
                        img.data('youtubeInitialed', false);
                    }

                    if (img.data('youtubeInitialed') === false) {
                        img.data('youtubeInitialed', true);
                        img.YouTubePopUp();
                    }

                    if (e.detail.pointerType != 'mouse') {
                        img.click();
                    }
                }
            }
        });

        $(document).off('youtubeVideoStarted').on('youtubeVideoStarted', function(e){
            var container = $(gallery.container),
                img       = container.find('img.youtubeClass[href="'+ e.link +'"]');

            if (img.length) {
                container = img.closest('.pswp__item');

                if (container.length) {
                    var buttonContainer = container.find('.gallery-viewer-play-video-btn-container');

                    img.fadeOut(200);

                    if (buttonContainer.length) {
                        buttonContainer.fadeOut(200);
                    }
                }

            }
        });

        $(document).off('youtubeVideoBeforeClose').on('youtubeVideoBeforeClose', function(e){
            var container = $(gallery.container),
                img       = container.find('img.youtubeClass[href="'+ e.link +'"]');

            if (img.length) {
                container = img.closest('.pswp__item');

                if (container.length) {
                    var buttonContainer = container.find('.gallery-viewer-play-video-btn-container');

                    img.fadeIn(300);
                    img.data('youtubeVideoStarted', false);

                    if (buttonContainer.length) {
                        buttonContainer.fadeIn(300);
                    }
                }

            }
        });
    });

    function resizeItem(item) {
        var container = $(item.container),
            children  = container.children();

        if (children.length > 1) {
            var newWidth  = $(children[ children.length - 1 ]).css('width'),
                newHeight = $(children[ children.length - 1 ]).css('height');

            children.css({
                'width'  : newWidth,
                'height' : newHeight
            });
        }
    }

    function removeVideo(gallery) {
        clearVideoInterval();

        var container        = $(gallery.container),
            buttonContainers = container.find('.gallery-viewer-play-video-btn-container');

        $.each(buttonContainers, function(){
            var $thisButtonContainer = $(this),
                container            = $thisButtonContainer.closest('.pswp__item');

            if (container.length) {
                var img = container.find('img:not(.youtubeClass)');

                $thisButtonContainer.remove();

                if (img.length) {
                    img.show();
                }
            }
        });
    }

    function detectVideo(item) {
        clearVideoInterval();

        if (typeof(item.videoSrc) != 'undefined') {
            interval = setInterval(function(){ addVideoIframe(item); }, 100);
        }
    }

    function clearVideoInterval() {
        clearInterval(interval);
        intervalTries = 0;
    }

    function addVideoIframe(item) {
        if (intervalTries >= maxIntervalTries) {
            clearVideoInterval();
            return;
        }

        intervalTries++;

        var container = $(item.container),
            img       = container.find('img:not(.youtubeClass)');

        if (img.length) {
            resizeItem(item);

            var imgSrcCode      = '_'+ img.attr('src'),
                buttonContainer = container.find('.gallery-viewer-play-video-btn-container');

            if (buttonContainer.length == 0) {
                buttonContainer = $('<div class="gallery-viewer-play-video-btn-container"><button><svg height="100%" version="1.1" viewBox="0 0 68 48" width="100%"><path class="ytp-large-play-button-bg" d="m .66,37.62 c 0,0 .66,4.70 2.70,6.77 2.58,2.71 5.98,2.63 7.49,2.91 5.43,.52 23.10,.68 23.12,.68 .00,-1.3e-5 14.29,-0.02 23.81,-0.71 1.32,-0.15 4.22,-0.17 6.81,-2.89 2.03,-2.07 2.70,-6.77 2.70,-6.77 0,0 .67,-5.52 .67,-11.04 l 0,-5.17 c 0,-5.52 -0.67,-11.04 -0.67,-11.04 0,0 -0.66,-4.70 -2.70,-6.77 C 62.03,.86 59.13,.84 57.80,.69 48.28,0 34.00,0 34.00,0 33.97,0 19.69,0 10.18,.69 8.85,.84 5.95,.86 3.36,3.58 1.32,5.65 .66,10.35 .66,10.35 c 0,0 -0.55,4.50 -0.66,9.45 l 0,8.36 c .10,4.94 .66,9.45 .66,9.45 z" fill="#1f1f1e" fill-opacity="0.81"></path><path d="m 26.96,13.67 18.37,9.62 -18.37,9.55 -0.00,-19.17 z" fill="#fff"></path><path d="M 45.02,23.46 45.32,23.28 26.96,13.67 43.32,24.34 45.02,23.46 z" fill="#ccc"></path></svg></button></div>');

                var clonedImg = img.clone();
                clonedImg.attr('href', item.videoSrc)
                    .addClass('youtubeClass')
                    .removeClass('pswp__img')
                    .css({
                        'width'  : '100%',
                        'height' : '100%'
                    });

                buttonContainer.prepend( clonedImg );
            }

            buttonContainer.css({
                    'width'  : img.outerWidth() +'px',
                    'height' : img.outerHeight() +'px'
                })
                .appendTo(container);

            img.hide();

            clearVideoInterval();
        }
    }
});

玩得开心!


0
通过jAlbum PhotoSwipe皮肤,可以http://jalbum.net/nl/skins/skin/PhotoSwipe将视频添加到PhotoSwipe画廊中。要查看,请打开示例相册:http://andrewolff.jalbum.net/Reestdal_PS/ 在皮肤代码中,我使用以下代码来处理前两张图像和下一个视频:
  // build items array
var items = [
  {
   src: 'slides/151228-112819_Kerststal.jpg',
   w: 1625,
   h: 1080,
   title: 'Vooraan: Maria\'s dorp.'
 },
  {
   src: 'slides/20150703-ch_IMG_2160.jpg',
   w: 810,
   h: 1080,
   title: 'My Cabin!<br>Hey boss, I must\'ve taken a wrong turn, cause I\'m stuck up here!'  
  },
  {
   html: '<video controls autoplay  style="padding-top: 40px;"><source src="slides/IMG_4979.mp4" type="video/mp4"></video>'
  },

这可能在理论上回答了问题,但最好包含未来用户所需的基本答案部分,并提供参考链接。 链接主导的答案 可能会因 链接腐烂 而失效。 - Mogsdad
我是新手,这个论坛上我通过在我的改进评论下点击删除标志来删除了一个改进。现在我看到原始解决方案左边有一个-1分数,这是合理的吗? - André Wolff
这正是我在寻找的。谢谢你。 - Daniel Logan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接