【问题标题】:JavaScript - Draggable Gallery SliderJavaScript - 可拖动的画廊滑块
【发布时间】:2021-04-08 11:55:17
【问题描述】:

我使用function from W3Schools 作为起点来制作可拖动的画廊滑块(在我的代码中为.slider-all-items)。为了防止垂直拖动,已从原始文件中删除了几行。

我正在尝试实现与jsfiddle example 非常相似的东西,这是一个可拖动的幻灯片,并且:

  • 总是全屏显示 (.item { width: 100vw || 100%})
  • 响应式即使在window.resize
  • 没有无限模式(查看上面的jsfiddle)。

添加了 3 张幻灯片,每张幻灯片占用窗口的100%(响应式)。

<div data-item="slider-full" class="slider-container">
    <div class="slider-all-items">
        <div class="slider-item slider-item1"></div>
        <div class="slider-item slider-item2"></div>
        <div class="slider-item slider-item3"></div>
    </div>
</div>

现在,我不需要无限模式,但是在幻灯片之间切换的动画可拖动滑块的一部分.
如果您尝试在 jsfiddle 示例中拖动幻灯片(方向无关紧要)只是几个px 它不会获得(下一张或上一张)幻灯片并将其居中,简而言之 功能被阻止。

要为leftright .items 设置动画,我做了这样的事情:

/* If the user is dragging to -1 (no slide), it'll set the slider `left` to *0* */

if (sliderLeft >= 0) {theSlider.style.left = "0px";}

最后一个.item(幻灯片)也一样:

/* If dragging greater than the last one, set to the last with animation */
if (sliderRight <= sliderWidth) {theSlider.style.left = on the last item}

动画 - 过渡:
property transition 及其值 0.5s ease 存储在名为 .shiftingclass 中。

如果两者(上述条件)中的任何一个是true.shifting class 将被添加到Slider,它将transition: 0.5s(如上所述)。同时会执行一个setTimeout() function, delay 0.5s,它会添加和删除它。 (延迟是为了平衡transition 在删除class 之前完全完成所花费的时间)。值得一提的是,class.shifting 应该被移除以保持快速和平滑的拖动。简而言之:它只会让class 起作用(当鼠标空闲时)。

.shifting{
    transition: all 0.5s ease;
} 

我想要达到的目标:

使幻灯片可拖动(全屏 - 响应式 - 无无限模式),并且:

如果拖动只是 X(small number)px 阻止它(如 jsfiddle - 使用 .shifting 和我的代码)。

如果超过X(greater than the x before)px,获取要求的幻灯片并将其居中。

现场(类似)示例:

编辑:您必须登录才能看到它,抱歉没有注意到并且找不到另一个示例

  • Fiverr - 向下滚动并检查横幅(滑块)。忽略无限模式和导航点。

我尝试过的事情:

  1. 使用forforEach loops 获取items 但无法在它们和theSlider.style.left 之间建立连接。

  2. 尝试了上面的 jsfiddle example 并进行了一些更改 (set to full screen),它可以工作,但问题出在 window.resize 上,它出现故障,需要刷新页面以使其按预期工作。

  3. 使用JavaScriptjQuery 刷新页面in 页面本身的特定内容(不重新加载)不起作用。 p>

当刷新页面中的内容不起作用时,我有一个想法,使用上面提到的 jsfiddlewidthheight 更改为 100% and 100vh, and on window.resize` 得到当前幻灯片索引,删除滑块,并使用存储的索引再次附加它,但有时可能会出现故障,因此决定坚持使用我的代码,问题是:

如何在幻灯片之间连接以使滑块按要求工作?

我的代码:

// get the slider
var theSlider = document.querySelector(".slider-all-items");
// get the items in the slider
var sliderItem = document.querySelectorAll('.slider-item');

// variables saved for later
var sliderWidth;
var sliderRight;

// run the function
dragElement(theSlider);


function dragElement(theSlider) {
    var pos1 = 0, pos3 = 0;
    theSlider.onmousedown = dragMouseDown;

    function dragMouseDown(e) {
        e = e || window.event;
        e.preventDefault();
        // get the mouse cursor position at startup:
        pos3 = e.clientX;
        document.onmouseup = closeDragElement;
        // call a function whenever the cursor moves:
        document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
        e = e || window.event;
        e.preventDefault();
        // calculate the new cursor position:
        pos1 = pos3 - e.clientX;
        pos3 = e.clientX;

        // set the element's new position:
        theSlider.style.left = (theSlider.offsetLeft - pos1) + "px";
    }
    
    function closeDragElement() {
        // add the class .shifting to the slider for every css change (transition)
        theSlider.classList.add("shifting");
        
        // get each item width
        sliderWidth = theSlider.getBoundingClientRect().width  / sliderItem.length;
        // get the right side position of the slider
        sliderRight = theSlider.getBoundingClientRect().right;
        // get the left side position of the slider
        sliderLeft = theSlider.getBoundingClientRect().left;

        if(sliderLeft >= 0){
            theSlider.style.left = "0px";
        }

        if(sliderRight <= sliderWidth){            
            theSlider.style.left =  -Math.abs((sliderWidth * sliderItem.length) - sliderWidth) + "px";
        }
        
        // delay 0.5s, then remove the class .shifting when finished checking and styling
        // .shifting {transition: all 0.5s ease;}
        setTimeout(() => {
            theSlider.classList.remove("shifting");
        }, 500);

        // stop moving when mouse button is released:
        document.onmouseup = null;
        document.onmousemove = null;
    }
}
*, *:before, *:after {
    margin: 0;
    padding: 0;
    -webkit-box-sizing: border-box; 
    box-sizing: border-box;
}

.slider-container {
    position: relative;
    height: 80vh;
    overflow-x: scroll;
    overflow-y: hidden;
}

.slider-container::-webkit-scrollbar {
    display: none !important;
}

.slider-all-items {
    position: absolute;
    display: inline-flex;    
}

.slider-item {
    width: calc(100vw - 0px);
    height: 80vh;
    cursor: grab;
    display: block;
}

.slider-item1 {
    background: red;
}

.slider-item2 {
    background-color: blue;
}

.slider-item3 {
    background-color: yellow;
}

.shifting{
    transition: all 0.5s ease;
}
<div data-item="slider-full" class="slider-container">
    <div class="slider-all-items">
        <div class="slider-item slider-item1"></div>
        <div class="slider-item slider-item2"></div>
        <div class="slider-item slider-item3"></div>
    </div>
</div>

【问题讨论】:

  • 您能否提供更多关于您尝试达到的效果的具体细节?
  • 我想提供帮助,但目前还不清楚您想在代码行为中改进什么。您指定您的目标是“即使在 window.resize 上也有响应,始终全屏显示(项目宽度:100vw 或 100%)并且没有无限模式。”。然而,它已经在调整窗口大小时调整大小,总是达到容器宽度的 100%,并且没有无限滚动。我看不到缺少什么。另外,我不明白您刷新部分屏幕的特定内容是什么意思。你是怎么做到的?
  • 已编辑,请检查。

标签: javascript jquery


【解决方案1】:

我相信我们可以消除故障并实现等宽的 div(滑块项),因为您已经使用了全屏 = 宽度 100%)而无需重新加载。

只需使用ResizeObserver:我相信我们所要做的就是在调整窗口大小时调用“closeDragElement”函数,因为这是计算滑块大小的唯一函数。 p>

ResizeObserver 的 CDN。

代码

        // get the slider
        var theSlider = document.querySelector(".slider-all-items");
        // get the items in the slider
        var sliderItem = document.querySelectorAll('.slider-item');

        // variables saved for later
        var sliderWidth;
        var sliderRight;

        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
            // get the mouse cursor position at startup:
            pos3 = e.clientX;
            document.onmouseup = closeDragElement;
            // call a function whenever the cursor moves:
            document.onmousemove = elementDrag;
        }

        function elementDrag(e) {
            e = e || window.event;
            e.preventDefault();
            // calculate the new cursor position:
            pos1 = pos3 - e.clientX;
            pos3 = e.clientX;

            // set the element's new position:
            theSlider.style.left = (theSlider.offsetLeft - pos1) + "px";
        }

        function closeDragElement() {
            // get each item width
            sliderWidth = theSlider.getBoundingClientRect().width / sliderItem.length;
            // get the right side position of the slider
            sliderRight = theSlider.getBoundingClientRect().right;
            // get the left side position of the slider
            sliderLeft = theSlider.getBoundingClientRect().left;

            if (sliderLeft >= 0) {
                theSlider.style.left = "0px";
            }

            if (sliderRight <= sliderWidth) {
                theSlider.style.left = -Math.abs((sliderWidth * sliderItem.length) - sliderWidth) + "px";
            }
            // stop moving when mouse button is released:
            document.onmouseup = null;
            document.onmousemove = null;
        }

        function dragElement(theSlider) {
            var pos1 = 0, pos3 = 0;
            theSlider.onmousedown = dragMouseDown;
            theSlider.addEventListener('resize', closeDragElement);
        }

        dragElement(theSlider);

        /* global ResizeObserver */

        const ro = new ResizeObserver(entries => {
            for (let entry of entries) {
                closeDragElement();
            }
        });

        ro.observe(theSlider); //<-- NOTICE HERE
*,
        *:before,
        *:after {
            margin: 0;
            padding: 0;
            -webkit-box-sizing: border-box;
            box-sizing: border-box;
        }

        .slider-container {
            position: relative;
            height: 80vh;
            overflow-x: scroll;
            overflow-y: hidden;
        }

        .slider-container::-webkit-scrollbar {
            display: none !important;
        }

        .slider-all-items {
            position: absolute;
            display: inline-flex;
        }

        .slider-item {
            width: calc(100vw - 0px);
            height: 80vh;
            cursor: grab;
            display: block;
        }

        .slider-item1 {
            background: red;
        }

        .slider-item2 {
            background-color: blue;
        }

        .slider-item3 {
            background-color: yellow;
        }

        .shifting {
            transition: all 0.5s ease;
        }
<div data-item="slider-full" class="slider-container">
        <div class="slider-all-items">
            <div class="slider-item slider-item1"></div>
            <div class="slider-item slider-item2"></div>
            <div class="slider-item slider-item3"></div>
        </div>
    </div>

之前: https://www.dropbox.com/s/y0oy4rwnlj5la4g/before.gif?dl=0

之后: https://www.dropbox.com/s/jsqba0ef61ibef1/after.gif?dl=0

【讨论】:

  • 问题是我在调整窗口大小时全屏尝试问题中的 jsfiddle 示例。我想做的是一个可拖动的画廊幻灯片。在拖动时在items 之间切换,请检查 jsfiddle 示例
  • 能否请您添加您正在谈论的故障的 gif 图像?我刚刚添加了我在您共享的代码中看到的故障的 gif(在 Dropbox 上)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 1970-01-01
  • 1970-01-01
  • 2016-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多