UIWebView 使用 elementFromPoint() 获取图像 url
Posted
技术标签:
【中文标题】UIWebView 使用 elementFromPoint() 获取图像 url【英文标题】:UIWebView getting image url with elementFromPoint() 【发布时间】:2013-08-14 18:38:20 【问题描述】:我正在尝试使用 UILongPressGestureRecognizer 获取在 UIWebView 中点击的图像的 url。
我有这个工作,但我不确定坐标是否关闭,或者它只是没有在 DOM 中找到 img 标签,因为它并不总是有效。
我正在使用此代码:
int displayWidth = [[self.webView stringByEvaluatingjavascriptFromString:@"window.outerWidth"] intValue];
CGFloat scale = self.webView.frame.size.width / displayWidth;
CGPoint pt = [gesture locationInView:self.webView];
pt.x /= scale;
pt.y /= scale;
NSString *imgURL = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).parentElement.getElementsByTagName(\"img\")[0].src", pt.x, pt.y];
NSString *urlToSave = [self.webView stringByEvaluatingJavaScriptFromString:imgURL];
如果我使用的网站开始时缩小并在网格中显示图像,然后放大然后选择图像,我会在页面左上角得到图像,而不是单击的图像。 不确定是缩放问题、偏移问题还是 DOM 问题?
编辑------------
对于初学者来说,坐标绝对是错误的! 如果我单击 UIWebView 中网页上的某个点,我会得到以下结果: 滚动 Y:0 点击点Y:89 Y *= scale += scrollY = 86.8293
现在,如果我向上滚动页面,那么我点击的点与顶部一致(大约在 y=0 处),我会得到以下结果: 滚动Y:144 点击点Y:1 Y *= scale += scrollY = 144.976
现在在计算之前,滚动似乎关闭了。该点是 89,但当滚动到该点时,滚动显示为 144。为什么会这样?
我正在从 window.pageYOffset 获取滚动
【问题讨论】:
我没有能力在周末测试任何 ios 东西,但有两个猜测:1)也许locationInView
返回相对于 UIWebView
框架的坐标,而不是它的内容,这意味着例如无论您是滚动还是缩放页面,点击UIWebView
的左上角都会给出0,0
? 2) 如果所有图像都有一个共同的父级,那么document.elementFromPoint(%f, %f).parentElement.getElementsByTagName("img")[0]
显然总是会返回第一个图像,无论哪个被点击。
谢谢。我没有考虑您关于所有具有共同父母的图像的第二点。在这种情况下有办法获取图像吗?例如,有一个包含许多图像的 列表。
【参考方案1】:
将这 2 个 javascript 函数放在一个名为 JSTools.js 的文件中
function gethtmlElementsAtPoint(x,y)
var tags = "";
var e;
var offset = 0;
while ((tags.search(",(A|IMG),") < 0) && (offset < 20))
tags = ",";
e = document.elementFromPoint(x,y+offset);
while (e)
if (e.tagName)
tags += e.tagName + ',';
e = e.parentNode;
if (tags.search(",(A|IMG),") < 0)
e = document.elementFromPoint(x,y-offset);
while (e)
if (e.tagName)
tags += e.tagName + ',';
e = e.parentNode;
offset++;
return tags;
function getLinkSRCAtPoint(x,y)
var tags = "";
var e = "";
var offset = 0;
while ((tags.length == 0) && (offset < 20))
e = document.elementFromPoint(x,y+offset);
while (e)
if (e.src)
tags += e.src;
break;
e = e.parentNode;
if (tags.length == 0)
e = document.elementFromPoint(x,y-offset);
while (e)
if (e.src)
tags += e.src;
break;
e = e.parentNode;
offset++;
return tags;
然后在你的控制器中
- (void)longPressRecognized:(UILongPressGestureRecognizer *)gestureRecognizer
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
CGPoint point = [gestureRecognizer locationInView:webView];
longpressTouchedPoint = point;
// convert point from view to HTML coordinate system
CGSize viewSize = [webView frame].size;
CGSize windowSize = [webView windowSize];
CGFloat f = windowSize.width / viewSize.width;
if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 5.)
point.x = point.x * f;
point.y = point.y * f;
else
// On iOS 4 and previous, document.elementFromPoint is not taking
// offset into account, we have to handle it
CGPoint offset = [webView scrollOffset];
point.x = point.x * f + offset.x;
point.y = point.y * f + offset.y;
// Load the JavaScript code from the Resources and inject it into the web page
NSString *path = [[NSBundle mainBundle] pathForResource:@"JSTools" ofType:@"js"];
NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[webView stringByEvaluatingJavaScriptFromString: jsCode];
// call js functions
NSString *tags = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"getHTMLElementsAtPoint(%i,%i);",(NSInteger)point.x,(NSInteger)point.y]];
NSString *tagsSRC = [webView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"getLinkSRCAtPoint(%i,%i);",(NSInteger)point.x,(NSInteger)point.y]];
NSLog(@"src : %@",tags);
NSLog(@"src : %@",tagsSRC);
NSString *url = nil;
if ([tags rangeOfString:@",IMG,"].location != NSNotFound)
url = tagsSRC; // Here is the image url!
混合来自多个来源,感谢网络社区!
编辑
您还必须使用这两个功能在 uiwebview 上创建一个类别:
- (CGSize)windowSize
CGSize size;
size.width = [[self stringByEvaluatingJavaScriptFromString:@"window.innerWidth"] integerValue];
size.height = [[self stringByEvaluatingJavaScriptFromString:@"window.innerHeight"] integerValue];
return size;
- (CGPoint)scrollOffset
CGPoint pt;
pt.x = [[self stringByEvaluatingJavaScriptFromString:@"window.pageXOffset"] integerValue];
pt.y = [[self stringByEvaluatingJavaScriptFromString:@"window.pageYOffset"] integerValue];
return pt;
【讨论】:
谢谢,虽然我遇到了 2 个编译错误。 webView 中没有 windowSize 选择器,webView 中没有 scrollOffset 选择器。有什么想法吗? 这很好用。谢谢你。这个和我做它的方式的主要区别是它获取坐标的方式。 对不起,我整个周末都没有上网,也没有接受你的回答,所以你只得到了我想的一半的赏金。不过感谢您的帮助。我敢肯定,一些赞成票会弥补这一点。 没问题,这是我对 SO 的第一个回答:在我看来,即使是半个赏金也是一个好的开始!【参考方案2】:我最近实现了一个类似的目标,但我没有确定“触摸”坐标。
如果您有权修改 html/javascript 源代码,我的回答会有所帮助。
我做了什么:
在每个图像上<img...
html DOM 元素我把onClick
javascript 处理程序更改为window.location
f.e
javascript function clickedImage(imageURL)
window.location = "customScheme://"+imageURL; // attached image url to be able to read it inside `UIWebView`
在UIWebView
委托的方法上忽略上面的链接,但是,我们能够得到图片的URL。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
if ([[request.URL scheme] isEqualToString:@"customScheme"])
//Fetching image URL
NSLog(@"Clicked on image with URL %@", [request.URL host])
...
// Always return NO not to allow `UIWebView` process such links
return NO;
....
抱歉,如果这种方法不完全适合您的问题,但我想这是您可以遵循并深入挖掘的选项。
小记:要使用UILongPressGestureRecognizer
,你可以通过制作javascript来模拟这种行为:
Long Press in JavaScript?
【讨论】:
这是一个非常有趣的想法。使用 Javascript 拦截并返回图片 URL。我需要使用长按,因为我希望用户能够浏览网络,因此需要单击链接。我想知道,如果图像也是链接,会发生什么情况,是否可以抓取底层图像? 你不应该将图像作为链接( 啊,是的,但那是我的html?我希望用户浏览任何网页并抓取图像。我可能会在加载和更改 html 时拦截它,但有很多可能性 是的,如果用户可以在任何地方浏览,你应该解析DOM元素并修改每个 请查看我对问题的编辑。接触点肯定是关闭的。【参考方案3】:您可以通过以下代码获取元素
<script type="text/javascript">
(function($)
$.fn.longClick = function(callback, timeout)
var timer;
timeout = timeout || 500;
$(this).mousedown(function(e)
timer = setTimeout(function() callback(e.offsetX,e.offsetY); , timeout);
return false;
);
$(document).mouseup(function()
clearTimeout(timer);
return false;
);
;
)(jQuery);
$(window).longClick(function(x,y)
var element = document.elementFromPoint(x, y);
alert(nodeToString(element));
,600);
function nodeToString ( node )
var tmpNode = document.createElement( "div" );
tmpNode.appendChild( node.cloneNode( true ) );
var str = tmpNode.innerHTML;
tmpNode = node = null; // prevent memory leaks in IE
return str;
</script>
这只是js代码。 mousedown 和 mouseup 不适用于 ios 。您需要为 ios webView 使用其他替代事件。
【讨论】:
以上是关于UIWebView 使用 elementFromPoint() 获取图像 url的主要内容,如果未能解决你的问题,请参考以下文章
UIWebView和UICollectionViewController的使用