在滑块插件上实现 RTL

Implementing RTL on a slider plugin

在开发者several requests ignored支持RTL之后,我正在尝试自己做。

反转数组顺序非常简单:

self.items = !!(_options.rtl) ? _items = items.reverse() : _items = items; // Reverse the array for RTL

..然而,另一个挑战是滑动 RTL。因此从幻灯片 4(这是第一张幻灯片)向右滑动应该会滑到下一张幻灯片(幻灯片 3)。

我相信所有的魔法都发生在这个函数中,但我不太清楚要调整什么:

_moveMainScroll = function(x, dragging) {

    if(!_options.loop && dragging) {

        if (_options.rtl) {
            console.log('RTL enabled');
            console.log('_currentItemIndex: ', _currentItemIndex);
            console.log('_slideSize.x: ', _slideSize.x);
            console.log('_currPositionIndex: ', _currPositionIndex);
            console.log('x: ', x);
            var newSlideIndexOffset = _currentItemIndex + (_slideSize.x * _currPositionIndex - x) / _slideSize.x,
                delta = Math.round(x - _mainScrollPos.x);
            console.log(newSlideIndexOffset, delta);
        }
        else {
            var newSlideIndexOffset = _currentItemIndex + (_slideSize.x * _currPositionIndex - x) / _slideSize.x,
            delta = Math.round(x - _mainScrollPos.x);
            console.log(newSlideIndexOffset, delta);
        }

        if( (newSlideIndexOffset < 0 && delta > 0) || (newSlideIndexOffset >= _getNumItems() - 1 && delta < 0) ) {
                x = _mainScrollPos.x + delta * _options.mainScrollEndFriction;
        } 
    }

    _mainScrollPos.x = x;
    _setTranslateX(x, _containerStyle);
}

到目前为止,这是我的代码:https://jsfiddle.net/tdx3p1p3/

以前从未使用过该库,所以我在这里可能有点天真。您的 rtl 选项似乎只会颠倒元素的顺序,否则没有任何效果。查看代码,我看不出这会是个问题,但我没有调查开发人员在您链接到的那篇文章中提到的标题问题。


如果我错了请原谅我,但我认为这就是你想要的:

                            ********
 Slide1 < Slide2 < Slide3 < *Slide4*
                            ********

如果是这种情况,您希望顺序相同,但初始元素为幻灯片 4(即索引 3):

var options = {
    ...
    rtl: false,
    index: 3
};

如果是这种情况,那么我认为您甚至不需要 _options.rtl 变量。


另一方面,如果您想要这种布局:

                            ********
 Slide4 < Slide3 < Slide2 < *Slide1*
                            ********

...那么你可以使用这个配置:

var options = {
    ...
    rtl: true,
    index: 3
};

...这当然需要 _options.rtl 变量,并且可能需要围绕字幕进行测试。

如果我理解正确,您想以常规方式使用 PhotoSwipe,特别是照常传递 items 数组(即第一张幻灯片位于索引 0),但是图库将此幻灯片 0 放在 "right-most" 位置,然后将 1 幻灯片放在其左侧,依此类推,让左上角计数器显示幻灯片 "index"(偏移 1相应地避免显示“0”)(因此仅使用 options.index: 3 是不够的)。

如果这是正确的,你会喜欢@e_i_pi想象中的2nd布局:

                            ********
 Slide4 < Slide3 < Slide2 < *Slide1*
                            ********

因此你需要三样东西:

  1. 反转你的 items 数组。
  2. 从最右边的幻灯片开始。
  3. 修改 UI 计数器,使报告的载玻片索引为 "reversed"。

您不需要通过调整 PhotoSwipe 脚本中的代码来执行这 3 个操作。您可以只使用执行这些操作的 "wrapper" 函数,并且仍然使用未修改的 PhotoSwipe 代码(以便您以后更容易升级,并从库的未来改进中受益)。

1.反转你的 items 数组:

如您所见,这是最简单的操作:items = items.reverse()

2。从最右边的幻灯片开始:

正如@e_i_pi 所建议的那样,您只需要传递一个 index option 等于 new 索引(即反转后)你的 "first" 幻灯片:index = items.length - 1

它最初位于索引 0,经过反转后现在是 "last" 项。

3。反转 UI 计数器:

这稍微高级一点,但没有太复杂。

正如 PhotoSwipe 作者 shown 所说,自定义 UI 计数器很容易,但需要先初始化图库。因此,"wrapper"函数需要在内部初始化gallery。

那么构建新的 UI 计数器内容的逻辑并不太复杂。您只需要取项目总数并减去items JS数组中的当前索引:

                            ********
 Slide4 < Slide3 < Slide2 < *Slide1*
                            ********
    0        1       2         3     <= index in items JS array
    4        3       2         1     <= "index" to be shown in UI counter

所以你可以有这样的东西:

var total = gallery.options.getNumItemsFn();
var current = gallery.getCurrentIndex();
var reversed = total - current;
var separator = gallery.options.indexIndicatorSep;
indexIndicatorDOMElement.innerHTML = reversed + separator + total;

把所有东西放在一起,你就有了一个包装函数,你可以把它放在它自己的 JS 文件中,这样你就可以在任何你想用的地方使用它。

// Wrapper initialize function that does the RTL conversion automatically.
// Note: it will also automatically initialize the PhotoSwipe, because it needs to be initialized for UI counter to be modified.
function photoSwipeRTL(pswpElement, uiClass, items, options) {
  // 1. Reverse the items.
  items = items.reverse();

  // 2. Override the start index.
  var itemsIndexMax = items.length - 1;
  var index = options.index || 0; // If not provided, use 0.
  // Now reverse the start index.
  options.index = itemsIndexMax - index;

  // Now instantiate a PhotoSwipe and initialize it, so that we can modify its UI counter.
  var pswp = new PhotoSwipe(pswpElement, uiClass, items, options);
  pswp.init();

  // Get the counter element provided in options, or get it from DOM.
  var indexIndicatorDOMElement = options.indexIndicatorDOMElement || document.querySelectorAll('.pswp__counter')[0];

  // 3. Modify the UI counter.
  pswp.ui.updateIndexIndicator = function() {
    // This code reverses the current index compared to the total number of items in the gallery.
    var total = pswp.options.getNumItemsFn();
    var current = pswp.getCurrentIndex();
    var reversed = total - current;
    var separator = pswp.options.indexIndicatorSep;
    indexIndicatorDOMElement.innerHTML = reversed + separator + total;
  };
  // force index update
  pswp.ui.updateIndexIndicator();

  return pswp;
}

而且你可以非常简单地使用它,几乎就像标准的 PhotoSwipe,只是你只需要执行工厂(不需要 new 关键字),并且不需要初始化图库,因为它已经内部完成。

// INITIALIZE
var pswpElement = document.querySelectorAll('.pswp')[0];

// build items array
var items = [slide1, slide2, slide3, slide4];

// define options (if needed)
var options = {
  indexIndicatorSep: ' of ',
  indexIndicatorDOMElement: document.querySelectorAll('.pswp__counter')[0]
};

// Initializes and opens PhotoSwipe
var gallery = photoSwipeRTL(pswpElement, PhotoSwipeUI_Default, items, options);

现场演示:https://plnkr.co/edit/kPeFeZbwhqHzbz8A9VRK?p=preview