Closed julianxhokaxhiu closed 6 years ago
Playing HTML5 video blocks touch events on many mobile browsers, so swiping won't work.
This feature is planned, but no via raw iframe in slide like Swipebox does it, more like RoyalSlider does this (with "cover" image http://dimsemenov.com/plugins/royal-slider/video-gallery/)
Cool stuff, I like that Idea too! I didn't knew this one before
Support for videos using a popular library like Video.js would be nice too (which is HTML5 video where available but falls back to flash for stuff like HLS which Chrome doesn't natively support). I'm about to deploy that for usage with the longer HLS videos I want to support on my photoblog.
Hi Dmitry,
Glad to hear that the video feature like on RoyalSlider will be implemented on PhotoSwipe. Meanwhile, can you provide an example of the implementation? I'd like to do it myself first before it's officially implemented. In the docs it said that this can be done by inserting an element after .pswp__scroll-wrap.
Thank you!
As an experiment to see what is needed, I added a video object as following the html guidelines. It is bare HTML5 video, and not wrapped with things like flash fallbacks etc. The video does somewhat work, but there are several problems.
I'll implement my own workarounds, but am also looking forward to this being a standard part of photoswipe.
you may consider plyr
@cmnstmntmn what are your trying to say? plyr doesn't address any of the issues I listed. The regular HTML5 video player "works", which plyr augments, but there are specific issues with photoswipe integration. For example the current player needs to be paused on going to a different slide.
Very interesting discussion. I'm testing too and i'm considering these actions on myself:
1) ALL slides videos must stop after closing and after switch different slide (each video.pause()) 2) on fullscreen video event, it must hide/show pswp stuffs (http://www.intheloftstudios.com/blog/detecting-html5-video-fullscreen-and-events)
working on...
+1 from me. Would love to see video support to be able to switch to this plugin.
+1
+1
+1
+1
+1
+1
I've made a simple Version of a Videointegration, its not good code, but it works ;)
procedure: add afterChange listener, check if caption named videoxxx.xxx, dynamically add an videoHolder over the image (and hid it), start resize listener
http://pixelkrams.de/2015/artspin/ (last Thumb)
(The Gallery is based on a webgallery-flash-export from lightroom, which generates almost perfect xml-data and the flex-images plugin)
Hello, can I use this for open a youtube video in popup ?
is a small thumbnail and onclick is open a youtube video in popup. http://www.no-margin-for-errors.com/projects/prettyphoto-jquery-lightbox-clone/
Thanks.
+1
Any plans on this one? PhotoSwipe does look sweet for usage :smiley:
+1
+1
+1
+1
+1
hi @SalvoDiFede. i trying to enable fullscreen youtube video. but i dont know what hide/show of pswp stuffs. in fact, when I click on the video fullscreen I see the bottom of the pswp, ie the site. any suggestion? thank you so much.
Hi @vitorbar: take a look at @Radla implementation: http://pixelkrams.de/2015/artspin/ (last Thumb) I moved my code to his solution... ps: thanks @Radla :+1:
thanks @SalvoDiFede @Radla. I will check
@Radla or @SalvoDiFede Could one of you provide more detailed information on how and where to edit the code?
greatly appreciated!
+1 :+1:
It would be great if this supported both embedding of youTube or Vimeo players. As well as supporting HTML Videos. Any planned updates ahead for this?
@georg90 simple copy of my main.js code from 'gallery.listen...' to end of 'function updateVideoPosition(o) {' should work, if you named some images like videoxxx.jpg and the corresponding videos (mp4 and webm). i only tested on apple mobiles, not on android. i have heard of some scaling problems...
@Radla thank you! got it working, but can't find the video url in my specific case. See https://github.com/DanielMuller/koken-plugin-photoswipe/issues/27
and my poor implementation: https://github.com/georg90/koken-plugin-photoswipe/commit/d36c53ce64e82c78978052f07215d3552ee0d542
still need to investigate further..
Maybe is there a way to open Magnific Popup with video on top of PhotoSwipe slide by clicking play button created as HTML content in PhotoSwipe slide?
http://codepen.io/makshh/pen/ONMVMm
Can you test it on mobile devices?
I think it is working fine on desktops.
It is working. So what have to be done ?
@kuzco1 - Work a little, dude. It just took me half an hour of reverse engineering. Just compare the codepen above to your existing photoswipe.
The only thing you really have to modify is :
// create slide object
if ($(linkEl).data('type') == 'html') {
item = {
html: $(linkEl).data('video')
};
} else {
item = {
src: linkEl.getAttribute('href'),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10)
};
}
Just target your proper selectors, until you get to the proper linkEl. Don't touch your existing html structure, just modify the a tag that requires to point to a video.
I don't have the time right now, but I'd like to fork this pen and combine with @Radla implementation, the photoswipe animation is preserved. There's no animation in the codepen.
I have tried the code shown here and work on multiple browsers but not in MS IE 11 and Edge 11.
+1
+1
+10000000
Here is my solution to use Photoswipe with Youtube&Vimeo videos.
It is a mix of java-script libraries and solutions which I saw here at Stackoverflow and on the web.
Stylings
<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>
Markup (the standard one)
<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>
Items
<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>
Scripts
<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 (this is a jQuery Plugin by Qassim Hassan). You need to download it as well. I've made some custom changes in it, so after downloading simply replace the js-code with mine.
/*
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 (the main 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();
}
}
});
Have fun!
Now that we have proof of concept,as shown by makshh, is there any chance this could be added to photoswipe?
+1
I have a very simple video implementation in my PhotoSwipe skin , see this example album.
It is implemented with thew next code:
`CSS: video { margin-top: 50px; visibility: hidden; position: absolute; }
JS: var videoRunning = false;
function checkVideo() {
if (videoRunning) {
$("video").each(function () { this.pause() });
$('video').css({visibility: 'hidden' })
videoRunning = false;
}
}
function sizeVideo(vp, imgW, imgH) {
var winW = vp.x;
var winH = vp.y -100;
var imgRatio = imgW / imgH;
var tWidth = winW;
var tHeight = winH;
function scaleWB() { tWidth = winW; tHeight = tWidth / imgRatio; }
function scaleBW() { tHeight = winH; tWidth = tHeight * imgRatio; }
if (imgRatio >= 1) {
scaleWB();
if (tHeight > winH) { scaleBW(); }
if (tWidth > imgW) { tWidth = imgW; tHeight = imgH; }
}
else {
scaleBW();
if (tWidth > winW) { scaleWB(); }
if (tHeight > imgH) { tWidth = imgW; tHeight = imgH; }
}
var tLeft = (winW-tWidth)/2;
var tTop = (winH-tHeight)/2;
$('video').css({'left':tLeft, 'top':tTop, 'width':tWidth, 'height':tHeight , visibility: 'visible' })
}
var items = [
{
src: 'slides/151004-141050_Vasse.jpg',
w: 1920,
h: 965,
title: 'image title'
},
{
videosrc: 'slides/IMG_0877.mp4',
vw: 608,
vh: 1080,
html: '',
title: 'video title'
},
];
var openPhotoSwipe = function(ind) { var pswpElement = document.querySelectorAll('.pswp')[0];
// define options (if needed)
var options = {
history: true,
index: ind,
focus: true,
loop: false,
closeOnScroll: false,
showAnimationDuration: 0,
hideAnimationDuration: 0
};
pswp = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
pswp.listen('afterChange', function() {
checkVideo();
if (typeof(pswp.currItem.videosrc) !== "undefined") {
sizeVideo(pswp.viewportSize, pswp.currItem.vw, pswp.currItem.vh);
videoRunning = true;
}
});
pswp.listen('resize', function () {
if (videoRunning) {
sizeVideo(pswp.viewportSize, pswp.currItem.vw, pswp.currItem.vh);
}
});
pswp.listen('close', function () {
checkVideo();
});
pswp.listen('beforeChange', function () {
checkVideo();
});
pswp.init();
};
`
Hi,
I implemented the support of the video with a small change in PhotoSwipe (that could be introduced in standard version). A small demo is available here: http://joel.online.free.fr You can download the demo web page and get javascripts.
Feel free to comment :-)
Joël
@Joel95
I gave it a try, however it looks like the code for youtube doesn't seem to work on iOS.
Please let know if we have to apply some code changes to make it work.
As I don't use this library anymore I'll close the issue. I'm not even sure if the author is still maintaining this. Anyway great achievements in time :) Best of luck to anyone!
@Joel95 could you please report the difference between your implementation and my PhotoSwipe skin implementation?
Now that is v4.0, have you got any plan on introducing it? I remember that old versions was not doing it. I was hoping that now that you're managing it maybe it could be introduced. See http://brutaldesign.github.io/swipebox/ for an example.
Thanks in advance :)
P.S.: if you need some inputs or user-cases feel free to ask them, since I've already patched swipebox to support a better embedding of video URLs :)