모바일 개발을 할 때 캐러셀 그래픽은 필수입니다. 다음 글에서는 순수 JS를 사용하여 모바일 웹 캐러셀 그래픽을 구현하는 방법에 대한 관련 정보를 주로 소개합니다. 중요한 것은 Tween 알고리즘을 결합하여 휠을 만드는 것입니다. 샘플 코드를 통해 자세히 살펴보겠습니다. 도움이 필요한 친구들이 함께 살펴보겠습니다.
머리말
이를 구현하는 가장 빠른 방법은 종종 스와이퍼와 같은 타사 코드를 사용하는 것이지만, 일부 경우에는 모바일 단말기의 캐러셀 이미지가 필요하다는 것을 모두가 알아야 한다고 생각합니다. 비교 복잡한 캐러셀이 필요할 때, 우리는 종종 당황하고 그것을 바꾸는 방법을 모릅니다.
그래서 우리는 다양하고 복잡하고 변화하는 요구에 적응하기 위해 스스로 바퀴를 만들려고 노력해야 합니다. 또 다른 점은 우리가 작성한 코드에 버그가 있으면 고치기가 매우 쉽고 자체적으로도 크게 개선되었다는 점입니다.
스와이퍼 소스 코드를 읽지 않고 간단하면서도 실용적인 모바일 캐러셀 차트를 직접 구현해 보았습니다. 의 생각과 실천 마침내 실현되었습니다(그림 참조).
모바일에서 캐러셀 이미지를 구현하는 것은 PC에서보다 더 복잡하며, 주로 다음 측면에서 그렇습니다.
1. 캐러셀 이미지는 다양한 상황에 맞게 조정되어야 합니다. 너비/dpr 화면
2. 터치 관련 이벤트를 사용해야 합니다
3. 모델마다 터치 이벤트 지원이 다르며 일부 호환성 문제가 있을 수 있습니다
4. 이동 손가락이 그림 거리의 일부이므로 남은 거리는 자동으로 완료되어야 합니다
5. 거리를 자동으로 완료하려면 용이성 시간 곡선이 필요합니다
하지만 프로그래밍 문제를 해결하는 아이디어는 비슷합니다.
캐러셀 차트를 사용할 때 주의 깊게 관찰할 수 있습니다. 현상을 통해 본질을 봅니다.
캐러셀 차트를 사용할 때 주의 깊게 관찰하고 현상을 통해 본질을 볼 수 있습니다.
Put your 사진에 손가락을 대고 손가락을 왼쪽이나 오른쪽으로 움직이면 그에 따라 사진도 움직입니다.
손가락이 조금 움직이면 사진이 자동으로 해당 위치로 돌아갑니다.
손가락이 왼쪽이나 오른쪽으로 빠르게 움직이면 자동으로 다음 사진으로 전환됩니다.
사진 회전판은 무한 루프입니다. 이를 달성하려면 3 1 2 3 1 방법, 즉 N+2 사진을 사용하여 N 사진의 무한 루프 캐러셀을 달성해야 합니다.
현상을 분석하여 기본 구현 계획을 제안할 수 있습니다.
1. 손가락 터치 이벤트는 3가지 이벤트를 통해 실현될 수 있습니다: touchstart touchmove touchend
2. 터치시작 x 좌표 시 손가락을 기록해야 하며, 터치의 pageX 속성을 사용할 수 있습니다.
3. 손가락이 이동하면 처음 두 단계에서 계산된 x 방향으로 이동한 거리, 시점의 차이를 기반으로 페이지 지점도 기록해야 합니다.
5. 이동 방향을 다음과 같이 결정합니다. x 방향으로 이동한 거리를 비교하고 다음 사진으로 전환해야 하는지 여부를 시간을 기준으로 사용자가 진행하는지 판단합니다. 좌우로 스와이프하는 작업
6. Translate3d를 사용하고 켜면 동영상이 생성됩니다. 하드웨어 가속
7. 특정 거리를 이동하려면 Tween 알고리즘에서 easyOut을 사용하여 매번 이동하는 거리를 실현할 수 있습니다. 물론 js를 사용하여 전환 애니메이션을 설정할 수도 있습니다.
head style
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=.5,maximum-scale=.5"> <title>移动端轮播图</title> <style> * { box-sizing: border-box; margin: 0; padding: 0 } .banner { overflow: hidden; width: 100%; height: 300px } .banner .img-wrap { position: relative; height: 100% } .banner img { display: block; position: absolute; top: 0; width: 100%; height: 100% } </style> </head>
<p class="banner"> <p class="img-wrap" id="imgWrap"> <img src="images/banner_3.jpg" data-index="-1"> <img src="images/banner_1.jpg" data-index="0"> <img src="images/banner_2.jpg" data-index="1"> <img src="images/banner_3.jpg" data-index="2"> <img src="images/banner_1.jpg" data-index="3"> </p> </p>
여기 HTMLElement.prototype.tweenTranslateXAnimate는 모든 HTML 요소 클래스로 확장된 tweenTranslateXAnimate 메서드입니다
특정 거리를 이동하려면 이 반복 작업을 완료하는 데 도움이 되는 타이머를 사용해야 합니다
<script> HTMLElement.prototype.tweenTranslateXAnimate = function (start, end, callback) { var duration = 50; var t = 0; var vv = end - start; var Tween = { Quad: { easeOut: function (t, b, c, d) { return -c * (t /= d) * (t - 2) + b; } } }; this.timer = setInterval(function () { var dis = start + Tween.Quad.easeOut(++t, 0, vv, duration); this.style.transform = 'translate3d(' + dis + 'px, 0, 0)'; if (vv > 0 && parseInt(this.style.transform.slice(12)) >= end) { this.style.transform = 'translate3d(' + parseInt(dis) + 'px, 0, 0)'; clearInterval(this.timer); callback && callback(); } if (vv < 0 && parseInt(this.style.transform.slice(12)) <= end) { this.style.transform = 'translate3d(' + parseInt(dis) + 'px, 0, 0)'; clearInterval(this.timer); callback && callback(); } }.bind(this), 4); } </script>
<script> ~function () { var lastPX = 0; // 上一次触摸的位置x坐标, 需要计算出手指每次移动的一点点距离 var movex = 0; // 记录手指move的x方向值 var imgWrap = document.getElementById('imgWrap'); var startX = 0; // 开始触摸时手指所在x坐标 var endX = 0; // 触摸结束时手指所在的x坐标位置 var imgSize = imgWrap.children.length - 2; // 图片个数 var t1 = 0; // 记录开始触摸的时刻 var t2 = 0; // 记录结束触摸的时刻 var width = window.innerWidth; // 当前窗口宽度 var nodeList = document.querySelectorAll('#imgWrap img'); // 所有轮播图节点数组 NodeList // 给图片设置合适的left值, 注意 querySelectorAll返回 NodeList, 具有 forEach方法 nodeList.forEach(function (node, index) { node.style.left = (index - 1) * width + 'px'; }); /** * 移动图片到当前的 tIndex索引所在位置 * @param {number} tIndex 要显示的图片的索引 * */ function toIndex(tIndex) { var dis = -(tIndex * width); var start = parseInt(imgWrap.style.transform.slice(12)); // 动画移动 imgWrap.tweenTranslateXAnimate(start, dis, function () { setTimeout(function () { movex = dis; if (tIndex === imgSize) { imgWrap.style.transform = 'translate3d(0, 0, 0)'; movex = 0; } if (tIndex === -1) { imgWrap.style.transform = 'translate3d(' + width * (1 - imgSize) + 'px, 0, 0)'; movex = -width * (imgSize - 1); } }, 0); }); } /** * 处理各种触摸事件 ,包括 touchstart, touchend, touchmove, touchcancel * @param {Event} evt 回调函数中系统传回的 js 事件对象 * */ function touch(evt) { var touch = evt.targetTouches[0]; var tar = evt.target; var index = parseInt(tar.getAttribute('data-index')); if (evt.type === 'touchmove') { var di = parseInt(touch.pageX - lastPX); endX = touch.pageX; movex += di; imgWrap.style.webkitTransform = 'translate3d(' + movex + 'px, 0, 0)'; lastPX = touch.pageX; } if (evt.type === 'touchend') { var minus = endX - startX; t2 = new Date().getTime() - t1; if (Math.abs(minus) > 0) { // 有拖动操作 if (Math.abs(minus) < width * 0.4 && t2 > 500) { // 拖动距离不够,返回! toIndex(index); } else { // 超过一半,看方向 console.log(minus); if (Math.abs(minus) < 20) { console.log('距离很短' + minus); toIndex(index); return; } if (minus < 0) { // endX < startX,向左滑动,是下一张 toIndex(index + 1) } else { // endX > startX ,向右滑动, 是上一张 toIndex(index - 1) } } } else { //没有拖动操作 } } if (evt.type === 'touchstart') { lastPX = touch.pageX; startX = lastPX; endX = startX; t1 = new Date().getTime(); } return false; } imgWrap.addEventListener('touchstart', touch, false); imgWrap.addEventListener('touchmove', touch, false); imgWrap.addEventListener('touchend', touch, false); imgWrap.addEventListener('touchcancel', touch, false); }(); </script>
물론 이것은 단지 데모일 뿐이며 실제 프로젝트에서 사용할 수 있으려면 추가적인 최적화와 캡슐화가 필요합니다.
이 데모는 문제를 해결하기 위한 아이디어만을 제공합니다. 이 아이디어를 통해 다양한 복잡한 요구 사항도 해결할 수 있다고 믿습니다...
위 내용은 네이티브 JS를 사용하여 모바일 웹 캐러셀 효과를 구현하는 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!