css 滑块的过渡问题

css transition issue with slider

我在这里提供了我所有的代码似乎都很好问题是当我从最后一张幻灯片更改为第一张幻灯片或相反时,在这两种情况下所有幻灯片都以不同的方式翻转而不是像其他 sildes 一样旋转

render()函数就是所有坐标都在计算的地方 我认为问题在于 CSS 过渡,因为它的主要内容是动画幻灯片,如果您能找到任何解决方法,我看不到任何简单的解决方法请告诉我,请寻找简单的解决方案或可能性,而不会与 co 混淆太多-坐标。提前致谢

class slider {
    constructor(){
        if(typeof arguments[0] != "undefined"){
            this.init()
            arguments[0].appendChild(this.html)
            this.calculate()
            this.render(1)
        }
        else{this.init()}
    }
    init(){
        let obj = this
        this.html = `
<div class="root border-2 p-5 border-black m-auto">
    <div class="each border border-black absolute text-center">item name 1</div>
</div>
        ` 
        let el = document.createElement("div")
        el.innerHTML = this.html
        this.html = el.querySelector("*")
        this.root = this.html

        let eEl = this.root.querySelector(".each")
        this.eachTemp = eEl.cloneNode(true)
        eEl.remove()

        this.fillBoxes(6)
        this.html.addEventListener("click",function(e){
            obj.onclick(obj,e)
        })
    }

    onclick(obj,e){
        let t = e.target
        if(t.closest(".each")){
            obj.render(t.index)
        }
    }

    fillBoxes(num){
        for(let i=0;i<num;i++){
            let newEl = this.eachTemp.cloneNode(true)
            newEl.index = i+1
            newEl.innerText = "Item " + (i+1)
            this.html.appendChild(newEl)
        }
        this.els = this.html.querySelectorAll(".each")
    }

    calculate(){
        this.eCor = this.els[0].getClientRects()[0]
        this.mag = this.eCor.width
        this.per = Math.PI / (this.els.length / 2)
        this.deg = this.rtod(this.per)        
    }

    render(index){
        this.els.forEach((each,i)=>{
            let rad = (this.per * i) - this.per*(index-1),
                x = Math.sin(rad)*this.mag,
                y = Math.cos(rad)*this.mag
            if(i+1 == index){each.classList.add("active")}
            else{each.classList.remove("active")}
            each.style.transform = `translate3d(${x}px,0%,${y}px)`
            each.style.transform += `rotateY(${this.rtod(rad)}deg)`
        })
    }

    rtod(radians){
        return radians * (180/Math.PI)
    }        

}

const s = new slider(document.body)
.each{
        height: 250px;
        width: 250px;
        background: skyblue;
        opacity: 0.8;
        transform-origin: 50% 50%;
        transform-style: preserve-3d;
        user-select: none;
        filter: brightness(80%);
        transition: all 1s  cubic-bezier(0, 1.22, 0.53, 1.02);
        /* box-shadow: 0px 0px 10px 1px black; */
    }
    .each:nth-child(odd){background:lightsalmon}
    .root{
        height: 280px;
        width: 280px;
        position: relative;
        margin-top: 10%;        
        perspective: 1000px;        
        transform-style: preserve-3d;
        transition: transform 0.5s;
        /* animation: loop 4s infinite linear; */
    }
    .each:hover{
        z-index: 1000 !important;
        filter:brightness(110%);
    }
    .active{
        opacity: 1 !important;
        filter:brightness(100%) !important;
    }
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">

当您在 1 和 6 张幻灯片之间切换时,计算出的 rotatedY 值会从 0 度变为 300 度(或从 300 度变为 0 度)。但实际上你只需要±60deg update。因此,您需要一种机制来 increase/decrease 以两种方式无休止地旋转 Y,例如 240 -> 300 -> 360 -> 420 -> 480 ...(不是 240 -> 300 -> 0 -> 60 -> ...)

我建议您在 class:

中添加这些属性
currentIndex = 1;
radOffset = 0;

然后,当你点击元素时,你需要计算radOffset(它increases/decreases无穷无尽):

const totalElements = this.els.length;
const rightDiff = t.index > this.currentIndex ? t.index - this.currentIndex : totalElements + t.index - this.currentIndex;
const leftDiff = totalElements - rightDiff;
const closestDiff = rightDiff < leftDiff ? - rightDiff : leftDiff;

this.currentIndex = t.index;
this.radOffset += this.per * closestDiff;

然后在你的渲染函数中使用它:

let rad = (this.per * i) + this.radOffset,

class slider {
    
    currentIndex = 1;
    radOffset = 0;

    rotateOffset = 0;
        constructor(){
            if(typeof arguments[0] != "undefined"){
                this.init()
                arguments[0].appendChild(this.html)
                this.calculate()
                this.render(1)
            }
            else{this.init()}
        }
        init(){
            let obj = this
            this.html = `
    <div class="root border-2 p-5 border-black m-auto">
        <div class="each border border-black absolute text-center">item name 1</div>
    </div>
            ` 
            let el = document.createElement("div")
            el.innerHTML = this.html
            this.html = el.querySelector("*")
            this.root = this.html
    
            let eEl = this.root.querySelector(".each")
            this.eachTemp = eEl.cloneNode(true)
            eEl.remove()
    
            this.fillBoxes(6)
            this.html.addEventListener("click",function(e){
                obj.onclick(obj,e)
            })
        }
    
        onclick(obj,e){
            let t = e.target
            if(t.closest(".each")){
            
                const totalElements = this.els.length;
                const rightDiff = t.index > this.currentIndex ? t.index - this.currentIndex : totalElements + t.index - this.currentIndex;
                const leftDiff = totalElements - rightDiff;
                const closestDiff = rightDiff < leftDiff ? - rightDiff : leftDiff;

                this.currentIndex = t.index;
                this.radOffset += this.per * closestDiff;
                
                obj.render(t.index);
                
            }
        }
    
        fillBoxes(num){
            for(let i=0;i<num;i++){
                let newEl = this.eachTemp.cloneNode(true)
                newEl.index = i+1
                newEl.innerText = "Item " + (i+1)
                this.html.appendChild(newEl)
            }
            this.els = this.html.querySelectorAll(".each")
        }
    
        calculate(){
            this.eCor = this.els[0].getClientRects()[0]
            this.mag = this.eCor.width
            this.per = Math.PI / (this.els.length / 2)
            this.deg = this.rtod(this.per)        
        }
    
        render(index, rotateDiff){
            this.els.forEach((each,i)=>{
                let rad = (this.per * i) + this.radOffset,
                    x = Math.sin(rad)*this.mag,
                    y = Math.cos(rad)*this.mag
                if(i+1 == index){each.classList.add("active")}
                else{each.classList.remove("active")}
                 
                each.style.transform = `translate3d(${x}px,0%,${y}px)`
                each.style.transform += `rotateY(${this.rtod(rad)}deg)`
            })
        }
    
        rtod(radians){
            return Math.round(radians * (180/Math.PI));
        }        
    
    }
    
    const s = new slider(document.body)
.each{
        height: 250px;
        width: 250px;
        background: skyblue;
        opacity: 0.8;
        transform-origin: 50% 50%;
        transform-style: preserve-3d;
        user-select: none;
        filter: brightness(80%);
        transition: all 1s  cubic-bezier(0, 1.22, 0.53, 1.02);
        /* box-shadow: 0px 0px 10px 1px black; */
    }
    .each:nth-child(odd){background:lightsalmon}
    .root{
        height: 280px;
        width: 280px;
        position: relative;
        margin-top: 10%;        
        perspective: 1000px;        
        transform-style: preserve-3d;
        transition: transform 0.5s;
        /* animation: loop 4s infinite linear; */
    }
    .each:hover{
        z-index: 1000 !important;
        filter:brightness(110%);
    }
    .active{
        opacity: 1 !important;
        filter:brightness(100%) !important;
    }
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">