PhotoSwipe视频

时间:2015-09-24 21:10:40

标签: javascript jquery html5 html5-video photoswipe

我想将视频添加到我的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});

}

3 个答案:

答案 0 :(得分:2)

针对移动尺寸问题,我使用了一个额外的功能,可根据gallery.viewportSize和视频宽高比计算视频尺寸。

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 :(得分:1)

通过jAlbum PhotoSwipe皮肤,请参阅http://jalbum.net/nl/skins/skin/PhotoSwipe,可以将视频添加到PhotoSwipe图库。要查看它,请打开示例相册:http://andrewolff.jalbum.net/Reestdal_PS/

我使用前2个图像的下一个代码和皮肤代码中的下一个视频:

  // 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>'
  },

答案 2 :(得分:1)

以下是我使用Photoswipe和Youtube&amp; Vimeo视频的解决方案。

这是我在Stackoverflow和网络上看到的java脚本库和解决方案的混合。

<强>花式

<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插件)。你也需要download它。我在其中进行了一些自定义更改,因此下载后只需将js-code替换为我的。

/*
    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();
        }
    }
});

玩得开心!