如何在iPad端用asScrollbar实现带滚动条的textarea正常显示
asScrollbar 内 textarea 文本显示异常修复
问题根因
asScrollbar 初始化绑定容器时,会自动给容器添加CSS 3D变换属性、劫持容器内的滚动事件,直接将textarea放在绑定容器内会触发两个问题:
- 容器的3D变换属性会干扰浏览器对textarea内部文本的渲染,出现文字错位、显示不全、渲染空白
- 库的滚动逻辑和textarea原生滚动逻辑冲突,自定义滚动条无法控制textarea滚动,textarea原生滚动也会失效
修复步骤
- 关闭asScrollbar的
useCssTransforms3d配置,避免3D变换触发textarea渲染bug - 隐藏textarea原生滚动条,避免出现双滚动条
- 给asScrollbar和textarea做滚动双向绑定:拖动自定义滚动条时同步textarea滚动位置,手动滚动textarea时同步自定义滚动条位置
- 给textarea加一层和自身同高度的父容器,避免asScrollbar直接计算textarea的内容高度出错
完整修改后代码
<!doctype html> <html class="no-js"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>jQuery asScrollbar</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="css/normalize.css"> <link rel="stylesheet" href="css/main.css"> <link rel="stylesheet" href="css/asScrollbar.css"> <style type="text/css"> body { background-color: #f7f7f7; } .section { padding: 20px; } .inner { margin: 0 auto; max-width: 960px; } .example { position: relative; overflow: hidden; padding: 10px; border: 1px solid #e0e0e0; -webkit-box-shadow: 1px 1px 2px 0px rgba(200, 200, 200, 0.3); -moz-box-shadow: 1px 1px 2px 0px rgba(200, 200, 200, 0.3); box-shadow: 1px 1px 2px 0px rgba(200, 200, 200, 0.3); background-color: #fefefe; } /* textarea容器高度和textarea保持一致 */ .textarea-wrap { height: 280px; } /* textarea样式,隐藏原生滚动条 */ .demo-textarea { width: 100%; height: 280px; border-radius: 25px; padding: 15px; box-sizing: border-box; resize: none; border: 1px solid #ccc; /* 兼容多浏览器隐藏原生滚动条 */ scrollbar-width: none; -ms-overflow-style: none; } .demo-textarea::-webkit-scrollbar { display: none; } </style> </head> <body> <!--[if lt IE 8]> <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p> <![endif]--> <div class="section"> <div class="inner"> <section> <h3>Horizontal scrollbar</h3> <div class="example" style="height: 50px"> <div class="example-scrollbar-horizontal" data-options='{"easing": "ease"}'> </div> </div> <div class="example" style="height: 50px"> <div class="example-scrollbar-horizontal" data-options='{"easing": "ease-in"}'> </div> </div> <div class="example" style="height: 50px"> <div class="example-scrollbar-horizontal" data-options='{"easing": "ease-out"}'> </div> </div> <div class="example" style="height: 50px"> <div class="example-scrollbar-horizontal" data-options='{"easing": "ease-in-out"}'> </div> </div> </section> <section> <h3>Vertical scrollbar</h3> <div class="example" style="height: 300px"> <div class="example-scrollbar-vertical"> <div class="textarea-wrap"> <textarea class="demo-textarea">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 测试行1:用来验证长文本滚动效果 测试行2:用来验证长文本滚动效果 测试行3:用来验证长文本滚动效果 测试行4:用来验证长文本滚动效果 测试行5:用来验证长文本滚动效果 测试行6:用来验证长文本滚动效果 测试行7:用来验证长文本滚动效果 测试行8:用来验证长文本滚动效果 测试行9:用来验证长文本滚动效果 测试行10:用来验证长文本滚动效果 测试行11:用来验证长文本滚动效果 测试行12:用来验证长文本滚动效果 测试行13:用来验证长文本滚动效果 测试行14:用来验证长文本滚动效果 测试行15:用来验证长文本滚动效果 </textarea> </div> </div> </div> </section> <section> <div> <button class="api-move-to" data-to="0">Move to 0</button> <button class="api-move-to" data-to="50">Move to 50</button> <button class="api-move-to" data-to="0%">Move to 0%</button> <button class="api-move-to" data-to="100%">Move to 100%</button> <button class="api-move-to" data-to="50%">Move to 50%</button> </div> <div> <button class="api-move-by" data-by="20">Move by 20</button> <button class="api-move-by" data-by="+20">Move by +20</button> <button class="api-move-by" data-by="-20">Move by -20</button> <button class="api-move-by" data-by="20%">Move by 20%</button> <button class="api-move-by" data-by="+20%">Move by +20%</button> <button class="api-move-by" data-by="-20%">Move by -20%</button> </div> </section> </div> </div> <script src="js/jquery.js"></script> <script src="js/jquery.mousewheel.js"></script> <script src="js/jquery-asScrollbar.js"></script> <script type="text/javascript"> jQuery(function() { $('.example-scrollbar-horizontal').asScrollbar({ direction: 'horizontal', minHandleLength: 200, handleLength: 100 }); // 垂直滚动条初始化,关闭3d变换 const $verticalScroll = $('.example-scrollbar-vertical').asScrollbar({ direction: 'vertical', handleLength: 100, maxHandleLength: 100, mouseDrag: true, touchDrag: true, pointerDrag: true, clickMove: true, clickMoveStep: 0.2, mousewheel: true, mousewheelSpeed: 50, keyboard: true, useCssTransforms3d: false, // 核心修改:关闭3D变换避免textarea渲染异常 useCssTransforms: true, useCssTransitions: true, duration: '300', easing: 'ease' }); const scrollApi = $verticalScroll.data('asScrollbar'); const $textarea = $('.demo-textarea'); // 自定义滚动条滚动时同步textarea位置 $verticalScroll.on('asScrollbar::scroll', function(e, percent) { const maxTextScroll = $textarea[0].scrollHeight - $textarea.innerHeight(); $textarea.scrollTop(percent * maxTextScroll); }); // textarea滚动时同步自定义滚动条位置 $textarea.on('scroll', function() { const maxTextScroll = this.scrollHeight - this.clientHeight; const currentPercent = maxTextScroll === 0 ? 0 : this.scrollTop / maxTextScroll; scrollApi.moveTo(currentPercent * 100 + '%', false); // 第二个参数false阻止触发事件循环 }); $('.api-move-to').on('click', function() { const to = $(this).data('to'); $('.example-scrollbar-horizontal, .example-scrollbar-vertical').asScrollbar('moveTo', to); }); $('.api-move-by').on('click', function() { const to = $(this).data('by'); $('.example-scrollbar-horizontal, .example-scrollbar-vertical').asScrollbar('moveBy', to); }); }); </script> </body> </html>
效果说明
修改后textarea文本可以正常渲染无错位,自定义滚动条和textarea滚动完全同步,鼠标滚轮、拖动滚动条、API调用都可以正常控制滚动,不会出现双滚动条问题。
内容的提问来源于stack exchange,提问作者Neo
相关产品推荐
相关产品推荐

