【发布时间】:2017-07-01 19:52:21
【问题描述】:
在回答another question on StackOverflow 时,我发布了一个应该是简单的演示,展示了如何通过@987654322 的操作实现子<div> 相对于其父<div> 中光标的移动的移动@ 和element.scrollLeft。
我的演示基本上按预期工作,演示了通过event.pageX 和event.pageY 收集mousemove 上的光标坐标的基础知识,做一些数学运算来计算应该移动较大的.inner 孩子的比率,并应用scroll*。
然而,我注意到当我将光标移动到.outer 父级的底部和/或右侧时,.inner 子级将在我的光标到达之前滚动到最大值边缘。
我为找到解决方案做了什么?
意识到event.pageX 总是至少是1 并且永远不会超过1 小于width 并且event.pageY 永远不会超过1 小于父<div> 的@987654345 @,我添加了一个基本函数来将坐标范围从 0 扩展到完整的 width 和/或 height。
尽管该函数完成了它的工作,但它并没有治愈过早的最大值scroll*。
编辑:我没有在 SO sn-ps 之外测试过这段代码,根据它是被编辑、正常查看还是扩展,它似乎以不同的方式呈现 HTML;有时该函数是必需的,有时它的存在会导致负值。
scrollTop不响应负值;相反,它将自己设置回0。如果设置的值大于元素可用的最大值,
scrollTop会将自身设置为最大值。
scrollLeft 也是如此。
所以这种不一致是不相关的;在我添加功能之前问题很明显。
还有什么?
我反复检查了数学,例如
- 假设我们有一个父母
<div>测量100px由100px - 还有一个孩子
<div>以300px测量300px(两个轴上都是父级的3 倍) - 如果光标在坐标上。
{ x: 90, y: 90 } -
scrollTop应设置为90 * 3=270 - 并且
scrollLeft应该设置为90 * 3=270 - 因此,子
<div>的底部或右侧边缘应该不与父级对齐。
考虑到这一点,正如我所说,我检查了又检查了一遍,数学应该工作,但结果出乎意料。
这是代码,有一些额外的位会输出innerHTML 中的一些数字(否则控制台会有点碍事),我的问题将在它下面继续。额外的<output> UI 不会影响结果。
const divs = document.querySelectorAll( "div" ),
outer_div = divs[ 0 ],
outer_div_styles = window.getComputedStyle( outer_div ),
inner_div_styles = window.getComputedStyle( divs[ 1 ] ),
outer_div_width = parseInt( outer_div_styles.width ),
outer_div_height = parseInt( outer_div_styles.height ),
dimention_ratio = {
x: parseInt( inner_div_styles.width ) / outer_div_width,
y: parseInt( inner_div_styles.height ) / outer_div_height
},
half_odw = outer_div_width / 2,
half_odh = outer_div_height / 2,
expandCoords = function( e ) { // sometimes useful, never harmful
var X = e.pageX,
Y = e.pageY;
if ( X < half_odw ) {
X -= 1;
} else if ( X > half_odw ) {
X += 1;
}
if ( Y < half_odh ) {
Y -= 1;
} else if ( Y > half_odh ) {
Y += 1;
}
return { x: X, y: Y };
},
// for demo convenience
output = document.querySelector( "output" );
outer_div.addEventListener( "mousemove", function( evt ) {
evt = expandCoords( evt );
// for demo convenience
output.innerHTML = "Coords: x:" + evt.x + ", y:" + evt.y + "<br>" +
"scrollLeft = " + ( evt.x * dimention_ratio.x ) + "<br>" +
"scrollTop = " + ( evt.y * dimention_ratio.y );
outer_div.scrollLeft = evt.x * dimention_ratio.x;
outer_div.scrollTop = evt.y * dimention_ratio.y;
}, false );
body {
overflow: hidden;
margin: 0;
}
.outer {
width: 100vw;
height: 100vh;
overflow: hidden;
}
.inner {
width: 1000vw; /* 10 times the width of its parent */
height: 500vh; /* 5 times the height of its parent */
box-shadow: inset 0 0 20px 20px green; /* no border edge highlight */
background: radial-gradient( white, black );
}
/* for demo convenience */
output {
position: absolute;
top: 10vh;
left: 10vw;
font-family: Consolas, monospace;
background: white;
padding: .2em .4em .3em;
cursor: default;
}
<div class="outer"><div class="inner"></div><output></output></div>
如您所见,子 <div> 的右边缘和下边缘早在光标到达父对象的右边缘和/或下边缘之前就已经出现了。
为什么会这样,如何在动态应用程序中修复它?
“动态应用程序”我的意思是不根据具体情况对解决方案进行硬编码。
注意:虽然(我知道)这段代码可以在很多方面进行优化,但它纯粹是为了演示,因此不会影响修复的优化具体问题不感兴趣。
【问题讨论】:
标签: javascript html math coordinates mousemove