首页 > 其他分享 >纯js实现图片无缝循环走马灯效果支持拖拽和惯性滑动

纯js实现图片无缝循环走马灯效果支持拖拽和惯性滑动

时间:2023-03-02 15:36:27浏览次数:36  
标签:endeSpeed style touch region piiic js var 走马灯 拖拽

要求实现一个无缝循环的图片滚动公告,支持上下,左右模式。

要求 1,不可有卡顿图片无缝轮播

         2 ,手指拖拽暂停轮播,用户可左右(或上下)拖拽,快速滑动有惯性效果。

         3, 用户拖拽完成后3秒继续播放循环滚动。

         4,页面上可以存在多个走马灯。

这种需求和轮播图类似,但效果区别是轮播图是一张张切换,有切换的效果,我们要求更接近滚动公告效果。

 

 

 

实现逻辑 1 视窗设置overflow:hidden,复制dom结构追加到父元素上,让父元素总宽度超过视窗宽度(代码里paetPiiic为视窗,piiic_region为父元素,piiic_item为要求轮播的元素)

                2 设置定时器,修改父元素piiic_region的left(或top)值,处理边界

                3 touch start touchmove touchend事件绑定,touchmove的时候piiic_region跟手指左右(上下)移动,处理边界。

                4 touchend的时候,获取手指滑动速度,给元素继续设置惯性移动,直至速度为0,每次移动要处理边界。

代码实现:我们的需求是要求上下和左右以及轮播速度可在后台配置的,所有有些属性写在dom上取用。

<!--上下方向图片-->
<div class="partPiiic" style="position: absolute;width: 3.75rem;height: 3.75rem;top: 0rem;left: 0rem;overflow:hidden" slidespeed="10">
      <div class="piiic_region" slidedirection="UD" slidespeed="10" style="position: relative; width: 100%;">
        <div class="piiic_item" style="position:relative;width:100%">
          < img style="width:100%;display:block;" src="test.jpg">
        </div>
      </div>
    </div>
<!--左右方向-->
<div class="partPiiic" style="position: absolute;width: 3.75rem;height: 1.81rem;top: 3.88rem;left: 0rem;overflow:hidden" slidespeed="10">
      <div class="piiic_region" slidedirection="LR" slidespeed="10" style="display: flex; position: relative; height: 100%; ">
        <div class="piiic_item" style="position:relative;height:100%" >
          < img style="height:100%" src="test1.jpg">
        </div>
      
      </div>
    </div>

js代码:

window.onload = function () { 
 //初始化图片走马灯
longPicInit(); 
}
function longPicInit() {
    var container = document.querySelector("body");
    var partPiiicList = container.querySelectorAll(".partPiiic");
    if (partPiiicList.length > 0) {
        for (var index = 0; index < partPiiicList.length; index++) {
            var partPiiicNode = partPiiicList[index];
               //存在其他业务逻辑,删除后只保留走马灯逻辑
               //根据你自己的实际情况,获取到所有走马灯元素即可
                //执行循环动画              
                loopLongPic(partPiiicNode);         
        }
    }
}
//主方法
function loopLongPic(partPiiicNode) {
//timeflag标志位 offspeed走马灯每次移动距离 copynum需要复制的子元素数量 var timeFlag = 1, offSpeed = 1, copyNum = 1, picTimer; var piiic_region = partPiiicNode.querySelector(".piiic_region"); var speed = piiic_region.getAttribute("slidespeed"); //走马灯速度 var deraction = piiic_region.getAttribute("slidedirection");//走马灯方向 上下还是左右 var piiic_item = piiic_region.querySelector(".piiic_item");//走马灯元素 if (deraction == "LR") {
//根据视图宽度除子元素宽度计算需要复制几个子元素 copyNum = Math.ceil(partPiiicNode.offsetWidth / piiic_item.offsetWidth); var text = $(piiic_region).html(); for (var i = 0; i < copyNum; i++) {
//复制后追加 $(piiic_region).append(text); } piiic_region.style.width = piiic_item.offsetWidth * (copyNum + 1) + "px"; } else {
//上下方向上的复制,逻辑同理 copyNum = Math.ceil(partPiiicNode.offsetHeight / piiic_item.offsetHeight); var text = $(piiic_region).html(); for (var i = 0; i < copyNum; i++) { $(piiic_region).append(text); } piiic_region.style.height = piiic_item.offsetHeight * (copyNum + 1) + "px"; }
//复制后,开启跑马灯 picTimer = setInterval(LoopMove, speed) function LoopMove() { if (timeFlag == 0) { clearInterval(picTimer) picTimer = null; return false; } if (deraction == "LR") {
//边界处理函数,到头拉回 criticalX() piiic_region.style.left = piiic_region.offsetLeft - offSpeed + "px"; } if (deraction == "UD") { criticalY(); piiic_region.style.top = piiic_region.offsetTop - offSpeed + "px"; } }

//添加touch事件 var touchStartX = 0,touchStartY = 0, moveStartY = 0, starttime = 0,restart, animateMoveTimer; piiic_region.addEventListener("touchstart", function (e) { if (picTimer) { clearInterval(picTimer); picTimer = null; } if (restart) { clearTimeout(restart); restart = null; } if (animateMoveTimer) { clearInterval(animateMoveTimer) } timeFlag = 0 //暂停定时器 手动拖拽上下左右距离 var ev = e || window.event; var touch = ev.targetTouches[0];
//记录touch初始位置 touchStartX = touch.pageX; touchStartY = touch.pageY;
//记录元素初始位置 moveStartX = piiic_region.offsetLeft; moveStartY = piiic_region.offsetTop; starttime = Date.now(); piiic_region.addEventListener("touchmove", preventDefault, false); }) piiic_region.addEventListener("touchmove", picImgMove) function picImgMove(e) { timeFlag = 0; if (timeFlag == 0) { var ev = e || window.event; var touch = ev.targetTouches[0] if (deraction == "LR") {//左右移动
//根据当前位置-初始位置计算手指移动距离 改变元素left
var moveX = touch.pageX - touchStartX; piiic_region.style.left = moveStartX + moveX + "px"; criticalX() } if (deraction == "UD") {//上下移动 var moveY = touch.pageY - touchStartY; piiic_region.style.top = moveStartY + moveY + "px"; criticalY() } } } piiic_region.addEventListener("touchend", function (e) { piiic_region.removeEventListener("touchmove", preventDefault); //获取最总结束位置 var ev = e || window.event; var touch = ev.changedTouches[0] var time = Date.now() - starttime;
//获取手指滑动速度 设置参数 可以根据自己想要的效果设置不同值 var endeSpeed = 0, rationSpeed = 40; //执行惯性移动 if (deraction == "LR") { var distanceX = touch.pageX - touchStartX; endeSpeed = (distanceX / time) * rationSpeed; animateMove(endeSpeed) } if (deraction == "UD") { var distanceY = touch.pageY - touchStartY; endeSpeed = (distanceY / time) * rationSpeed; animateMove(endeSpeed) } }) function animateMove(endeSpeed) { if (animateMoveTimer) { clearInterval(animateMoveTimer) } //endeSpeed是结束时的初速度,a为加速度,每隔1ms速度递减执行当前速度*1ms时间的距离,如果速度接近0,则清除计时器 var a = endeSpeed < 0 ? 2 : -2; animateMoveTimer = setInterval(function () { if (Math.abs(endeSpeed) < 1) { clearInterval(animateMoveTimer); if (picTimer) {clearInterval(picTimer); picTimer = null;} if (restart) {clearTimeout(restart); restart = null;} restart = setTimeout(function () { timeFlag = 1; picTimer = setInterval(LoopMove, speed); }, 3000); return; } endeSpeed += a; if (deraction == "LR") { piiic_region.style.left = piiic_region.offsetLeft + endeSpeed + "px"; criticalX(); } if (deraction == "UD") { piiic_region.style.top = piiic_region.offsetTop + endeSpeed + "px"; criticalY(); } },1) } //边界处理函数 function criticalX() { if (piiic_region.offsetLeft < -piiic_region.offsetWidth / (copyNum + 1)) {
//拖到最右边 循环 piiic_region.style.left = 0; } else if (piiic_region.offsetLeft >= 0) {
//拖到最左边 循环 piiic_region.style.left = -piiic_region.offsetWidth / (copyNum + 1) + "px"; } } function criticalY() { if (piiic_region.offsetTop < -piiic_region.offsetHeight / (copyNum + 1)) { piiic_region.style.top = 0 } else if (piiic_region.offsetTop >= 0) { piiic_region.style.top = -piiic_region.offsetHeight / (copyNum + 1) + "px"; } } }

 



 

标签:endeSpeed,style,touch,region,piiic,js,var,走马灯,拖拽
From: https://www.cnblogs.com/stt-bky/p/17171899.html

相关文章

  • JS 获取浏览器的宽和高
    网页可见区域宽:document.body.clientWidth网页可见区域高:document.body.clientHeight网页可见区域宽:document.body.offsetWidth(包括边线的宽)网页可见区域高:document.bod......
  • js返回上一页面
    一、history.back()和history.go(-1)history.back()和history.go(-1)都是返回之前页面,但是方法不同,所以是有区别的:history.back(-1) //直接返回当前页的上一页,数......
  • vue项目引用vue-pdf打包多出worker.js文件
    问题描述:项目要用到pdf预览功能,因为是vue项目就是直接导入了vue-pdf组件,但是在进行打包的时候在dist文件夹下面多个worker.js文件,导致项目部署后预览pdf直接报了404 方......
  • 视频直播源码,js实现节流和防抖
    视频直播源码,js实现节流和防抖防抖:就是指连续触发事件但是在设定的一段时间内中只执行最后后一次,例如:设定1000毫秒执行,当你触发事件了,他会1000毫秒后执行,但是在还剩500毫......
  • node.js 版本不对,
    1.在知道版本的情况下,用nvm切换一下对应的版本应该就没问题了。在运行前端程序的时候。经常会遇到node.js版本不对的情况。今天我也碰到了这个情况。经查询查,发现了一个no......
  • 洛谷P4051 [JSOI2007]字符加密 题解 后缀数组sa的应用
    题目链接:https://www.luogu.com.cn/problem/P4051题目大意:给定一个长度为\(n\)的字符串\(s\),每次将\(s\)的首字符取出放到末尾……这样能得到\(n\)个字符串。将......
  • 我们后端代码这样子设置虽然这样子返回的是字符串,但是json字符串也是字符串
    我们后端代码这样子设置虽然这样子返回的是字符串  但是json字符串也是字符串,后端如果想接收的话,直接百度下怎么接收json字符串就行   ......
  • Js 根据视频链接取该视频第一帧的图片,并返回Base64
    <!DOCTYPEhtml><html><head><title>GetVideoFrameExample</title></head><body><divid="result"></div><script>//获取视频第一帧的......
  • 腾讯视频js逆向过程
    今天很开心,讲一讲腾讯视频的js逆向过程,是过程,不是破解方法,也没有什么源代码,当然你可以看懂之后自己写出来。再顺便说下腾讯视频程序员的加密手段很狡猾。比爱奇艺不知道好多少。......
  • mysql5.7之JSON数据类型
    1、json对象1.1、方法使用对象操作的方法进行查询:字段->'$.json属性'使用函数进行查询:json_extract(字段,'$.json属性')获取JSON数组/对象长度:JSON_LENGTH()1.2、......