思路:safari 自带了长按保存的功能,分析这个功能的特点: 长按一个图片,保存后的图片就是所点击的图片,做到了精确定位。JS可以处理精确定位的问题,使用UIWebview 和 JS 能够解决我们的问题。
直接上代码
UIWebView *aWebView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)];
aWebView.delegate = self;
aWebView.scalesPageToFit = YES;
self.mainWebView = aWebView;
[self.view addSubview:aWebView];
NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://image.baidu.com/"] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:20];
[self.mainWebView loadRequest:request];
UILongPressGestureRecognizer *longtapGesture = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longtap:)];
[self.view addGestureRecognizer:longtapGesture];
添加webview,添加长按手势,看起来没有什么。
-(void)longtap:(UILongPressGestureRecognizer * )longtapGes{
if (longtapGes.state == UIGestureRecognizerStateBegan) {
CGPoint pt = [longtapGes locationInView:self.view];
pt= [self.mainWebView convertPoint:pt fromView:nil];
CGPoint offset = [self.mainWebView.scrollView contentOffset];
CGSize viewSize = [self.view frame].size;
CGSize windowSize = [self.view frame].size;
CGFloat f = windowSize.width / viewSize.width;
pt.x = pt.x * f + offset.x;
pt.y = pt.y * f + offset.y;
[self openContextualMenuAt:pt];
}
}
注意看下这段代码
pt 为映射在webview 上的坐标
得到坐标后,根据contentOffset,获取到点击的坐标上在 web 绝对位置上的坐标点。
- (void)openContextualMenuAt:(CGPoint)pt
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"test1" ofType:@"txt"];
NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[self.mainWebView stringByEvaluatingJavaScriptFromString: jsCode];
NSString *tags = [self.mainWebView stringByEvaluatingJavaScriptFromString:
[NSString stringWithFormat:@"MyAppGetHTMLElementsAtPoint(%i,%i);",(NSInteger)pt.x,(NSInteger)pt.y]];
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Contextual Menu"
delegate:self cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil otherButtonTitles:nil];
if ([tags rangeOfString:@",A,"].location != NSNotFound) {
[sheet addButtonWithTitle:@"打开链接"];
}
if ([tags rangeOfString:@",IMG,"].location != NSNotFound) {
NSString *str = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", pt.x, pt.y];
NSString *imgStr= [self.mainWebView stringByEvaluatingJavaScriptFromString: str];
NSLog(@"启动一个request下载图片:%@",imgStr);
[sheet addButtonWithTitle:@"保存图片"];
}
[sheet addButtonWithTitle:@"在Safari中打开"];
[sheet showInView:self.view];
}
test1.txt 内容如下
function MyAppGetHTMLElementsAtPoint(x,y) {
var tags = ",";
var e = document.elementFromPoint(x,y);
while (e) {
if (e.tagName) {
tags += e.tagName + ',';
}
e = e.parentNode;
}
return tags;
}
这段js 能够返回 web 内容坐标对应 web 节点
然后通过注入方式调用js,并获取到图片地址
NSString *str = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", pt.x, pt.y];
NSString *imgStr= [self.mainWebView stringByEvaluatingJavaScriptFromString: str];
到这里,我们的任务已经完成了大半了。
还需要做的是弹出选择框,用户选择操作,代码实现选择操作。此处省略若干代码和说明。
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
// 这里实际启动request,下载图片
// 我看见UC 浏览器断网也是可以下载图片的,我大概知道是通过JS,但具体操作就不知道了,有没有人知道是怎么实现的,分享下
}
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}
这里 webview 一旦加载完成了,通过JS注入,这段js 直接去除了点击和选中效果,否则会出现uiwebview 自带copy 工具,以及选中变灰的效果。
总结:
在webview 加载完成之后,禁用掉webview自带的选择和长按事件。
在外部添加长按事件,并映射成webview中长按事件所处的位置px
在通过调用stringByEvaluatingJavaScriptFromString:@""方法获取到上步中px所处位置的 html 节点
同样通过调用stringByEvaluatingJavaScriptFromString:@""方法得到节点的 src 信息
新开请求去获得图片
我看见UC 浏览器断网也是可以下载图片的,我大概知道是通过JS,但具体操作就不知道了,有没有人知道是怎么实现的,分享下