Browse Source

photoswipe theme: swiping over video now works (mostly)

pull/398/head
Lukas Vacek 6 years ago
parent
commit
1b9751b427
  1. 91
      sigal/themes/photoswipe/static/photoswipe.js
  2. 12
      sigal/themes/photoswipe/static/photoswipe.min.js
  3. 14
      sigal/themes/photoswipe/static/styles.css
  4. 6
      sigal/themes/photoswipe/templates/album.html

91
sigal/themes/photoswipe/static/photoswipe.js

@ -702,8 +702,87 @@ var _isOpen,
_updatePageScrollOffset = function() {
self.setScrollOffset(0, framework.getScrollY());
};
},
_unbindAllSwipeAreaPlayPause = function() {
for (var i=0; i < NUM_HOLDERS; i++) {
_unbindSwipeAreaPlayPause(_itemHolders[i].el);
}
},
_unbindSwipeAreaPlayPause = function(containerElement) {
var childrenVideoElements = containerElement.getElementsByTagName("video");
var childrenSwipeAreaElements = containerElement.getElementsByClassName("video__swipearea");
if (childrenVideoElements.length != 1 || childrenSwipeAreaElements.length != 1) {
return
}
var videoElement = childrenVideoElements[0];
var swipeAreaElement = childrenSwipeAreaElements[0];
if (swipeAreaElement.play_pause != undefined) {
framework.unbind(swipeAreaElement, 'click', swipeAreaElement.play_pause);
}
if (swipeAreaElement.resize != undefined) {
framework.unbind(videoElement, "loadeddata", swipeAreaElement.resize);
framework.unbind(videoElement, "canplay", swipeAreaElement.resize);
framework.unbind(window, 'resize', swipeAreaElement.resize);
}
},
_bindSwipeAreaPlayPause = function(containerElement) {
var childrenVideoElements = containerElement.getElementsByTagName("video");
var childrenSwipeAreaElements = containerElement.getElementsByClassName("video__swipearea");
if (childrenVideoElements.length != 1 || childrenSwipeAreaElements.length != 1) {
return;
}
var videoElement = childrenVideoElements[0];
var swipeAreaElement = childrenSwipeAreaElements[0];
swipeAreaElement.play_pause = function(e) {
if (videoElement.paused) {
videoElement.play();
} else {
videoElement.pause();
}
};
swipeAreaElement.resize = function() {
// swiping in top 70% of the video works
// yes it's not a very good solution but better than swiping not working at all
// this is to ensure that both works internal browser controls *and* swiping
if (videoElement.scrollHeight > 400) {
swipeAreaElement.style.height = (videoElement.scrollHeight * 0.7) + "px";
// swipeArea is vertically and horizontally centered just like the video
// but should appear at the top so we do top -> 40%
// keep 25 px at the top not covered so video can register mouse coming back
swipeAreaElement.style.top = "calc(35% + 25px)";
} else if (videoElement.scrollHeight > 150) {
// minimal height *not* covered by swipe area is 70px
// to ensure controls always work
swipeAreaElement.style.height = videoElement.scrollHeight - 70 + "px";
// 35px (half of height) - 10% extra (for video to register mouse coming back)
swipeAreaElement.style.top = "calc(50% - 25px)";
} else {
// the video is so small that a user can swipe above/below anyway
swipeAreaElement.style.height = 0;
}
// do not extend the swipe area across the whole video width
// so the video can regiser when mouse moves in/out so controls can reappear
if (videoElement.scrollWidth > 300) {
swipeAreaElement.style.width = videoElement.scrollWidth - 50 + "px";
} else if (videoElement.scrollWidth > 100) {
swipeAreaElement.style.width = videoElement.scrollWidth - 20 + "px";
} else {
// the video is so narrow that a user can swipe around the video anyway
swipeAreaElement.style.width = 0;
}
};
framework.bind(swipeAreaElement, 'click', swipeAreaElement.play_pause);
framework.bind(videoElement, 'loadeddata', swipeAreaElement.resize);
framework.bind(videoElement, 'canplay', swipeAreaElement.resize);
framework.bind(window, 'resize', swipeAreaElement.resize);
swipeAreaElement.resize(); // set the initial size
};
@ -989,8 +1068,8 @@ var publicMethods = {
_isDestroying = true;
_shout('close');
_unbindEvents();
self.pauseVideo();
_unbindAllSwipeAreaPlayPause();
_showOrHide(self.currItem, null, true, self.destroy);
},
@ -1099,7 +1178,7 @@ var publicMethods = {
} else {
_currZoomElementStyle = null;
}
_currPanBounds = self.currItem.bounds;
_startZoomLevel = _currZoomLevel = self.currItem.initialZoomLevel;
@ -1136,6 +1215,7 @@ var publicMethods = {
}
self.pauseVideo();
_unbindAllSwipeAreaPlayPause();
self.currItem = _getItemAt( _currentItemIndex );
_renderMaxResolution = false;
@ -1165,6 +1245,9 @@ var publicMethods = {
}
// set the video__swipearea onclick to play/pause video
_bindSwipeAreaPlayPause(_itemHolders[1].el);
// reset zoom/pan on previous item
if(_currZoomElementStyle && Math.abs(_indexDiff) === 1) {

12
sigal/themes/photoswipe/static/photoswipe.min.js vendored

@ -33,7 +33,11 @@ return false;},_setupTransforms=function(){if(_transformKey){var allow3dTransfor
_transformKey='left';framework.addClass(template,'pswp--ie');_setTranslateX=function(x,elStyle){elStyle.left=x+'px';};_applyZoomPanToItem=function(item){var zoomRatio=item.fitRatio>1?1:item.fitRatio,s=item.container.style,w=zoomRatio*item.w,h=zoomRatio*item.h;s.width=w+'px';s.height=h+'px';s.left=item.initialPosition.x+'px';s.top=item.initialPosition.y+'px';};_applyCurrentZoomPan=function(){if(_currZoomElementStyle){var s=_currZoomElementStyle,item=self.currItem,zoomRatio=item.fitRatio>1?1:item.fitRatio,w=zoomRatio*item.w,h=zoomRatio*item.h;s.width=w+'px';s.height=h+'px';s.left=_panOffset.x+'px';s.top=_panOffset.y+'px';}};},_onKeyDown=function(e){var keydownAction='';if(_options.escKey&&e.keyCode===27){keydownAction='close';}else if(_options.arrowKeys){if(e.keyCode===37){keydownAction='prev';}else if(e.keyCode===39){keydownAction='next';}}
if(keydownAction){if(!e.ctrlKey&&!e.altKey&&!e.shiftKey&&!e.metaKey){if(e.preventDefault){e.preventDefault();}else{e.returnValue=false;}
self[keydownAction]();}}},_onGlobalClick=function(e){if(!e){return;}
if(_moved||_zoomStarted||_mainScrollAnimating||_verticalDragInitiated){e.preventDefault();e.stopPropagation();}},_updatePageScrollOffset=function(){self.setScrollOffset(0,framework.getScrollY());};var _animations={},_numAnimations=0,_stopAnimation=function(name){if(_animations[name]){if(_animations[name].raf){_cancelAF(_animations[name].raf);}
if(_moved||_zoomStarted||_mainScrollAnimating||_verticalDragInitiated){e.preventDefault();e.stopPropagation();}},_updatePageScrollOffset=function(){self.setScrollOffset(0,framework.getScrollY());},_unbindAllSwipeAreaPlayPause=function(){for(var i=0;i<NUM_HOLDERS;i++){_unbindSwipeAreaPlayPause(_itemHolders[i].el);}},_unbindSwipeAreaPlayPause=function(containerElement){var childrenVideoElements=containerElement.getElementsByTagName("video");var childrenSwipeAreaElements=containerElement.getElementsByClassName("video__swipearea");if(childrenVideoElements.length!=1||childrenSwipeAreaElements.length!=1){return}
var videoElement=childrenVideoElements[0];var swipeAreaElement=childrenSwipeAreaElements[0];if(swipeAreaElement.play_pause!=undefined){framework.unbind(swipeAreaElement,'click',swipeAreaElement.play_pause);}
if(swipeAreaElement.resize!=undefined){framework.unbind(videoElement,"loadeddata",swipeAreaElement.resize);framework.unbind(videoElement,"canplay",swipeAreaElement.resize);framework.unbind(window,'resize',swipeAreaElement.resize);}},_bindSwipeAreaPlayPause=function(containerElement){var childrenVideoElements=containerElement.getElementsByTagName("video");var childrenSwipeAreaElements=containerElement.getElementsByClassName("video__swipearea");if(childrenVideoElements.length!=1||childrenSwipeAreaElements.length!=1){return;}
var videoElement=childrenVideoElements[0];var swipeAreaElement=childrenSwipeAreaElements[0];swipeAreaElement.play_pause=function(e){if(videoElement.paused){videoElement.play();}else{videoElement.pause();}};swipeAreaElement.resize=function(){if(videoElement.scrollHeight>400){swipeAreaElement.style.height=(videoElement.scrollHeight*0.7)+"px";swipeAreaElement.style.top="calc(35% + 25px)";}else if(videoElement.scrollHeight>150){swipeAreaElement.style.height=videoElement.scrollHeight-70+"px";swipeAreaElement.style.top="calc(50% - 25px)";}else{swipeAreaElement.style.height=0;}
if(videoElement.scrollWidth>300){swipeAreaElement.style.width=videoElement.scrollWidth-50+"px";}else if(videoElement.scrollWidth>100){swipeAreaElement.style.width=videoElement.scrollWidth-20+"px";}else{swipeAreaElement.style.width=0;}};framework.bind(swipeAreaElement,'click',swipeAreaElement.play_pause);framework.bind(videoElement,'loadeddata',swipeAreaElement.resize);framework.bind(videoElement,'canplay',swipeAreaElement.resize);framework.bind(window,'resize',swipeAreaElement.resize);swipeAreaElement.resize();};var _animations={},_numAnimations=0,_stopAnimation=function(name){if(_animations[name]){if(_animations[name].raf){_cancelAF(_animations[name].raf);}
_numAnimations--;delete _animations[name];}},_registerStartAnimation=function(name){if(_animations[name]){_stopAnimation(name);}
if(!_animations[name]){_numAnimations++;_animations[name]={};}},_stopAllAnimations=function(){for(var prop in _animations){if(_animations.hasOwnProperty(prop)){_stopAnimation(prop);}}},_animateProp=function(name,b,endProp,d,easingFn,onUpdate,onComplete){var startAnimTime=_getCurrentTime(),t;_registerStartAnimation(name);var animloop=function(){if(_animations[name]){t=_getCurrentTime()-startAnimTime;if(t>=d){_stopAnimation(name);onUpdate(endProp);if(onComplete){onComplete();}
return;}
@ -52,7 +56,7 @@ if(!_oldIE){framework.bind(self.scrollWrap,_downEvents,self);}
_listen('initialZoomInEnd',function(){self.setContent(_itemHolders[0],_currentItemIndex-1);self.setContent(_itemHolders[2],_currentItemIndex+1);_itemHolders[0].el.style.display=_itemHolders[2].el.style.display='block';if(_options.focus){template.focus();}
_bindEvents();});self.setContent(_itemHolders[1],_currentItemIndex);self.updateCurrItem();_shout('afterInit');if(!_isFixedPosition){_updateSizeInterval=setInterval(function(){if(!_numAnimations&&!_isDragging&&!_isZooming&&(_currZoomLevel===self.currItem.initialZoomLevel)){self.updateSize();}},1000);}
framework.addClass(template,'pswp--visible');},close:function(){if(!_isOpen){return;}
_isOpen=false;_isDestroying=true;_shout('close');_unbindEvents();self.pauseVideo();_showOrHide(self.currItem,null,true,self.destroy);},destroy:function(){_shout('destroy');if(_showOrHideTimeout){clearTimeout(_showOrHideTimeout);}
_isOpen=false;_isDestroying=true;_shout('close');_unbindEvents();self.pauseVideo();_unbindAllSwipeAreaPlayPause();_showOrHide(self.currItem,null,true,self.destroy);},destroy:function(){_shout('destroy');if(_showOrHideTimeout){clearTimeout(_showOrHideTimeout);}
template.setAttribute('aria-hidden','true');template.className=_initalClassName;if(_updateSizeInterval){clearInterval(_updateSizeInterval);}
framework.unbind(self.scrollWrap,_downEvents,self);framework.unbind(window,'scroll',self);_stopDragUpdateLoop();_stopAllAnimations();_listeners=null;},panTo:function(x,y,force){if(!force){if(x>_currPanBounds.min.x){x=_currPanBounds.min.x;}else if(x<_currPanBounds.max.x){x=_currPanBounds.max.x;}
if(y>_currPanBounds.min.y){y=_currPanBounds.min.y;}else if(y<_currPanBounds.max.y){y=_currPanBounds.max.y;}}
@ -60,9 +64,9 @@ _panOffset.x=x;_panOffset.y=y;_applyCurrentZoomPan();},handleEvent:function(e){e
if(_itemHolders[1].el.children.length){var zoomElement=_itemHolders[1].el.children[0];if(framework.hasClass(zoomElement,'pswp__zoom-wrap')){_currZoomElementStyle=zoomElement.style;}else{_currZoomElementStyle=null;}}else{_currZoomElementStyle=null;}
_currPanBounds=self.currItem.bounds;_startZoomLevel=_currZoomLevel=self.currItem.initialZoomLevel;_panOffset.x=_currPanBounds.center.x;_panOffset.y=_currPanBounds.center.y;if(emulateSetContent){_shout('afterChange');}},invalidateCurrItems:function(){_itemsNeedUpdate=true;for(var i=0;i<NUM_HOLDERS;i++){if(_itemHolders[i].item){_itemHolders[i].item.needsUpdate=true;}}},updateCurrItem:function(beforeAnimation){if(_indexDiff===0){return;}
var diffAbs=Math.abs(_indexDiff),tempHolder;if(beforeAnimation&&diffAbs<2){return;}
self.pauseVideo();self.currItem=_getItemAt(_currentItemIndex);_renderMaxResolution=false;_shout('beforeChange',_indexDiff);if(diffAbs>=NUM_HOLDERS){_containerShiftIndex+=_indexDiff+(_indexDiff>0?-NUM_HOLDERS:NUM_HOLDERS);diffAbs=NUM_HOLDERS;}
self.pauseVideo();_unbindAllSwipeAreaPlayPause();self.currItem=_getItemAt(_currentItemIndex);_renderMaxResolution=false;_shout('beforeChange',_indexDiff);if(diffAbs>=NUM_HOLDERS){_containerShiftIndex+=_indexDiff+(_indexDiff>0?-NUM_HOLDERS:NUM_HOLDERS);diffAbs=NUM_HOLDERS;}
for(var i=0;i<diffAbs;i++){if(_indexDiff>0){tempHolder=_itemHolders.shift();_itemHolders[NUM_HOLDERS-1]=tempHolder;_containerShiftIndex++;_setTranslateX((_containerShiftIndex+2)*_slideSize.x,tempHolder.el.style);self.setContent(tempHolder,_currentItemIndex-diffAbs+i+1+1);}else{tempHolder=_itemHolders.pop();_itemHolders.unshift(tempHolder);_containerShiftIndex--;_setTranslateX(_containerShiftIndex*_slideSize.x,tempHolder.el.style);self.setContent(tempHolder,_currentItemIndex+diffAbs-i-1-1);}}
if(_currZoomElementStyle&&Math.abs(_indexDiff)===1){var prevItem=_getItemAt(_prevItemIndex);if(prevItem.initialZoomLevel!==_currZoomLevel){_calculateItemSize(prevItem,_viewportSize);_setImageSize(prevItem);_applyZoomPanToItem(prevItem);}}
_bindSwipeAreaPlayPause(_itemHolders[1].el);if(_currZoomElementStyle&&Math.abs(_indexDiff)===1){var prevItem=_getItemAt(_prevItemIndex);if(prevItem.initialZoomLevel!==_currZoomLevel){_calculateItemSize(prevItem,_viewportSize);_setImageSize(prevItem);_applyZoomPanToItem(prevItem);}}
_indexDiff=0;self.updateCurrZoomItem();_prevItemIndex=_currentItemIndex;_shout('afterChange');},updateSize:function(force){if(!_isFixedPosition&&_options.modal){var windowScrollY=framework.getScrollY();if(_currentWindowScrollY!==windowScrollY){template.style.top=windowScrollY+'px';_currentWindowScrollY=windowScrollY;}
if(!force&&_windowVisibleSize.x===window.innerWidth&&_windowVisibleSize.y===window.innerHeight){return;}
_windowVisibleSize.x=window.innerWidth;_windowVisibleSize.y=window.innerHeight;template.style.height=_windowVisibleSize.y+'px';}

14
sigal/themes/photoswipe/static/styles.css

@ -161,6 +161,19 @@ figcaption {
overflow: hidden;
}
.video__swipearea {
position: absolute;
height: 0px;
width: 0px;
overflow: hidden;
top: calc(40% + 25px);
left: 50%;
transform: translateX(-50%) translateY(-50%);
max-width: 100%;
max-height: 100%;
z-index: 5;
}
.video__container iframe,
.video__container video {
position: absolute;
@ -169,6 +182,7 @@ figcaption {
transform: translateX(-50%) translateY(-50%);
max-width: 100%;
max-height: 100%;
z-index: 4;
}
.video-desc {

6
sigal/themes/photoswipe/templates/album.html

@ -32,8 +32,12 @@
{% if media.type == "video" %}
<figure class="gallery__img--secondary thumbnail"
itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<!-- because events (taps, touches, clicks) on video with controls are not propagated we use swipeare which covers most of the video
except the bottom controls and later bind click on video_swipearea to do play/pause
this fixes swiping over video to go to next/previous item or close the gallery, so it is usable on mobile
very ugly hack, if you know of a better solution, please go ahead -->
<a href="{{ media.url }}" itemprop="contentUrl" data-type="video"
data-video='<div class="video"><div class="video__container"><video controls><source src="{{ media.url }}" type="{{ media.mime }}" /></video></div></div>'>
data-video='<div class="video"><div class="video__container"><div class="video__swipearea"></div><video controls playsinline><source src="{{ media.url }}" type="{{ media.mime }}" /></video></div></div>'>
<img src="{{ theme.url }}/echo/blank.gif"
data-echo="{{ media.thumbnail }}"
alt="{{ media.thumbnail }}" itemprop="thumbnail" title="" />

Loading…
Cancel
Save