javascript - 在 div 上复制输入滚动
问题描述
我正在尝试在 div 元素上复制输入水平滚动,因此每当用户沿输入移动时,div 元素的滚动与输入完全相同。
我的问题在于 Chrome,因为输入似乎具有不同的滚动行为,导致两个元素中的 scrollLeft 值不同。在 Firefox 中,它按预期工作。
有没有办法在不使用 jQuery 或其他库的情况下在 Chrome 中实现这一点?还是我在问不可能?
var theTextDiv = document.getElementById("the-text");
var theText = document.getElementById("the-text-input");
function keepScroll(txt) {
theTextDiv.scrollLeft = theText.scrollLeft;
}
theText.addEventListener("blur", function() { keepScroll("blur"); });
theText.addEventListener("change", function() { keepScroll("change"); });
theText.addEventListener("focus", function() { keepScroll("focus"); });
theText.addEventListener("input", function() { keepScroll("input"); });
theText.addEventListener("keydown", function() { keepScroll("keydown"); });
theText.addEventListener("keyup", function() { keepScroll("keyup"); });
theText.addEventListener("scroll", function() { keepScroll("scroll"); });
theText.addEventListener("select", function() { keepScroll("select"); });
#the-text {
border: 1px solid red;
max-width: 98px;
font-size: 14px;
overflow-x: scroll;
word-wrap: break-word;
white-space: nowrap;
font-family: "Times New Roman", Times, serif;
padding: 1px;
margin-right: 10px;
}
#the-text-input {
border: 1px solid red;
width: 100px;
font-size: 14px;
font-family: "Times New Roman", Times, serif;
}
<div id="the-text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
<input type="text" id="the-text-input" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." />
编辑:
我在 Mac 上的 Chrome 77 上尝试了上面的代码,它按预期工作,两个元素之间没有差距,我开始认为这是 Windows 问题而不是 Chrome 问题
编辑(2):
重新启动我的电脑后,所有工作都按预期(严重)可能是某些 chrome 缓存导致出现奇怪的行为
解决方案
input
这可能与和/或上的填充和边框有关div
,并且看起来它在 Chrome 77 中运行良好,您要么忘记在发布的示例中添加一些代码,要么这些元素的默认样式也在播放这里的一个角色。
在任何情况下,我的建议是从两个元素中删除边距、填充和边框,并div
用它们添加一个包装(红色示例)。
您也可以使用box-sizing: border-box
,保留这些样式并避免使用包装器,但padding
在 中的行为不同input
,因为填充区域中的内容不可见(蓝色示例)。
最后,您更新滚动的代码在模糊上无法正常工作,因为当事件触发输入时滚动尚未重置为 0。包装它setTimeout
或window.requestAnimationFrame
解决问题。此外,后者还将使更新更加流畅和同步。
const text = document.getElementById('text');
const input = document.getElementById('input');
function updateScroll() {
// Scroll not updated on blur without requestAnimationFrame
// or setTimeout:
requestAnimationFrame(() => text.scrollLeft = input.scrollLeft);
}
input.addEventListener('blur', updateScroll);
input.addEventListener('change', updateScroll);
input.addEventListener('focus', updateScroll);
input.addEventListener('input', updateScroll);
input.addEventListener('keydown', updateScroll);
input.addEventListener('keyup', updateScroll);
input.addEventListener('scroll', updateScroll);
input.addEventListener('select', updateScroll);
const textAlternative = document.getElementById('text-alternative');
const inputAlternative = document.getElementById('input-alternative');
function updateScrollAlternative() {
// Scroll not updated on blur without requestAnimationFrame
// or setTimeout:
requestAnimationFrame(() => textAlternative.scrollLeft = inputAlternative.scrollLeft);
}
inputAlternative.addEventListener('blur', updateScrollAlternative);
inputAlternative.addEventListener('change', updateScrollAlternative);
inputAlternative.addEventListener('focus', updateScrollAlternative);
inputAlternative.addEventListener('input', updateScrollAlternative);
inputAlternative.addEventListener('keydown', updateScrollAlternative);
inputAlternative.addEventListener('keyup', updateScrollAlternative);
inputAlternative.addEventListener('scroll', updateScrollAlternative);
inputAlternative.addEventListener('select', updateScrollAlternative);
body {
margin: 0;
}
.box {
position: relative;
display: block;
width: 50%;
box-sizing: border-box;
/* Moved styles here: */
border: 3px solid red;
padding: 8px;
margin: 8px auto 0;
}
#text,
#input,
#text-alternative,
#input-alternative {
display: block;
width: 100%;
font-size: 14px;
font-family: monospace;
outline: none;
}
#text,
#input {
/* Removed margin, padding and borders: */
border: 0;
padding: 0;
margin: 0;
}
#text-alternative,
#input-alternative {
width: 50%;
box-sizing: border-box;
/* Keep styles here thanks to box-sizing, but behaves differently: */
border: 3px solid blue;
padding: 8px;
margin: 8px auto 0;
}
#text,
#text-alternative {
word-wrap: break-word;
white-space: nowrap;
/* No need to keep it visible unless you want to scroll manually too: */
overflow-x: hidden;
}
<div class="box">
<div id="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<label class="box">
<input id="input" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." />
</label>
<div id="text-alternative">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
<input id="input-alternative" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." />
推荐阅读
- java - 无法在 Android WebView 中设置 HttpURLConnection 标头
- python - “NoSuchWindowException:没有这样的窗口:窗口已经关闭”,同时通过 Python3 使用 Selenium 和 WebDriver 切换选项卡
- excel - 使用 VBA 函数检查列是否存在 NA 错误并创建 IF-Then Else 输出
- python - 直接将python字符串转换为字节而不使用eval()
- python - 如何从 Python 中的 AppleScript 获取返回值?
- hyperledger-fabric - 由于缺少 escc,Fabric v1.2.0 的链码实例化失败
- reactjs - 为什么子组件在 React Native 中没有从父组件接收更新值?
- vbscript - UFT/QTP 动态网址
- python - Python中数字的质因数
- ansible - 如何在 Jinja/Ansible 中生成 dict 作为 var?