CSS transition实现3D轮播首尾切换翻转异常求无坐标修改简易方案
轮播首尾切换异常翻转修复方案
根因说明
异常翻转是CSS transition的角度过渡默认走最短路径导致的:首尾切换时,轮播元素的rotateY目标值和当前值的差值绝对值超过180度,浏览器会选择反向旋转的更短路径过渡,而非按轮播方向旋转一圈,就会出现异常翻转效果。
修复方案
无需修改原有坐标计算逻辑,仅需增加几行角度校正代码,将过渡的角度差值控制在±180度范围内即可:
- 为每个轮播元素增加自定义属性存储当前实际使用的旋转角度
- 每次渲染计算出目标角度后,对目标角度做等效转换,保证和上一次使用的角度差值不超过±180度
修改后完整JS代码
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) // 初始化存储当前旋转角度的自定义属性 newEl.currentRot = 0 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")} // 计算目标原始角度 let targetRot = this.rtod(rad) // 角度校正,保证过渡路径正确 let diff = targetRot - each.currentRot while(diff > 180){ targetRot -= 360 diff = targetRot - each.currentRot } while(diff < -180){ targetRot += 360 diff = targetRot - each.currentRot } // 更新存储的当前角度 each.currentRot = targetRot each.style.transform = `translate3d(${x}px,0%,${y}px)` each.style.transform += `rotateY(${targetRot}deg)` }) } rtod(radians){ return radians * (180/Math.PI) } } const s = new slider(document.body)
CSS和HTML代码无修改,保持原有逻辑即可。
内容的提问来源于stack exchange,提问作者Amir Rahman
相关产品推荐
相关产品推荐

