[js/css]iframe 在 iphone 下不能滚动的解决与自己做滑动控件
clq
浏览(533) -
2020-02-25 13:30:27 发表
编辑
关键字:
[2020-03-03 18:49:18 最后更新]
[js/css]iframe 在 iphone 下不能滚动的解决与自己做滑动控件 //-------------------------------------------------------- //目前的 iphone6 这样的,对 iframe 中的内容是不能滚动的 // //据说可以在 iphone 下解决 iframe 不滚动的问题 // -webkit-overflow-scrolling: touch; /* 当手指从触摸屏上移开,会保持一段时间的滚动 */ // -webkit-overflow-scrolling: auto; /* 当手指从触摸屏上移开,滚动会立即停止 */ //---- //也可以这样,但是对于动态页面就可能不合适 //<iframe name="iframe2" onload="this.height=iframe2.document.body.scrollHeight" src="iframe2.html" frameborder="0" width="100%"></iframe> //---- //<!--iframe外层加div 主要css:-webkit-overflow-scrolling:touch;overflow:auto!important;--> //---- //overflow-y: scroll; //这两的组合后确实可以,但是在 pc 上会很难看,怎样判断是 pc 呢 //改用 overflow-y: auto; 可以解决,但估计这种方式以后肯定是要改的//自己做滑动控件? 参考 https://blog.csdn.net/zfzhuman123/article/details/90520355 $("#" + _this_control.clientPanel.name).css("-webkit-overflow-scrolling", "touch"); //$("#" + _this_control.clientPanel.name).css("overflow-y", "scroll"); $("#" + _this_control.clientPanel.name).css("overflow-y", "auto"); 自己做滑动控件? 参考 https://blog.csdn.net/zfzhuman123/article/details/90520355
guest
2020-02-25 13:33:42 发表
编辑
基本原理就是把要拖动东西放到一个无限宽的容器中,然后改它的 left -------------------------------------------------------- 手把手教你用原生js来写一个swiper滑块插件(上)原理 原创 卧龙派 最后发布于2019-05-27 12:49:06 阅读数 807 收藏 展开 嗨~ 这里是芝麻,今天我们一块来做一个“滑块插件”。那么啥是滑块插件呢?滑块插件能干嘛呢?请看下图: 滑块插件演示 是不是有点印象了,没错,他的最基本的用法就是左右滑动,插件使用者只需要写几行简单的html和js即可实现一个简单滑动效果,不过你完全可以组合各种元素来适应不同的场景。 当然插件我已经写好了,咱先看下这个插件是怎么来用的,对插件有一个大概了解,一会写起来不至于太懵逼。。。 插件地址:https://github.com/laravuel/swiper.git demo目录有演示和用法,不过插件我用了webpack和babel转码,可以不用管,直接看src/swiper.js即可。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 就是这么简单,插件本身只是一个类,你只需要new一个对象出来,然后传递一些参数就ok了。而且,插件还提供了一个change方法,让使用者可以在外部控制滑块的滑动! const swiper = new Swiper({...}); swiper.change(2); // 滑动到第三个滑块 1 2 那么接下来,就是我们的教程时间了,我也不确定你能不能硬着头皮看完,不过我敢肯定,如果你能够亲手把插件写出来,你肯定会开心的飞起!!! 由于本次教程内容比较多,所以我分上下两部分来讲,第一部分主要讲解原理,第二部分开始着手编写插件。所以,感兴趣的小伙伴可以加个关注先。 1. 功能分析 俗话说,一上来就贴代码纯属耍流氓~ 我们要清楚自己想实现哪些功能,懒得思考的童鞋可以结合我上面的动图来分析: 滑块可以左右滑动(支持移动端和pc端) 滑块块内部可以写任何元素 滑动到第一个和最后一个滑块时会有一个限制,防止越界 能够自动播放 我们所能看到的大概就这些,接下来我们会对这些功能一一进行拆解和分析。 2. 实现原理 上面简单梳理了一些功能,其实可以再扩展出以下几个问题: 滑块的html结构是什么样的? 滑块的滑动原理是什么? 如何来触发滑动? 别急,一个个来 2.1.1 滑块的html结构是什么样的? 我们先来看一张图: 滑块结构 这就是一个滑块的最基本的结构图,有三个部分组成: 视图 我们的内容展示区域,相当于最外层的一个展示层 容器 容器的宽度是无限长的,容纳我们所有需要切换的内容,滑块的左右滑动,实质上是容器的左右移动(left),而每个滑块相对于容器其实是静止的 滑块 一个个的内容 那么根据这个结构,可以用如下html代码来表示: 1 2 3 4 5 6 7 8 9 10 然后再配上css样式: .swiper { position: relative; width: 300px; /* 下面是为了让大家看的更清楚,加的修饰 */ padding: 30px 0; margin: 0 auto; background: #FFB973; } .swiper .swiper-container { position: relative; /* 为啥要设置-300px呢,因为我想让他默认在第二个滑块的位置,一会会给大家演示 */ left: -300px; /* 让容器尽可能的宽,这样才能容纳更多的滑块 */ width: 10000%; /* 让内部滑块可以排成一行 */ display: flex; /* 下面是为了让大家看的更清楚,加的修饰 */ background: red; padding: 15px 0; } .swiper .swiper-container .swiper-item { /* 宽度设置1%会按照外层视图的宽度来铺满 */ width: 1%; height: 300px; background: #eee; /* 下面是为了让大家看的更清楚,加的修饰 */ text-align: center; font-size: 40px; color: #fff; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 你就会看到这么个效果: 初始效果 当然,你可以把我加的修饰css样式都给去掉,然后再试试。 2.1.2 滑块的滑动原理是什么? 如果你能够理解上面的html结构的话,那我们就可以进行滑动的讲解了。(如果还不理解的话,那就继续往下看吧~或许会突然恍然大悟!) 上面我们提到了“滑块容器”这个概念,滑块的左右移动就是他来负责的 .swiper .swiper-container { position: relative; left: -300px; } 1 2 3 4 因为滑块的宽度是和视图的宽度一样的,所以我们这里滑块的宽度是300px,那么我们把容器的left设置为-300px,就相当于向左移动了一个滑块的宽度,设置为-600px就表示向左移动了两个滑块的宽度,懂了吧,如果你想移动到某个滑块,那么只需要知道这个滑块的顺序(从0开始),然后乘以滑块宽度的相反数就行了,比如要移动到第三个滑块,他的顺序是2,那么就是2 * -300 = -600 看下面动图演示: 滑动切换 但是好像并没有出现滑动的动画效果耶,废话,还没写呢,有些童鞋可能喜欢用jquery,习惯了他的animate动画方法,说实话其实我不太喜欢,因为我觉得css自带的动画完全可以解决大部分需求,而且当你以后用了vue这种mvvm框架,你会发现jquery这种动画方式很不实用! 扯远了,不过今天我们不用css的animation属性,我们用另外一个属性transition就可以满足,看名字你也能猜到,就是一个过渡属性,详细的用法请参考:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions 我们把容器加上transition属性试试看哈: .swiper .swiper-container { /* 省略... */ transition: left 0.2s ease-in-out; } 1 2 3 4 5 滑动动画 所以,我们写的这段css代码transition: left 0.2s ease-in-out;是表示:如果元素的left值变更,那么会有一个0.2s的过渡动画(补间动画) 到这里,我觉得你应该能理解了吧,每个滑块swiper-item的左右滑动,并不是滑块本身在移动,而是他的父元素swiper-container容器在左右移动(left值变化),然后我们用transition属性来让这个变化过程出现一个过渡动画效果! 2.1.3 如何来触发滑动? 上面我们扯了一堆html和css,接下来我们说点js吧。 “如何来触发滑动?”,我们先不考虑手机端,就按照pc网页来,那么触发操作就是在容器上按住鼠标向左/右拖动,然后松开鼠标后,滑块就会向左/右滑动。 整个流程都跟鼠标事件挂钩: mousedown 鼠标按下事件 mousemove 鼠标移动事件 mouseup 鼠标抬起事件 利用好这3个事件,我们就可以来实现鼠标控制滑块移动了!!我们先来实现摁住鼠标向左、向右拖动滑块。 既然我们的容器swiper-container是负责左右移动的,那么我们就来监听他的鼠标事件吧,首先用querySelector获取视图和容器两个元素节点: // 首先获取视图层元素 const swiperEl = document.querySelector('.swiper'); // 在视图层里边查找容器元素 const containerEl = swiperEl.querySelector('.swiper-container'); 1 2 3 4 获取到容器元素后,就可以用他的addEventListener来监听事件了: containerEl.addEventListener('mousedown', (event) => { console.log('鼠标按下了'); }); containerEl.addEventListener('mousemove', (event) => { console.log('鼠标移动了'); }); containerEl.addEventListener('mouseup', (event) => { console.log('鼠标抬起了'); }); 1 2 3 4 5 6 7 8 9 看下动图操作: 鼠标按下抬起 虽然我们可以成功的监听到鼠标的操作事件,但是好像有点问题,我们期望的结果是,只有当鼠标按下后才会触发鼠标移动操作,但是现在看来并没有,所以可以考虑加一个状态来控制。 let state = 0; // 鼠标默认状态 containerEl.addEventListener('mousedown', (event) => { state = 1; // 设置为1表示按下了鼠标 console.log('鼠标按下了'); }); containerEl.addEventListener('mousemove', (event) => { if (state != 1) return; // 只有当state == 1时候才允许执行该事件 console.log('鼠标移动了'); }); containerEl.addEventListener('mouseup', (event) => { state = 0; // 恢复默认状态 console.log('鼠标抬起了'); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 鼠标事件这样就好多了!!! 那么鼠标事件有了,接下来要让容器跟着鼠标左右动才行。 我们要知道,浏览器对于鼠标的任何操作,都会有一个坐标参数(pageX和pageY),所以,我们可以根据鼠标移动时候的坐标参数来计算容器的left值,你可以想象一下,当你摁下鼠标然后左右移动,鼠标每次移动相对于上次都会产生一个距离,我们是不是可以把容器的left值加上或者减去这个距离,从而达到一个拖动效果呢?记得前面我们回调函数里边的event参数了吗,他就是鼠标当前操作的相关属性,而我们目前只需要用到pageX属性 event 下面我们来写代码,有个地方需要注意下,我们先把容器的transition这个属性给注释掉,后面会解释为什么? .swiper .swiper-container { /* 省略... */ /* transition: left 0.2s ease-in-out; */ } 1 2 3 4 5 每一步的操作,都在注释里边详细标注: // 首先获取视图层元素 const swiperEl = document.querySelector('.swiper'); // 在视图层里边查找容器元素 const containerEl = swiperEl.querySelector('.swiper-container'); let state = 0; // 鼠标默认状态 let oldEvent = null; // 用来记录鼠标上次的位置 // 获取容器的初始left值 let left = containerEl.offsetLeft; containerEl.addEventListener('mousedown', (event) => { state = 1; // 设置为1表示按下了鼠标 oldEvent = event; // 当鼠标按下时候记录初始位置 console.log('鼠标按下了'); }); containerEl.addEventListener('mousemove', (event) => { if (state != 1) return; // 只有当state == 1时候才允许执行该事件 // 用当前鼠标的位置来和上次鼠标的位置作比较 // 如果当前鼠标的pageX小于上次鼠标的pageX,那就表示鼠标在向左拖动,就需要把容器left值减去鼠标移动的距离 if (event.pageX < oldEvent.pageX) { left -= oldEvent.pageX - event.pageX; } else { left += event.pageX - oldEvent.pageX; } // 完事之后记得把当前鼠标的位置赋值给oldEvent oldEvent = event; // 最后再把left赋值给容器 containerEl.style.left = left + 'px'; console.log('鼠标移动了'); }); containerEl.addEventListener('mouseup', (event) => { state = 0; // 恢复默认状态 console.log('鼠标抬起了'); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 运行看效果: 鼠标拖动 没毛病,你看这个鼠标,他又白又。。。 可是,可是,你这鼠标松开后,也没滑动到对应位置啊,额,额,前面我们不是讲了嘛,滑块顺序、滑块宽度还记得么?0 - 滑块顺序 * 滑块宽度就会移动到这个滑块,还记得不? 我们用index来记录当前滑块的顺序 let index = 0; // 记录当前滑块的顺序(从0开始) 1 用itemWidth来存储滑块的宽度 // 获取到所有的滑块元素 const itemEls = containerEl.querySelectorAll('.swiper-item'); // 获取到滑块的宽度 const itemWidth = itemEls[0].offsetWidth; 1 2 3 4 把我们的left变量改一下,之前left变量是直接获取容器元素的left值,现在我们要根据index来计算 // let left = containerEl.offsetLeft; // 存储容器的left,这里我们根据index来计算初始容器的left值 let left = 0 - itemWidth * index; // 设置容器的初始位置 containerEl.style.left = left + 'px'; 1 2 3 4 5 这样我们只需要修改index变量的值,那么容器初始位置就会发生变化。 然后,我们在鼠标按下的时候,记录下坐标位置,在鼠标抬起的时候拿当前鼠标的位置和按下的位置作比较,来判断用户是向左划的,还是向右划的! 滑块左右移动判断 加一个变量,用来记录鼠标按下的参数,并且在鼠标按下的时候进行赋值! let startEvent = null; // 用来记录鼠标按下时候的位置(最初位置) containerEl.addEventListener('mousedown', (event) => { state = 1; // 设置为1表示按下了鼠标 startEvent = oldEvent = event; // 当鼠标按下时候记录初始位置 console.log('鼠标按下了'); }); 1 2 3 4 5 6 7 那么鼠标抬起的时候,只需要和startEvent.pageX做比较,就可以判断出左滑还是右滑,左滑我们让index + 1,右滑就让index - 1,最终我们通过index再来计算left containerEl.addEventListener('mouseup', (event) => { state = 0; // 恢复默认状态 // 鼠标抬起时候,和按下的坐标作比对,用来判断是向左滑动还是向右滑动 // 向左滑动那么就是要显示下一个滑块,所以index要加1 if (event.pageX < startEvent.pageX) { index ++; } else { index --; } left = 0 - itemWidth * index; containerEl.style.left = left + 'px'; console.log('鼠标抬起了'); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 鼠标抬起通过index设置滑块位置 是不是像那么回事了,不过怎么没滑动动画呢,还记得我们注释掉的那个transition么,为什么要注释掉呢,因为只有在鼠标抬起的那一刻才需要滑动动画,左右拖动是根据鼠标位移距离来计算left,数值很小,完全不需要衔接动画,所以,我们先把注释掉那个transition代码单独提取出来放到一个和swiper-container同级的.move类里边,当鼠标抬起的时候,我们把swiper-container追加一个move类就行。 .swiper .swiper-container.move { transition: left 0.2s ease-in-out; } 1 2 3 containerEl.addEventListener('mouseup', (event) => { state = 0; // 恢复默认状态 // 鼠标抬起时候,和按下的坐标作比对,用来判断是向左滑动还是向右滑动 // 向左滑动那么就是要显示下一个滑块,所以index要加1 if (event.pageX < startEvent.pageX) { index ++; } else { index --; } // 追加一个move样式 containerEl.className += ' move'; // 当过度动画结束后,一定要把这个类给移除掉 containerEl.addEventListener('transitionend', () => { // 正则替换 \s+ 表示一个或多个空白字符 containerEl.className = containerEl.className.replace(/\s+move/, ''); }) left = 0 - itemWidth * index; containerEl.style.left = left + 'px'; console.log('鼠标抬起了'); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 注意观察swiper-container的dom节点: 滑动雏形 仔细看上面的动图,第一个和最后一个滑动的时候是不是越界了,那么我们只需要判断index就行,看代码: containerEl.addEventListener('mouseup', (event) => { state = 0; // 恢复默认状态 // 鼠标抬起时候,和按下的坐标作比对,用来判断是向左滑动还是向右滑动 // 向左滑动那么就是要显示下一个滑块,所以index要加1 if (event.pageX < startEvent.pageX) { index ++; } else { index --; } // 防止滑块越界 // 如果当前滑块是第一个,向右滑动后,回到第一个滑块 // 如果是最后一个,向左滑动后,回到最后一个滑块 if (index < 0) { index = 0; } else if (index > itemEls.length - 1) { index = itemEls.length - 1; } // 追加一个move样式 containerEl.className += ' move'; // 当过度动画结束后,一定要把这个类给移除掉 containerEl.addEventListener('transitionend', () => { // 正则替换 \s+ 表示一个或多个空白字符 containerEl.className = containerEl.className.replace(/\s+move/, ''); }) left = 0 - itemWidth * index; containerEl.style.left = left + 'px'; console.log('鼠标抬起了'); }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 防止越界 我们扩展出的三个问题,基本上都解决了。 而且到目前为止,其实你已经实现了一个基本的滑块功能了,只不过略显粗糙! 2.2 自动播放的原理 回到我们的功能列表,我们来看下第四条“自动播放”,第一个想到的是setInterval setInterval(() => { // 这个回调会每隔2秒执行一次 }, 2000); 1 2 3 所以,我们只需要在这个回调函数里边写上让滑块滑动的代码不就行了? 我们是用index变量来控制当前滑块的,那么每隔2秒让index加1,最后再根据index计算出left的值,不就可以了? setInterval(() => { // 默认向左滑动 index ++; // 如果滑动到最后一个滑块,则回到第一个滑块 if (index > itemEls.length - 1) { index = 0; } // 下面的代码跟我们鼠标抬起的事件的代码一样的,要不要考虑简单的封装一下? // 追加一个move样式 containerEl.className += ' move'; // 当过度动画结束后,一定要把这个类给移除掉 containerEl.addEventListener('transitionend', () => { // 正则替换 \s+ 表示一个或多个空白字符 containerEl.className = containerEl.className.replace(/\s+move/, ''); }) left = 0 - itemWidth * index; containerEl.style.left = left + 'px'; }, 2000); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 自动播放 关于重复逻辑的问题,我们会在第二部分写插件时候进行封装,这部分,我们只讲原理,当然如果你是个强迫症患者,可以自己试着封装个函数。 不过他老是这么自动播放也不是个事,有时候我想看看内容,还没看完呢,就自动划走了,所以,我们可以当鼠标放在容器上的时候,停止播放,鼠标移开后又恢复自动播放 mouseover 鼠标移动到某个元素上 mouseout 鼠标在某个元素上移开 我们还是在容器上监听这两个事件,并用一个状态autoplay来控制播放: // 自动播放状态 let autoplay = true; setInterval(() => { if (!autoplay) return; // 默认向左滑动 index ++; // 如果滑动到最后一个滑块,则回到第一个滑块 if (index > itemEls.length - 1) { index = 0; } // 追加一个move样式 containerEl.className += ' move'; // 当过度动画结束后,一定要把这个类给移除掉 containerEl.addEventListener('transitionend', () => { // 正则替换 \s+ 表示一个或多个空白字符 containerEl.className = containerEl.className.replace(/\s+move/, ''); }) left = 0 - itemWidth * index; containerEl.style.left = left + 'px'; }, 2000); containerEl.addEventListener('mouseover', () => { // 鼠标移动到容器上,停止播放 autoplay = false; }); containerEl.addEventListener('mouseout', () => { // 鼠标从容器上移开,恢复播放 autoplay = true; }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 鼠标控制自动播放 当然,还有其他的方法来控制自动播放,比如用clearInterval函数等。 3. 结尾 至此,我们的原理都讲的差不多了,有遗漏的地方,还望指出,那么在第二部分,我会和大家一块来把写的杂七杂八的代码做一个封装,让我们的代码插件化,适应更多的场景。 ———————————————— 版权声明:本文为CSDN博主「卧龙派」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/zfzhuman123/article/details/90520355
本帖子属于以下条目()
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.