Photoswipe 4.0:以编程方式启动 'swipe to next'
Photoswipe 4.0: Initiate 'swipe to next' programatically
情况
我一直在尝试在单击 NEXT 按钮时触发 'slide to next picture' 动画,但我还没有找到解决方案。
GitHub 上对此进行了讨论,但它只是关于添加幻灯片动画的选项,而不是关于如何使用 PS 实际做到这一点,就像现在这样.
在 3.0 中有一个选项,但由于 4.0 是一个完全重写,它不再起作用。
问题
我需要单击箭头时 'jumping' 到 next/prev 图片,我需要 swiping/dragging 图片时也使用的 'slide transition'。
没有触发的选项,那我怎么用JS手动触发这个效果呢?
我终于咬紧牙关,花了一些时间来完成这项工作,因为似乎没有人对此有解决方案,在 GitHub 或其他任何地方都没有。
解决方案
我使用了点击箭头跳转到下一个项目并触发下一个图像的加载并设置整个幻灯片状态以立即表示正确情况的事实。
所以我只是添加了自定义按钮,这些按钮将启动幻灯片转换,然后触发对原始按钮(我通过 CSS 隐藏)的点击,这将更新幻灯片状态以表示我在视觉上创建的情况。
- 添加了新的下一个和上一个箭头
- 通过 css
隐藏了原始的下一个和上一个箭头
- 当点击新的下一个或上一个箭头时,我自己制作幻灯片动画
- 然后以编程方式触发对原始下一个或上一个箭头的点击
代码如下:
HTML
// THE NEW BUTTONS
<button class="NEW-button-left" title="Previous (arrow left)">PREV</button>
<button class="NEW-button-right" title="Next (arrow right)">NEXT</button>
// added right before this original lines of the example code
<button class="pswp__button pswp__button--arrow--left ...
CSS
pswp__button--arrow--left,
pswp__button--arrow--right {
display: none;
}
NEW-button-left,
NEW-button-right {
/* whatever you fancy */
}
JAVASCRIPT(辅助函数)
var tx = 0; // current translation
var tdir = 0;
var slidepseactive = false;
// helper function to get current translate3d positions
// as per
function getTransform(el) {
var results = $(el).css('-webkit-transform').match(/matrix(?:(3d)\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))(?:, (-{0,1}\d+)), -{0,1}\d+\)|\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))\))/)
if(!results) return [0, 0, 0];
if(results[1] == '3d') return results.slice(2,5);
results.push(0);
return results.slice(5, 8);
}
// set the translate x position of an element
function translate3dX($e, x) {
$e.css({
// TODO: depending on the browser we need one of those, for now just chrome
//'-webkit-transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
//, '-moz-transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
'transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
});
};
JAVASCRIPT(主要)
// will slide to the left or to the right
function slidePS(direction) {
if (slidepseactive) // prevent interruptions
return;
tdir = -1;
if (direction == "left") {
tdir = 1;
}
// get the current slides transition position
var t = getTransform(".pswp__container");
tx = parseInt(t[0]);
// reset anim counter (you can use any property as anim counter)
$(".pswp__container").css("text-indent", "0px");
slidepseactive = true;
$(".pswp__container").animate(
{textIndent: 100},{
step: function (now, fx) {
// here 8.7 is the no. of pixels we move per animation step %
// so in this case we slide a total of 870px, depends on your setup
// you might want to use a percentage value, in this case it was
// a popup thats why it is a a fixed value per step
translate3dX($(this), tx + Math.round(8.7 * now * tdir));
},
duration: '300ms',
done: function () {
// now that we finished sliding trigger the original buttons so
// that the photoswipe state reflects the new situation
slidepseactive = false;
if (tdir == -1)
$(".pswp__button--arrow--right").trigger("click");
else
$(".pswp__button--arrow--left").trigger("click");
}
},
'linear');
}
// now activate our buttons
$(function(){
$(".NEW-button-left").click(function(){
slidePS("left");
});
$(".NEW-button-right").click(function(){
slidePS("right");
});
});
我使用了这些 SE 答案中的信息:
- jQuery animate a -webkit-transform
- Get translate3d values of a div?
您可以只使用 css 转换:
.pswp__container{
transition:.3s ease-in-out all;
}
这对于移动设备的性能来说可能不太理想,但我只是在媒体查询中添加了这种转换,并允许用户在较小的屏幕上使用滑动功能。
PhotoSwipe 幻灯片切换
因此,我在 Photoswipe 中添加了幻灯片过渡效果,并且它在不影响本机行为的情况下运行良好。
http://codepen.io/mjau-mjau/full/XbqBbp/
http://codepen.io/mjau-mjau/pen/XbqBbp
唯一的限制是在循环模式下不会在接缝之间应用过渡(例如,从最后一张幻灯片循环到第一张幻灯片时)。在示例中,我使用了 jQuery.
本质上,它通过简单地添加一个 CSS 转换 class 到 .pswp__container
来工作,但是我们需要添加一些 javascript 事件来防止转换不会干扰滑动,并且仅当 mouseUsed
时。我们还添加了一个补丁,因此不会在循环接缝之间添加过渡。
1.将以下内容添加到您的 CSS
它将在需要时从 javascript 按需应用。
.pswp__container_transition {
-webkit-transition: -webkit-transform 333ms cubic-bezier(0.4, 0, 0.22, 1);
transition: transform 333ms cubic-bezier(0.4, 0, 0.22, 1);
}
2。添加 javascript 事件以协助分配转换 class
这可以去任何地方,但必须在 jQuery 加载后触发。
var mouseUsed = false;
$('body').on('mousedown', '.pswp__scroll-wrap', function(event) {
// On mousedown, temporarily remove the transition class in preparation for swipe. $(this).children('.pswp__container_transition').removeClass('pswp__container_transition');
}).on('mousedown', '.pswp__button--arrow--left, .pswp__button--arrow--right', function(event) {
// Exlude navigation arrows from the above event.
event.stopPropagation();
}).on('mousemove.detect', function(event) {
// Detect mouseUsed before as early as possible to feed PhotoSwipe
mouseUsed = true;
$('body').off('mousemove.detect');
});
3。添加 beforeChange
侦听器以在 photoswipe init
上重新分配转换 class
以下需要添加到您的 PhotoSwipe 初始化逻辑中。
// Create your photoswipe gallery element as usual
gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
// Transition Manager function (triggers only on mouseUsed)
function transitionManager() {
// Create var to store slide index
var currentSlide = options.index;
// Listen for photoswipe change event to re-apply transition class
gallery.listen('beforeChange', function() {
// Only apply transition class if difference between last and next slide is < 2
// If difference > 1, it means we are at the loop seam.
var transition = Math.abs(gallery.getCurrentIndex()-currentSlide) < 2;
// Apply transition class depending on above
$('.pswp__container').toggleClass('pswp__container_transition', transition);
// Update currentSlide
currentSlide = gallery.getCurrentIndex();
});
}
// Only apply transition manager functionality if mouse
if(mouseUsed) {
transitionManager();
} else {
gallery.listen('mouseUsed', function(){
mouseUsed = true;
transitionManager();
});
}
// init your gallery per usual
gallery.init();
当您使用滑动手势时,PhotoSwipe 可以自行完成此操作。那么为什么不使用内部代码而不是使用效果不佳的代码呢?
使用我的解决方案,一切正常,箭头点击,光标键,甚至最后循环返回,都没有破坏任何东西。
只需编辑 photoswipe.js
文件并用此代码替换 goTo 函数:
goTo: function(index) {
var itemsDiff;
if (index == _currentItemIndex + 1) { //Next
itemsDiff = 1;
}
else { //Prev
itemsDiff = -1;
}
var itemChanged;
if(!_mainScrollAnimating) {
_currZoomedItemIndex = _currentItemIndex;
}
var nextCircle;
_currentItemIndex += itemsDiff;
if(_currentItemIndex < 0) {
_currentItemIndex = _options.loop ? _getNumItems()-1 : 0;
nextCircle = true;
} else if(_currentItemIndex >= _getNumItems()) {
_currentItemIndex = _options.loop ? 0 : _getNumItems()-1;
nextCircle = true;
}
if(!nextCircle || _options.loop) {
_indexDiff += itemsDiff;
_currPositionIndex -= itemsDiff;
itemChanged = true;
}
var animateToX = _slideSize.x * _currPositionIndex;
var animateToDist = Math.abs( animateToX - _mainScrollPos.x );
var finishAnimDuration = 333;
if(_currZoomedItemIndex === _currentItemIndex) {
itemChanged = false;
}
_mainScrollAnimating = true;
_shout('mainScrollAnimStart');
_animateProp('mainScroll', _mainScrollPos.x, animateToX, finishAnimDuration, framework.easing.cubic.out,
_moveMainScroll,
function() {
_stopAllAnimations();
_mainScrollAnimating = false;
_currZoomedItemIndex = -1;
if(itemChanged || _currZoomedItemIndex !== _currentItemIndex) {
self.updateCurrItem();
}
_shout('mainScrollAnimComplete');
}
);
if(itemChanged) {
self.updateCurrItem(true);
}
return itemChanged;
},
情况
我一直在尝试在单击 NEXT 按钮时触发 'slide to next picture' 动画,但我还没有找到解决方案。
GitHub 上对此进行了讨论,但它只是关于添加幻灯片动画的选项,而不是关于如何使用 PS 实际做到这一点,就像现在这样.
在 3.0 中有一个选项,但由于 4.0 是一个完全重写,它不再起作用。
问题
我需要单击箭头时 'jumping' 到 next/prev 图片,我需要 swiping/dragging 图片时也使用的 'slide transition'。
没有触发的选项,那我怎么用JS手动触发这个效果呢?
我终于咬紧牙关,花了一些时间来完成这项工作,因为似乎没有人对此有解决方案,在 GitHub 或其他任何地方都没有。
解决方案
我使用了点击箭头跳转到下一个项目并触发下一个图像的加载并设置整个幻灯片状态以立即表示正确情况的事实。 所以我只是添加了自定义按钮,这些按钮将启动幻灯片转换,然后触发对原始按钮(我通过 CSS 隐藏)的点击,这将更新幻灯片状态以表示我在视觉上创建的情况。
- 添加了新的下一个和上一个箭头
- 通过 css 隐藏了原始的下一个和上一个箭头
- 当点击新的下一个或上一个箭头时,我自己制作幻灯片动画
- 然后以编程方式触发对原始下一个或上一个箭头的点击
代码如下:
HTML
// THE NEW BUTTONS
<button class="NEW-button-left" title="Previous (arrow left)">PREV</button>
<button class="NEW-button-right" title="Next (arrow right)">NEXT</button>
// added right before this original lines of the example code
<button class="pswp__button pswp__button--arrow--left ...
CSS
pswp__button--arrow--left,
pswp__button--arrow--right {
display: none;
}
NEW-button-left,
NEW-button-right {
/* whatever you fancy */
}
JAVASCRIPT(辅助函数)
var tx = 0; // current translation
var tdir = 0;
var slidepseactive = false;
// helper function to get current translate3d positions
// as per
function getTransform(el) {
var results = $(el).css('-webkit-transform').match(/matrix(?:(3d)\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))(?:, (-{0,1}\d+)), -{0,1}\d+\)|\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))\))/)
if(!results) return [0, 0, 0];
if(results[1] == '3d') return results.slice(2,5);
results.push(0);
return results.slice(5, 8);
}
// set the translate x position of an element
function translate3dX($e, x) {
$e.css({
// TODO: depending on the browser we need one of those, for now just chrome
//'-webkit-transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
//, '-moz-transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
'transform': 'translate3d(' +String(x) + 'px, 0px, 0px)'
});
};
JAVASCRIPT(主要)
// will slide to the left or to the right
function slidePS(direction) {
if (slidepseactive) // prevent interruptions
return;
tdir = -1;
if (direction == "left") {
tdir = 1;
}
// get the current slides transition position
var t = getTransform(".pswp__container");
tx = parseInt(t[0]);
// reset anim counter (you can use any property as anim counter)
$(".pswp__container").css("text-indent", "0px");
slidepseactive = true;
$(".pswp__container").animate(
{textIndent: 100},{
step: function (now, fx) {
// here 8.7 is the no. of pixels we move per animation step %
// so in this case we slide a total of 870px, depends on your setup
// you might want to use a percentage value, in this case it was
// a popup thats why it is a a fixed value per step
translate3dX($(this), tx + Math.round(8.7 * now * tdir));
},
duration: '300ms',
done: function () {
// now that we finished sliding trigger the original buttons so
// that the photoswipe state reflects the new situation
slidepseactive = false;
if (tdir == -1)
$(".pswp__button--arrow--right").trigger("click");
else
$(".pswp__button--arrow--left").trigger("click");
}
},
'linear');
}
// now activate our buttons
$(function(){
$(".NEW-button-left").click(function(){
slidePS("left");
});
$(".NEW-button-right").click(function(){
slidePS("right");
});
});
我使用了这些 SE 答案中的信息:
- jQuery animate a -webkit-transform
- Get translate3d values of a div?
您可以只使用 css 转换:
.pswp__container{
transition:.3s ease-in-out all;
}
这对于移动设备的性能来说可能不太理想,但我只是在媒体查询中添加了这种转换,并允许用户在较小的屏幕上使用滑动功能。
PhotoSwipe 幻灯片切换
因此,我在 Photoswipe 中添加了幻灯片过渡效果,并且它在不影响本机行为的情况下运行良好。
http://codepen.io/mjau-mjau/full/XbqBbp/
http://codepen.io/mjau-mjau/pen/XbqBbp
唯一的限制是在循环模式下不会在接缝之间应用过渡(例如,从最后一张幻灯片循环到第一张幻灯片时)。在示例中,我使用了 jQuery.
本质上,它通过简单地添加一个 CSS 转换 class 到 .pswp__container
来工作,但是我们需要添加一些 javascript 事件来防止转换不会干扰滑动,并且仅当 mouseUsed
时。我们还添加了一个补丁,因此不会在循环接缝之间添加过渡。
1.将以下内容添加到您的 CSS
它将在需要时从 javascript 按需应用。
.pswp__container_transition {
-webkit-transition: -webkit-transform 333ms cubic-bezier(0.4, 0, 0.22, 1);
transition: transform 333ms cubic-bezier(0.4, 0, 0.22, 1);
}
2。添加 javascript 事件以协助分配转换 class 这可以去任何地方,但必须在 jQuery 加载后触发。
var mouseUsed = false;
$('body').on('mousedown', '.pswp__scroll-wrap', function(event) {
// On mousedown, temporarily remove the transition class in preparation for swipe. $(this).children('.pswp__container_transition').removeClass('pswp__container_transition');
}).on('mousedown', '.pswp__button--arrow--left, .pswp__button--arrow--right', function(event) {
// Exlude navigation arrows from the above event.
event.stopPropagation();
}).on('mousemove.detect', function(event) {
// Detect mouseUsed before as early as possible to feed PhotoSwipe
mouseUsed = true;
$('body').off('mousemove.detect');
});
3。添加 beforeChange
侦听器以在 photoswipe init
上重新分配转换 class
以下需要添加到您的 PhotoSwipe 初始化逻辑中。
// Create your photoswipe gallery element as usual
gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
// Transition Manager function (triggers only on mouseUsed)
function transitionManager() {
// Create var to store slide index
var currentSlide = options.index;
// Listen for photoswipe change event to re-apply transition class
gallery.listen('beforeChange', function() {
// Only apply transition class if difference between last and next slide is < 2
// If difference > 1, it means we are at the loop seam.
var transition = Math.abs(gallery.getCurrentIndex()-currentSlide) < 2;
// Apply transition class depending on above
$('.pswp__container').toggleClass('pswp__container_transition', transition);
// Update currentSlide
currentSlide = gallery.getCurrentIndex();
});
}
// Only apply transition manager functionality if mouse
if(mouseUsed) {
transitionManager();
} else {
gallery.listen('mouseUsed', function(){
mouseUsed = true;
transitionManager();
});
}
// init your gallery per usual
gallery.init();
当您使用滑动手势时,PhotoSwipe 可以自行完成此操作。那么为什么不使用内部代码而不是使用效果不佳的代码呢?
使用我的解决方案,一切正常,箭头点击,光标键,甚至最后循环返回,都没有破坏任何东西。
只需编辑 photoswipe.js
文件并用此代码替换 goTo 函数:
goTo: function(index) {
var itemsDiff;
if (index == _currentItemIndex + 1) { //Next
itemsDiff = 1;
}
else { //Prev
itemsDiff = -1;
}
var itemChanged;
if(!_mainScrollAnimating) {
_currZoomedItemIndex = _currentItemIndex;
}
var nextCircle;
_currentItemIndex += itemsDiff;
if(_currentItemIndex < 0) {
_currentItemIndex = _options.loop ? _getNumItems()-1 : 0;
nextCircle = true;
} else if(_currentItemIndex >= _getNumItems()) {
_currentItemIndex = _options.loop ? 0 : _getNumItems()-1;
nextCircle = true;
}
if(!nextCircle || _options.loop) {
_indexDiff += itemsDiff;
_currPositionIndex -= itemsDiff;
itemChanged = true;
}
var animateToX = _slideSize.x * _currPositionIndex;
var animateToDist = Math.abs( animateToX - _mainScrollPos.x );
var finishAnimDuration = 333;
if(_currZoomedItemIndex === _currentItemIndex) {
itemChanged = false;
}
_mainScrollAnimating = true;
_shout('mainScrollAnimStart');
_animateProp('mainScroll', _mainScrollPos.x, animateToX, finishAnimDuration, framework.easing.cubic.out,
_moveMainScroll,
function() {
_stopAllAnimations();
_mainScrollAnimating = false;
_currZoomedItemIndex = -1;
if(itemChanged || _currZoomedItemIndex !== _currentItemIndex) {
self.updateCurrItem();
}
_shout('mainScrollAnimComplete');
}
);
if(itemChanged) {
self.updateCurrItem(true);
}
return itemChanged;
},