旋转相册与导航跟随双向绑定
头部js,转换rem
function IsPC() { var userAgentInfo = navigator.userAgent; var reg = new RegExp("(Android|iPhone|SymbianOS|Windows Phone|iPad|iPod)", "ig"); var isPC = !reg.test(userAgentInfo); return isPC } var initFontSize = function () { var n = document.getElementsByTagName("html")[0], e = document.documentElement.clientWidth; if (IsPC()) { if (e > 750) { n.style.fontSize = "50px" } else { n.style.fontSize = e / 750 * 50 + "px" } } else { n.style.fontSize = e / 750 * 50 + "px"; } }; initFontSize(); window.onresize = function () { initFontSize() };
css部分
* { padding: 0; margin: 0; } body { background-color: #fff; perspective: 8rem; /*filter: grayscale(100%);*/ width: 15rem; overflow: hidden; } .wrapper { width: 1.2rem; height: 1.2rem; /* 当前元素水平居中 */ margin: 3.6rem auto; position: relative; /* 当前元素为3d立体的 */ transform-style: preserve-3d; transform: rotateX(-10deg) rotateY(360deg); user-select: none; } .wrapper img { position: absolute; /* width,height的百分比默认会相对于父级 但是会受到自身position的影响而改变 */ width: 100%; height: 100%; /* z-index: 100; */ background-color: transparent; /* 监听到transform属性变化的时候会有动画 */ transition: -ms-text-align-last: left; /*transition:all 1s; text-align-last: left; 1s;*/ transform: scale(0); /* transform: rotateY(0deg) translateZ(0px); */ /*-webkit-box-reflect: below 0.2rem -webkit-linear-gradient(top, rgba(0, 0, 0, 0) 50%,rgba(0, 0, 0, 0.5) 100% );*/ } .container { width: 15rem; border-radius: 1rem; height: 1rem; border: 1px solid #888; margin: 0 auto; overflow: hidden; position: relative; color: #000; } .container ul { height: 100%; margin: 0; padding: 0; list-style: none } .container li { float: left; width: 1rem; height: 100%; position: relative; display: flex; } .container li i { font-style: normal; display: inline-block; transform: translate(-50%, 5px); font-size: 14px } .container li::after { content: ""; position: absolute; border-left: 1px solid #aaa; height: 13px; left: 0; bottom: 5px } .container .center { width: 5px; height: 100%; position: absolute; background: #f40; left: 50%; top: 0; transform: translateX(-50%) } #chooseResult { text-align: center; height: 1rem; line-height: 1rem; color: #000; font-size: 24px; } .main { width: 7.5rem; height: 6rem; margin: 0 auto; position: relative; overflow: hidden; } .main::before, .main::after { background: linear-gradient(to right, #fff 0, rgba(255, 255, 255, 0) 100%); height: 100%; top: 0; z-index: 100; pointer-events: none; display: block; content: ''; left: 0; position: absolute; width: 40px; } .main::after { right: 0; left: inherit; transform: rotate(180deg); }
body部分
<div class="main"> <!-- ! + tab/enter --> <div class="wrapper" style="transform: rotateX(-10deg) rotateY(0deg);"> <!-- img[src=./img/$.png]*11 --> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/d.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/e.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/f.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/g.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/h.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/i.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/j.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/k.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/l.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/m.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/n.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/o.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/p.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/r.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/s.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/t.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/u.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/v.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/w.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/x.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/y.png" alt="" draggable="false"> <img src="https://4cs.gia.edu/cn/interactive-4cs/img/color/z.png" alt="" draggable="false"> </div> </div> <h2 id="chooseResult"> </h2> <div class="container"> <ul> <li>d</li> <li>e</li> <li>f</li> <li>g</li> <li>h</li> <li>i</li> <li>j</li> <li>k</li> <li>l</li> <li>m</li> <li>n</li> <li>o</li> <li>p</li> <li>r</li> <li>s</li> <li>t</li> <li>u</li> <li>v</li> <li>w</li> <li>x</li> <li>y</li> <li>z</li> </ul> <div class="center"></div> </div>
相册旋转js
var imgList = document.getElementsByTagName('img'); var wrapper = document.getElementsByClassName('wrapper')[0]; var list_box = document.getElementsByClassName('list_box')[0]; var main = document.getElementsByClassName('main')[0]; var list_item = document.querySelectorAll('.list div'); var rotateY = 0; wrapper.style.transform = 'rotateX(' + -5 + 'deg) rotateY(' + 360 + 'deg)'; // 每相邻两张图片的夹角 var deg = 360 / imgList.length; window.onload = function() { wrapper.style.transform = 'rotateX(' + -5 + 'deg) rotateY(' + 360 + 'deg)'; // 每相邻两张图片的夹角 for(var i = 0; i < imgList.length; i++) { imgList[i].style.transform = "rotateY(" + deg * i + "deg) translateZ(200px) scale(1)"; imgList[i].style.transitionDelay = (imgList.length - 1 - i) * 0.1 + 's'; } var lastX = null, lastY = null, nowX = null, nowY = null, disX = null, disY = null, // 当前相册旋转的角度 rotateX = -10, //预设角度 rotateY = 0; var timer = null; var nowrotateY = null, //点击 初始旋转角度 lastrotateY = null, //点击结束 旋转角度 disrotateY = null, //开始与结束旋转的差值 activeIndex = 0, //当前显示的图片下标 num = null; //当前显示img 与 显示下一张 角度的差值 main.addEventListener("touchstart", function(e) { wrapper.style.transition = ""; lastX = e.changedTouches[0].pageX; lastY = e.changedTouches[0].pageY; noY = e.changedTouches[0].pageX; nowrotateY = getTranslateY(wrapper); falg = true; if(nowrotateY < deg) { wrapper.style.transform = 'rotateX(' + -5 + 'deg) rotateY(' + 360 + 'deg)'; } rotateY = nowrotateY; main.addEventListener("touchmove", function(e) { nowX = e.changedTouches[0].pageX; nowY = e.changedTouches[0].pageY; disX = nowX - lastX; disY = nowY - lastY; rotateX += -disY * 0.15; rotateY += disX * 0.15; //拖拽相册,旋转的角度比例 index = isIndex(); //设置旋转角度区间 if(rotateY > 360 - deg) { rotateY = rotateY - 360; } else if(rotateY < 0) { rotateY = rotateY + 360; } index = isIndex(); wrapper.style.transform = 'rotateX(' + -5 + 'deg) rotateY(' + rotateY + 'deg)'; lastY = nowY; lastX = nowX; setChoose(index); //传入当前显示的index触发导航栏跟随滚动 }, false) main.addEventListener("touchend", function(e) { laY = e.changedTouches[0].pageX; lastrotateY = getTranslateY(wrapper) main.removeEventListener("touchmove", function() {}, false); disrotateY = laY - noY; //与开始旋转的差值 num = Math.ceil(getTranslateY(wrapper) / deg) * deg - getTranslateY(wrapper); //与下一个36度的差值 //拖拽相册 旋转顺滑 if(laY > noY && falg) { rotateY = getTranslateY(wrapper) + num; } else { rotateY = getTranslateY(wrapper) - (deg - num); } if(falg) { falg = false; wrapper.style.transition = "1s"; wrapper.style.transform = 'rotateX(' + -5 + 'deg) rotateY(' + Math.ceil(rotateY) + 'deg)'; } setChoose(isIndex()); //传入当前显示的index触发导航栏跟随滚动 }, false) }, false) //判断当前index function isIndex() { var rote = getTranslateY(wrapper); var i = Math.round(rote / deg); i = imgList.length - Math.abs(i); if(rote < deg) { i = 0 } return Math.abs(i) } } //获取元素rotateY function getTranslateY(node) { var regRule = /rotateY(Y|\dd)?\(\s*(\w+\s*,)?\s*([^,]+)(\s*,[^)]+)?\s*\)/; var transform = node.style.transform; var reg; if(!transform) { return null; } reg = regRule.exec(transform); return +reg[3].split('deg')[0]; }
导航拖拽js
//$(function(){ //var activeIn=window.sessionStorage.getItem('activeIndex'); //if (!activeIn) { // activeIn = window.sessionStorage.setItem('activeIndex',0) //}else{ // console.log(activeIn) //} //$('.but').eq(activeIn).addClass('active').siblings().removeClass('active'); //$('.but').click(function(){ // console.log($('.but')) // let index = $(this).index()-$('.but').length; // console.log(index) // activeIn = window.sessionStorage.setItem('activeIndex',index) // $(this).addClass('active').siblings().removeClass('active'); //// $(".invitation_card_lst ul").eq(index).addClass('active').siblings().removeClass('active'); //}) //}) // // var config = { container: document.querySelector(".container"), optionWidth: 70, title: document.getElementById("chooseResult"), newindex:null, lastindex:null, disindex:null, options: [ { value: 0, text: "d" }, { value: 1, text: "e" }, { value: 2, text: "f" }, { value: 3, text: "j" }, { value: 4, text: "h" }, { value: 5, text: "j" }, { value: 6, text: "j" }, { value: 7, text: "k" }, { value: 8, text: "l" },{ value: 9, text: "m" }, { value: 10, text: "n" }, { value: 11, text: "o" }, { value: 12, text: "p" }, { value: 13, text: "r" }, { value: 14, text: "s" }, { value: 15, text: "t" }, { value: 16, text: "u" }, { value: 17, text: "v" }, { value: 18, text: "w" },{ value: 19, text: "x" }, { value: 20, text: "y" }, { value: 21, text: "z" }] } config.ul = config.container.querySelector("ul"); config.containerWidth = config.container.clientWidth; config.ulWidth = config.options.length * config.optionWidth; config.maxLeft = config.containerWidth / 2; config.minLeft = config.maxLeft - config.ulWidth + config.optionWidth; function forbiddenSelect() { config.container.onselectstart = function() { return false } } function createOptions() { config.ul.innerHTML = ""; var frag = document.createDocumentFragment(); config.ul.style.width = config.ulWidth + "px"; for(const op of config.options) { var li = document.createElement("li"); li.innerHTML = `<i data-value="${op.value}">${op.text}</i>`; li.style.width = config.optionWidth + "px"; frag.appendChild(li); } config.ul.appendChild(frag); } //导航跟随 function setChoose(value) { config.ul.style.transition = ".8s"; var children = Array.from(config.ul.children); var left = config.containerWidth / 2 - value * config.optionWidth; config.ul.style.marginLeft = left + "px"; } //相册跟随 var nowindex=null; var lastindex=null; function setRote({value}){ nowindex=value; rotateY=360-nowindex*deg wrapper.style.transition = ".5s"; wrapper.style.transform = 'rotateX(' + -5 + 'deg) rotateY(' + rotateY+ 'deg)'; lastindex=nowindex; } function getChoose() { var left = getComputedStyle(config.ul).marginLeft; left = parseFloat(left) - config.containerWidth / 2; left = Math.abs(left); var i = left / config.optionWidth; i = Math.round(i); return config.options[i]; } function regDragEvent(callback) { config.ul.addEventListener("touchstart",function(e) { config.ul.style.transition = ""; wrapper.style.transition = ""; //保存,深克隆初始位置,避免被更改 var x = {a:e.changedTouches[0].pageX}, left ={a:parseFloat(getComputedStyle(this).marginLeft)} ; left1={...left}; x1={...x}; config.ul.addEventListener("touchmove", function(e) { var dis = e.changedTouches[0].pageX - x1.a; var newLeft = left1.a + dis; if(newLeft < config.minLeft) { newLeft = config.minLeft; } else if(newLeft > config.maxLeft) { newLeft = config.maxLeft; } config.ul.style.marginLeft = newLeft + "px"; callback && callback(getChoose()); setRote(getChoose()); }) config.ul.addEventListener("touchend", function(e) { var op = getChoose(); setChoose(op.value); callback && callback(op); }) }) } function setTitle(op) { config.title.innerText = `选中的文本:${op.text},选中的值:${op.value}`; } function init() { forbiddenSelect(); createOptions(); setChoose("0"); setTitle(config.options[0]); regDragEvent(setTitle); } init();
....