Javascript 通过scrollOffset查找最近的锚点href
我有一个Javascript 通过scrollOffset查找最近的锚点href,javascript,uiwebview,anchor,Javascript,Uiwebview,Anchor,我有一个UIWebView,其中一个HTML页面已完全加载。UIWebView的框架为320 x 480,可水平滚动。我可以得到用户当前的偏移量。我希望使用XY偏移找到最近的锚点,以便我可以“跳到”该锚点位置。这有可能吗?有人能给我指一下Javascript中的资源吗 <a id="p-1">Text Text Text Text Text Text Text Text Text<a id="p-2">Text Text Text Text Text Text Text
UIWebView
,其中一个HTML页面已完全加载。UIWebView
的框架为320 x 480,可水平滚动。我可以得到用户当前的偏移量。我希望使用XY偏移找到最近的锚点,以便我可以“跳到”该锚点位置。这有可能吗?有人能给我指一下Javascript中的资源吗
<a id="p-1">Text Text Text Text Text Text Text Text Text<a id="p-2">Text Text Text Text Text Text Text Text Text ...
我找到了一种不使用scrollOffset的方法。这有点复杂,所以如果你有任何问题要理解的话,就评论一下 HTML:
<body>
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<a />Text Text Text Text Text Text Text Text Text
<br /><br /><br /><br /><br />
<a />Text Text Text Text Text Text Text Text Text
</body>
JS:
var-tempY;
函数getClosestAnchor(e)
{
if((window.event?event.keyCode:e.which)!=97)返回;
var allAnchors=document.getElementsByTagName(“a”);
var-allDiff=[];
对于(var a=0;a
奖励:您不必为所有锚定指定id。呸!我完成了
JS:
var x=0,y=0;//这里是给定的x和y,您可以更改它们
var Id最近;//最近的锚点的Id
var smallestIndex;
var-couplesXY=[];
阿兰霍斯变种;
var html=document.getElementsByTagName(“html”)[0];
html.style.width=“3000px”//您可以更改3000,这是为了使水平滚动成为可能
html.style.height=“3000px”;//这里也是
随机函数(最小值、最大值)
{
var nb=min+(max+1-min)*数学随机();
返回数学楼层(nb);
}
function left(obj)//此站点的重新混合函数http://www.quirksmode.org/js/findpos.html
{
if(obj.style.position==“绝对”)返回parseInt(obj.style.left);
var-posX=0;
如果(!obj.offsetParent)返回;
do posX+=obj.offsetLeft;
而(对象=对象抵销母公司);
返回posX;
}
功能顶部(obj)
{
if(obj.style.position==“绝对”)返回parseInt(obj.style.top);
var-posY=0;
如果(!obj.offsetParent)返回;
do posY+=obj.offsetTop;
而(对象=对象抵销母公司);
返回posY;
}
function generateRandomAnchors()//仅举一个例子,如果已经有了锚,则可以删除该函数
{
对于(var a=0;a[UPDATE]我重写了代码,以匹配所有具有id的锚,并简化了我的sortByDistance
函数中向量范数的比较
检查我的尝试(上一次是)
javascript部分:
// findPos : courtesy of @ppk - see http://www.quirksmode.org/js/findpos.html
var findPos = function(obj) {
var curleft = 0,
curtop = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft;
curtop = obj.offsetTop;
while ((obj = obj.offsetParent)) {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
}
}
return [curleft, curtop];
};
var findClosestAnchor = function (anchors) {
var sortByDistance = function(element1, element2) {
var pos1 = findPos( element1 ),
pos2 = findPos( element2 );
// vect1 & vect2 represent 2d vectors going from the top left extremity of each element to the point positionned at the scrolled offset of the window
var vect1 = [
window.scrollX - pos1[0],
window.scrollY - pos1[1]
],
vect2 = [
window.scrollX - pos2[0],
window.scrollY - pos2[1]
];
// we compare the length of the vectors using only the sum of their components squared
// no need to find the magnitude of each (this was inspired by Mageek’s answer)
var sqDist1 = vect1[0] * vect1[0] + vect1[1] * vect1[1],
sqDist2 = vect2[0] * vect2[0] + vect2[1] * vect2[1];
if ( sqDist1 < sqDist2 ) return -1;
else if ( sqDist1 > sqDist2 ) return 1;
else return 0;
};
// Convert the nodelist to an array, then returns the first item of the elements sorted by distance
return Array.prototype.slice.call( anchors ).sort( sortByDistance )[0];
};
这个答案没有得到足够的重视。
完整的样本,快速(二进制搜索)与缓存的立场
固定的高度和宽度,最近的锚点和滚动到的id
<!DOCTYPE html>
<html lang="en">
<head>
<meta>
<title>Offset 2</title>
<style>
body { font-family:helvetica,arial; font-size:12px; }
</style>
<script>
var ui = reqX = reqY = null, etop = eleft = 0, ref, cache;
function createAnchors()
{
if (!ui)
{
ui = document.getElementById('UIWebView');
reqX = document.getElementById('reqX');
reqY = document.getElementById('reqY');
var h=[], i=0;
while (i < 1000)
h.push('<a>fake anchor ... ',i,'</a> <a href=#>text for anchor <b>',(i++),'</b></a> ');
ui.innerHTML = '<div style="padding:10px;width:700px">' + h.join('') + '</div>';
cache = [];
ref = Array.prototype.slice.call(ui.getElementsByTagName('a'));
i = ref.length;
while (--i >= 0)
if (ref[i].href.length == 0)
ref.splice(i,1);
}
}
function pos(i)
{
if (!cache[i])
{
etop = eleft = 0;
var e=ref[i];
if (e.offsetParent)
{
do
{
etop += e.offsetTop;
eleft += e.offsetLeft;
} while ((e = e.offsetParent) && e != ui)
}
cache[i] = [etop, eleft];
}
else
{
etop = cache[i][0];
eleft = cache[i][1];
}
}
function find()
{
createAnchors();
if (!/^\d+$/.test(reqX.value))
{
alert ('I need a number for X');
return;
}
if (!/^\d+$/.test(reqY.value))
{
alert ('I need a number for Y');
return;
}
var
x = reqX.value,
y = reqY.value,
low = 0,
hi = ref.length + 1,
med,
limit = (ui.scrollHeight > ui.offsetHeight) ? ui.scrollHeight - ui.offsetHeight : ui.offsetHeight - ui.scrollHeight;
if (y > limit)
y = limit;
if (x > ui.scrollWidth)
x = (ui.scrollWidth > ui.offsetWidth) ? ui.scrollWidth : ui.offsetWidth;
while (low < hi)
{
med = (low + ((hi - low) >> 1));
pos(med);
if (etop == y)
{
low = med;
break;
}
if (etop < y)
low = med + 1;
else
hi = med - 1;
}
var ctop = etop;
if (eleft != x)
{
if (eleft > x)
while (low > 0)
{
pos(--low);
if (etop < ctop || eleft < x)
{
pos(++low);
break;
}
}
else
{
hi = ref.length;
while (low < hi)
{
pos(++low);
if (etop > ctop || eleft > x)
{
pos(--low);
break;
}
}
}
}
ui.scrollTop = etop - ui.offsetTop;
ui.scrollLeft = eleft - ui.offsetLeft;
ref[low].style.backgroundColor = '#ff0';
alert(
'Requested position: ' + x + ', ' + y +
'\nScrollTo position: ' + ui.scrollLeft + ', '+ ui.scrollTop +
'\nClosest anchor id: ' + low
);
}
</script>
</head>
<body>
<div id=UIWebView style="width:320px;height:480px;overflow:auto;border:solid 1px #000"></div>
<label for="req">X: <input id=reqX type=text size=5 maxlength=5 value=200></label>
<label for="req">Y: <input id=reqY type=text size=5 maxlength=5 value=300></label>
<input type=button value="Find closest anchor" onclick="find()">
</body>
</html>
偏移量2
正文{字体系列:helvetica,arial;字体大小:12px;}
var ui=reqX=reqY=null,etop=eleft=0,ref,cache;
函数createAnchors()
{
如果(!ui)
{
ui=document.getElementById('UIWebView');
reqX=document.getElementById('reqX');
reqY=document.getElementById('reqY');
var h=[],i=0;
而(i<1000)
h、 推动(“”);
ui.innerHTML=''+h.join('')+'';
缓存=[];
ref=Array.prototype.slice.call(ui.getElementsByTagName('a');
i=参考长度;
而(--i>=0)
if(ref[i].href.length==0)
参考拼接(i,1);
}
}
功能pos(一)
{
如果(!缓存[i])
{
etop=eleft=0;
var e=参考[i];
if(如抵销母公司)
{
做
{
etop+=e.offsetTop;
eleft+=e.offsetLeft;
}while((e=e.offsetParent)和&e!=ui)
}
cache[i]=[etop,eleft];
}
其他的
{
etop=cache[i][0];
eleft=cache[i][1];
}
}
函数find()
{
createAnchors();
如果(!/^\d+$/.测试(需求值))
{
警报(“我需要一个X的数字”);
返回;
}
如果(!/^\d+$/.测试(需求值))
{
警报(“我需要Y的数字”);
返回;
}
变量
x=需求x.值,
y=需求值,
低=0,
hi=参考长度+1,
医学,
限制=(ui.scrollHeight>ui.offsetHeight)?ui.scrollHeight-ui.offsetHeight:ui.offsetHeight-ui.scrollHeight;
如果(y>限制)
y=极限;
如果(x>ui.scrollWidth)
x=(ui.scrollWidth>ui.offsetWidth)?ui.scrollWidth:ui.offsetWidth;
while(低<高)
{
med=(低+((高-低)>>1));
pos(医学);
如果(etop==y)
{
低=中等;
打破
}
if(etopx)
而(低>0)
{
pos(--低);
if(etopctop | | eleft>x)
{
pos(--低);
打破
}
}
}
}
ui.scrollTop=etop-ui.offsetTop;
ui.scrollLeft=eleft-ui.offsetLeft;
ref[low].style.backgroundColor='#ff0';
警觉的(
'请求的位置:'+x+','+y+
'\n滚动到位置:'+ui.scrollLeft+','+ui.scrollTop+
“\n终止锚id:”+低
);
}
X:
Y:
您绝对想要通过scrollOffset吗?您想要从锚点左上角或从中心或其他位置最近的锚点吗?给定当前XY偏移量,我想要从文档左上角最近的锚点。Danny Boy,您没有太多评论,您尝试过我们的建议吗?这个问题有问题…我感到有点震惊的是,你甚至没有找到投票最多的答案。我无法在iOS应用程序中使用任何答案。我已经无数次尝试并修改了下面的每个解决方案。我正在尝试
body
{
height:3000px;
}
var tempY;
function getClosestAnchor(e)
{
if((window.event?event.keyCode:e.which)!=97)return;
var allAnchors=document.getElementsByTagName("a");
var allDiff=[];
for(var a=0;a<allAnchors.length;a++)allDiff[a]=margeY(allAnchors[a])-tempY;
var smallest=allDiff[0];
for(var a=1;a<allDiff.length;a++)
{
if(Math.abs(smallest)>Math.abs(allDiff[a]))
{
smallest=allDiff[a];
}
}
window.scrollBy(0,smallest);
}
function margeY(obj)
{
var posY=0;
if(!obj.offsetParent)return;
do posY+=obj.offsetTop;
while(obj=obj.offsetParent);
return posY;
}
function update(e)
{
if(e.pageY)tempY=e.pageY;
else tempY=e.clientY+(document.documentElement.scrollTop||document.body.scrollTop)-document.documentElement.clientTop;
}
window.onkeypress=getClosestAnchor;
window.onmousemove=update;
var x=0,y=0;//Here are the given X and Y, you can change them
var idClosest;//Id of the nearest anchor
var smallestIndex;
var couplesXY=[];
var allAnchors;
var html=document.getElementsByTagName("html")[0];
html.style.width="3000px";//You can change 3000, it's to make the possibility of horizontal scroll
html.style.height="3000px";//Here too
function random(min,max)
{
var nb=min+(max+1-min)*Math.random();
return Math.floor(nb);
}
function left(obj)//A remixed function of this site http://www.quirksmode.org/js/findpos.html
{
if(obj.style.position=="absolute")return parseInt(obj.style.left);
var posX=0;
if(!obj.offsetParent)return;
do posX+=obj.offsetLeft;
while(obj=obj.offsetParent);
return posX;
}
function top(obj)
{
if(obj.style.position=="absolute")return parseInt(obj.style.top);
var posY=0;
if(!obj.offsetParent)return;
do posY+=obj.offsetTop;
while(obj=obj.offsetParent);
return posY;
}
function generateRandomAnchors()//Just for the exemple, you can delete the function if you have already anchors
{
for(var a=0;a<50;a++)//You can change 50
{
var anchor=document.createElement("a");
anchor.style.position="absolute";
anchor.style.width=random(0,100)+"px";//You can change 100
anchor.style.height=random(0,100)+"px";//You can change 100
anchor.style.left=random(0,3000-parseInt(anchor.style.width))+"px";//If you changed 3000 from
anchor.style.top=random(0,3000-parseInt(anchor.style.height))+"px";//the top, change it here
anchor.style.backgroundColor="black";
anchor.id="Anchor"+a;
document.body.appendChild(anchor);
}
}
function getAllAnchors()
{
allAnchors=document.getElementsByTagName("a");
for(var a=0;a<allAnchors.length;a++)
{
couplesXY[a]=[];
couplesXY[a][0]=left(allAnchors[a]);
couplesXY[a][1]=top(allAnchors[a]);
}
}
function findClosestAnchor()
{
var distances=[];
for(var a=0;a<couplesXY.length;a++)distances.push(Math.pow((x-couplesXY[a][0]),2)+Math.pow((y-couplesXY[a][1]),2));//Math formula to get the distance from A to B (http://euler.ac-versailles.fr/baseeuler/lexique/notion.jsp?id=122). I removed the square root not to slow down the calculations
var smallest=distances[0];
smallestIndex=0;
for(var a=1;a<distances.length;a++)if(smallest>distances[a])
{
smallest=distances[a];
smallestIndex=a;
}
idClosest=allAnchors[smallestIndex].id;
alert(idClosest);
}
function jumpToIt()
{
window.scrollTo(couplesXY[smallestIndex][0],couplesXY[smallestIndex][1]);
allAnchors[smallestIndex].style.backgroundColor="red";//Color it to see it
}
generateRandomAnchors();
getAllAnchors();
findClosestAnchor();
jumpToIt();
// findPos : courtesy of @ppk - see http://www.quirksmode.org/js/findpos.html
var findPos = function(obj) {
var curleft = 0,
curtop = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft;
curtop = obj.offsetTop;
while ((obj = obj.offsetParent)) {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
}
}
return [curleft, curtop];
};
var findClosestAnchor = function (anchors) {
var sortByDistance = function(element1, element2) {
var pos1 = findPos( element1 ),
pos2 = findPos( element2 );
// vect1 & vect2 represent 2d vectors going from the top left extremity of each element to the point positionned at the scrolled offset of the window
var vect1 = [
window.scrollX - pos1[0],
window.scrollY - pos1[1]
],
vect2 = [
window.scrollX - pos2[0],
window.scrollY - pos2[1]
];
// we compare the length of the vectors using only the sum of their components squared
// no need to find the magnitude of each (this was inspired by Mageek’s answer)
var sqDist1 = vect1[0] * vect1[0] + vect1[1] * vect1[1],
sqDist2 = vect2[0] * vect2[0] + vect2[1] * vect2[1];
if ( sqDist1 < sqDist2 ) return -1;
else if ( sqDist1 > sqDist2 ) return 1;
else return 0;
};
// Convert the nodelist to an array, then returns the first item of the elements sorted by distance
return Array.prototype.slice.call( anchors ).sort( sortByDistance )[0];
};
// Also adapted from PPK - this guy is everywhere ! - check http://www.quirksmode.org/dom/getstyles.html
var getStyle = function(el,styleProp)
{
if (el.currentStyle)
var y = el.currentStyle[styleProp];
else if (window.getComputedStyle)
var y = document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
return y;
}
// findPos : original by @ppk - see http://www.quirksmode.org/js/findpos.html
// made recursive and transformed to returns the corect position when css columns are used
var findPos = function( obj, childCoords ) {
if ( typeof childCoords == 'undefined' ) {
childCoords = [0, 0];
}
var parentColumnWidth,
parentHeight;
var curleft, curtop;
if( obj.offsetParent && ( parentColumnWidth = parseInt( getStyle( obj.offsetParent, '-webkit-column-width' ) ) ) ) {
parentHeight = parseInt( getStyle( obj.offsetParent, 'height' ) );
curtop = obj.offsetTop;
column = Math.ceil( curtop / parentHeight );
curleft = ( ( column - 1 ) * parentColumnWidth ) + ( obj.offsetLeft % parentColumnWidth );
curtop %= parentHeight;
}
else {
curleft = obj.offsetLeft;
curtop = obj.offsetTop;
}
curleft += childCoords[0];
curtop += childCoords[1];
if( obj.offsetParent ) {
var coords = findPos( obj.offsetParent, [curleft, curtop] );
curleft = coords[0];
curtop = coords[1];
}
return [curleft, curtop];
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta>
<title>Offset 2</title>
<style>
body { font-family:helvetica,arial; font-size:12px; }
</style>
<script>
var ui = reqX = reqY = null, etop = eleft = 0, ref, cache;
function createAnchors()
{
if (!ui)
{
ui = document.getElementById('UIWebView');
reqX = document.getElementById('reqX');
reqY = document.getElementById('reqY');
var h=[], i=0;
while (i < 1000)
h.push('<a>fake anchor ... ',i,'</a> <a href=#>text for anchor <b>',(i++),'</b></a> ');
ui.innerHTML = '<div style="padding:10px;width:700px">' + h.join('') + '</div>';
cache = [];
ref = Array.prototype.slice.call(ui.getElementsByTagName('a'));
i = ref.length;
while (--i >= 0)
if (ref[i].href.length == 0)
ref.splice(i,1);
}
}
function pos(i)
{
if (!cache[i])
{
etop = eleft = 0;
var e=ref[i];
if (e.offsetParent)
{
do
{
etop += e.offsetTop;
eleft += e.offsetLeft;
} while ((e = e.offsetParent) && e != ui)
}
cache[i] = [etop, eleft];
}
else
{
etop = cache[i][0];
eleft = cache[i][1];
}
}
function find()
{
createAnchors();
if (!/^\d+$/.test(reqX.value))
{
alert ('I need a number for X');
return;
}
if (!/^\d+$/.test(reqY.value))
{
alert ('I need a number for Y');
return;
}
var
x = reqX.value,
y = reqY.value,
low = 0,
hi = ref.length + 1,
med,
limit = (ui.scrollHeight > ui.offsetHeight) ? ui.scrollHeight - ui.offsetHeight : ui.offsetHeight - ui.scrollHeight;
if (y > limit)
y = limit;
if (x > ui.scrollWidth)
x = (ui.scrollWidth > ui.offsetWidth) ? ui.scrollWidth : ui.offsetWidth;
while (low < hi)
{
med = (low + ((hi - low) >> 1));
pos(med);
if (etop == y)
{
low = med;
break;
}
if (etop < y)
low = med + 1;
else
hi = med - 1;
}
var ctop = etop;
if (eleft != x)
{
if (eleft > x)
while (low > 0)
{
pos(--low);
if (etop < ctop || eleft < x)
{
pos(++low);
break;
}
}
else
{
hi = ref.length;
while (low < hi)
{
pos(++low);
if (etop > ctop || eleft > x)
{
pos(--low);
break;
}
}
}
}
ui.scrollTop = etop - ui.offsetTop;
ui.scrollLeft = eleft - ui.offsetLeft;
ref[low].style.backgroundColor = '#ff0';
alert(
'Requested position: ' + x + ', ' + y +
'\nScrollTo position: ' + ui.scrollLeft + ', '+ ui.scrollTop +
'\nClosest anchor id: ' + low
);
}
</script>
</head>
<body>
<div id=UIWebView style="width:320px;height:480px;overflow:auto;border:solid 1px #000"></div>
<label for="req">X: <input id=reqX type=text size=5 maxlength=5 value=200></label>
<label for="req">Y: <input id=reqY type=text size=5 maxlength=5 value=300></label>
<input type=button value="Find closest anchor" onclick="find()">
</body>
</html>