在回答another question on StackOverflow时,我发布了一个简单的演示,展示了如何实现相对于光标在其父<div>
内移动的子<div>
的移动,通过操纵element.scrollTop
和element.scrollLeft
。
我的演示基本上按预期工作,演示了通过mousemove
和event.pageX
在event.pageY
上收集光标坐标的基础知识,做了一些数学运算来计算较大的{{应移动{1}}孩子并应用.inner
。
然而,我注意到当我将光标移动到scroll*
父级的底部和/或右侧时,.outer
子项将向前滚动到最大值我的光标到达边缘。
我做了什么来寻找解决方案?
认识到.inner
始终至少event.pageX
且永远不会超过1
1
且width
永远不会超过event.pageY
}} {}}} {}} {} {}} 。
尽管该功能起到了作用,但它并没有治愈过早的最大值1
。
编辑:我没有在SO片段之外测试此代码,这些代码似乎以不同的方式显示HTML,具体取决于是否正在编辑,正常查看或扩展;有时函数是必需,有时它的存在会产生负值。
<div>
没有回应负值;相反,它将自己设置回height
。如果设置为大于元素可用最大值的值,
0
将自己设置为最大值。
width
也是如此
所以这种不一致是不相关的;在添加函数之前,问题很明显。
还有什么?
我一再检查数学,例如
height
的父scroll*
scrollTop
0
scrollTop
测量scrollLeft
的孩子<div>
(两轴上父母的3倍)100px
100px
应设为<div>
= 300px
300px
应设置为{ x: 90, y: 90 }
= scrollTop
90 * 3
的底边或右边应不与父母的边缘对齐。考虑到这一点,正如我所说,我已经检查并再次检查,数学应该有效,但结果是出乎意料的。
这是代码,有一些额外的位输出270
中的一些数字(否则控制台会有所不同),我的问题将继续下去。额外的scrollLeft
用户界面不会影响结果。
90 * 3
270
<div>
正如您所看到的,在光标到达父级的右边和/或底边之前很久,孩子innerHTML
的右边和右边就会进入视图。
为什么会这样,以及如何在动态应用中修复它?
通过“动态应用程序”我的意思是没有根据具体情况对解决方案进行硬编码。
注意:虽然(我知道)此代码可以通过多种方式优化,但它纯粹用于演示,因此,优化不会影响修复具体问题没有意义。
答案 0 :(得分:0)
scrollTop
和scrollLeft
衡量在各自轴上滚动的像素数量。
这相当于滚动超出视野的数量,因此总会有剩余的数量无法滚动。
此金额等于父母的相应度量。
<div>
的大小是父级的两倍,那么当在任一轴上滚动到最大值时,只会滚动一半。10
倍大小:9/10ths
滚动等。 在此特定应用程序中,光标坐标应乘以以下计算的尺寸比率:
( width of the child minus the width of the parent ) divided by the width of the parent
和
( height of the child minus the height of the parent ) divided by the height of the parent
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 ) / outer_div_width, // fixed
y: ( parseInt( inner_div_styles.height ) - outer_div_height ) / outer_div_height // fixed
},
half_odw = outer_div_width / 2,
half_odh = outer_div_height / 2,
expandCoords = function( e ) {
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 };
};
outer_div.addEventListener( "mousemove", function( evt ) {
evt = expandCoords( evt );
outer_div.scrollLeft = evt.x * dimention_ratio.x;
outer_div.scrollTop = evt.y * dimention_ratio.y;
}, false );
&#13;
body {
overflow: hidden;
margin: 0;
}
.outer {
width: 100vw;
height: 100vh;
overflow: hidden;
}
.inner {
width: 1234vw; /* 12.34 times the width of its parent */
height: 567vh; /* 5.67 times the height of its parent */
box-shadow: inset 0 0 20px 20px green; /* no border edge highlight */
background: radial-gradient( white, black );
}
&#13;
<div class="outer"><div class="inner"></div></div>
&#13;