Authored by gaoqiang xu

[feature] 支持H5页面图片点击捕获 reviewed by 戴强

@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 #define kAnimationDurationMultiplier (1.8) 16 #define kAnimationDurationMultiplier (1.8)
17 17
18 @interface YHWebViewProgressView () 18 @interface YHWebViewProgressView ()
  19 +<CAAnimationDelegate>
19 @property (nonatomic) BOOL isWkWebView; 20 @property (nonatomic) BOOL isWkWebView;
20 @property (nonatomic, strong)UIImageView *maskView; 21 @property (nonatomic, strong)UIImageView *maskView;
21 @end 22 @end
@@ -16,6 +16,11 @@ @@ -16,6 +16,11 @@
16 */ 16 */
17 @property (weak, nonatomic) IBOutlet id <YHExplorerDelegate> delegate; 17 @property (weak, nonatomic) IBOutlet id <YHExplorerDelegate> delegate;
18 @property (nonatomic) BOOL enableProgressBar; 18 @property (nonatomic) BOOL enableProgressBar;
  19 +/*
  20 + * Explorer的tap手势 默认NO
  21 + * 开启后可以处理图片点击事件
  22 + */
  23 +@property (nonatomic) BOOL enablePictureTapGesture;
19 @property (weak, nonatomic) UINavigationBar * currentNaviBar; 24 @property (weak, nonatomic) UINavigationBar * currentNaviBar;
20 - (UIWebView *)webView; 25 - (UIWebView *)webView;
21 26
@@ -24,4 +29,5 @@ @@ -24,4 +29,5 @@
24 * 移除滚动条 29 * 移除滚动条
25 */ 30 */
26 - (void)removeProgress; 31 - (void)removeProgress;
  32 +
27 @end 33 @end
@@ -9,13 +9,16 @@ @@ -9,13 +9,16 @@
9 #import "YHExplorerView.h" 9 #import "YHExplorerView.h"
10 10
11 @interface YHExplorerView () 11 @interface YHExplorerView ()
  12 +<UIGestureRecognizerDelegate>
12 @property (strong, nonatomic) YHExplorerViewController *webViewController; 13 @property (strong, nonatomic) YHExplorerViewController *webViewController;
13 @property (strong, nonatomic) NSString *url; 14 @property (strong, nonatomic) NSString *url;
14 @property (assign, nonatomic) BOOL isLoaded; 15 @property (assign, nonatomic) BOOL isLoaded;
  16 +@property (strong, nonatomic) UITapGestureRecognizer *tapGesture;
15 17
16 @end 18 @end
17 19
18 @implementation YHExplorerView 20 @implementation YHExplorerView
  21 +
19 - (instancetype)initWithFrame:(CGRect)frame withNaviBar:(UINavigationBar *)naviBar 22 - (instancetype)initWithFrame:(CGRect)frame withNaviBar:(UINavigationBar *)naviBar
20 { 23 {
21 self = [self initWithFrame:frame]; 24 self = [self initWithFrame:frame];
@@ -27,7 +30,7 @@ @@ -27,7 +30,7 @@
27 { 30 {
28 self = [super initWithFrame:frame]; 31 self = [super initWithFrame:frame];
29 if (self) { 32 if (self) {
30 - self.isLoaded = NO; 33 + [self _initialize];
31 } 34 }
32 35
33 return self; 36 return self;
@@ -37,12 +40,17 @@ @@ -37,12 +40,17 @@
37 { 40 {
38 self = [super initWithCoder:aDecoder]; 41 self = [super initWithCoder:aDecoder];
39 if (self) { 42 if (self) {
40 - self.isLoaded = NO; 43 + [self _initialize];
41 } 44 }
42 45
43 return self; 46 return self;
44 } 47 }
45 48
  49 +- (void)_initialize {
  50 + self.isLoaded = NO;
  51 + self.enablePictureTapGesture = NO;
  52 +}
  53 +
46 - (void)setUrl:(NSString *)url 54 - (void)setUrl:(NSString *)url
47 { 55 {
48 // 检验url是否能正常转成NSURL,防止webview不能加载 56 // 检验url是否能正常转成NSURL,防止webview不能加载
@@ -67,6 +75,9 @@ @@ -67,6 +75,9 @@
67 - (void)didMoveToWindow 75 - (void)didMoveToWindow
68 { 76 {
69 if (!self.window) { 77 if (!self.window) {
  78 + if (_tapGesture) {
  79 + [self removeGestureRecognizer:self.tapGesture];
  80 + }
70 return; 81 return;
71 } 82 }
72 83
@@ -77,6 +88,11 @@ @@ -77,6 +88,11 @@
77 [self.webViewController loadWebUrl:self.url]; 88 [self.webViewController loadWebUrl:self.url];
78 } 89 }
79 } 90 }
  91 +
  92 + if (self.enablePictureTapGesture) {
  93 + [self addGestureRecognizer:self.tapGesture];
  94 + [self.tapGesture requireGestureRecognizerToFail:self.webView.scrollView.panGestureRecognizer];
  95 + }
80 } 96 }
81 97
82 - (void)layoutSubviews 98 - (void)layoutSubviews
@@ -123,6 +139,16 @@ @@ -123,6 +139,16 @@
123 return self.webViewController.webView; 139 return self.webViewController.webView;
124 } 140 }
125 141
  142 +- (UITapGestureRecognizer *)tapGesture {
  143 + if (!_tapGesture) {
  144 + _tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hanldeTapGesture:)];
  145 + _tapGesture.delegate = self;
  146 + }
  147 + return _tapGesture;
  148 +}
  149 +
  150 +#pragma mark - Setters
  151 +
126 - (void)setDelegate:(id<YHExplorerDelegate>)delegate 152 - (void)setDelegate:(id<YHExplorerDelegate>)delegate
127 { 153 {
128 self.webViewController.delegate = delegate; 154 self.webViewController.delegate = delegate;
@@ -140,11 +166,71 @@ @@ -140,11 +166,71 @@
140 166
141 } 167 }
142 168
  169 +- (void)setEnablePictureTapGesture:(BOOL)enablePictureTapGesture {
  170 + _enablePictureTapGesture = enablePictureTapGesture;
  171 +
  172 + if (!self.window) {
  173 + return;
  174 + }
  175 +
  176 + if (enablePictureTapGesture) {
  177 + if (self.superview) {
  178 + [self addGestureRecognizer:self.tapGesture];
  179 + [self.tapGesture requireGestureRecognizerToFail:self.webView.scrollView.panGestureRecognizer];
  180 + }
  181 + } else {
  182 + if (_tapGesture) {
  183 + [self removeGestureRecognizer:self.tapGesture];
  184 + self.tapGesture = nil;
  185 + }
  186 + }
  187 +}
  188 +
143 - (BOOL)enableProgressBar 189 - (BOOL)enableProgressBar
144 { 190 {
145 return self.webViewController.progressBarEnabled; 191 return self.webViewController.progressBarEnabled;
146 } 192 }
147 193
  194 +#pragma mark - Private
  195 +- (NSString *)_getImageScriptStringWithPoint:(CGPoint)p {
  196 + NSString *string = [NSString stringWithFormat:@"var imageElement = document.elementFromPoint(%f, %f);\
  197 + var rect = imageElement.getBoundingClientRect();\
  198 + var frame = {x:rect.left, y:rect.top, width:rect.width, height:rect.height};\
  199 + var dataSet = { url:imageElement.src, displayFrame:frame };\
  200 + JSON.stringify(dataSet);", p.x, p.y];
  201 + return string;
  202 +}
  203 +
  204 +#pragma mark - UIGestureRecognizerDelegate
  205 +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
  206 + if (gestureRecognizer == _tapGesture) {
  207 + return YES;
  208 + } else {
  209 + return NO;
  210 + }
  211 +}
  212 +
  213 +#pragma mark - Gesture Handlers
  214 +- (void)hanldeTapGesture:(UITapGestureRecognizer *)gesture {
  215 + if (gesture == _tapGesture) {
  216 + CGPoint touchPoint = [gesture locationInView:self.webView];
  217 +
  218 + NSString *imgURL = [self _getImageScriptStringWithPoint:touchPoint];
  219 + NSString *resultString = [self.webView stringByEvaluatingJavaScriptFromString:imgURL];
  220 +
  221 + if (resultString.length) {
  222 +
  223 + NSData *resultData = [resultString dataUsingEncoding:NSUTF8StringEncoding];
  224 +
  225 + NSDictionary *json = [NSJSONSerialization JSONObjectWithData:resultData
  226 + options:0
  227 + error:nil];
  228 + if ([self.delegate respondsToSelector:@selector(explorer:didClickPicture:)]) {
  229 + [self.delegate explorer:self.webViewController didClickPicture:json];
  230 + }
  231 + }
  232 + }
  233 +}
148 234
149 #pragma mark - Method Forwarding 235 #pragma mark - Method Forwarding
150 - (BOOL)respondsToSelector:(SEL)aSelector 236 - (BOOL)respondsToSelector:(SEL)aSelector
@@ -137,6 +137,17 @@ @@ -137,6 +137,17 @@
137 */ 137 */
138 - (NSString * _Nullable)extraUserAgent; 138 - (NSString * _Nullable)extraUserAgent;
139 139
  140 +/**
  141 + @brief 点击图片事件
  142 + 注:需要开启 `YHExplorerView`属性`enablePictureTapGesture`
  143 +
  144 + @param explorer explorer对象
  145 + @param params 图片的一些信息
  146 +
  147 + @since 1.1.3
  148 + */
  149 +- (void)explorer:(YHExplorerViewController * _Nonnull)explorer didClickPicture:(NSDictionary * _Nonnull)pictureInfo;
  150 +
140 #pragma mark Native 151 #pragma mark Native
141 /** 152 /**
142 @brief H5端触发Native事件 153 @brief H5端触发Native事件
@@ -58,7 +58,7 @@ @@ -58,7 +58,7 @@
58 WebViewController *wv = [self.storyboard instantiateViewControllerWithIdentifier:@"wc"]; 58 WebViewController *wv = [self.storyboard instantiateViewControllerWithIdentifier:@"wc"];
59 59
60 if ([title isEqualToString:@"链接跳转"]) { 60 if ([title isEqualToString:@"链接跳转"]) {
61 - wv.url = @"http://sealedace.com/content/images/test/h5_test.html"; 61 + wv.url = @"http://m.yohobuy.com";
62 } else { 62 } else {
63 wv.url = @"http://localhost"; 63 wv.url = @"http://localhost";
64 } 64 }
@@ -13,6 +13,8 @@ @@ -13,6 +13,8 @@
13 <YHExplorerDelegate> 13 <YHExplorerDelegate>
14 @property (weak, nonatomic) IBOutlet YHExplorerView *webView; 14 @property (weak, nonatomic) IBOutlet YHExplorerView *webView;
15 @property (strong, nonatomic) UITextView *tv; 15 @property (strong, nonatomic) UITextView *tv;
  16 +@property (strong, nonatomic) UIVisualEffectView *blurView;
  17 +@property (strong, nonatomic) UIImageView *displayPictureView;
16 @end 18 @end
17 19
18 @implementation WebViewController 20 @implementation WebViewController
@@ -32,6 +34,27 @@ @@ -32,6 +34,27 @@
32 return YES; 34 return YES;
33 } 35 }
34 36
  37 +- (UIVisualEffectView *)blurView {
  38 + if (!_blurView) {
  39 + UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
  40 + _blurView = [[UIVisualEffectView alloc] initWithEffect:effect];
  41 + _blurView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 200.f);
  42 + [_blurView addSubview:self.displayPictureView];
  43 + _blurView.userInteractionEnabled = YES;
  44 + self.displayPictureView.frame = _blurView.bounds;
  45 + }
  46 + return _blurView;
  47 +}
  48 +
  49 +- (UIImageView *)displayPictureView {
  50 + if (!_displayPictureView) {
  51 + _displayPictureView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
  52 + _displayPictureView.contentMode = UIViewContentModeScaleAspectFit;
  53 + _displayPictureView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
  54 + }
  55 + return _displayPictureView;
  56 +}
  57 +
35 - (void)dealloc 58 - (void)dealloc
36 { 59 {
37 60
@@ -52,6 +75,7 @@ @@ -52,6 +75,7 @@
52 [super viewDidLoad]; 75 [super viewDidLoad];
53 self.webView.delegate = self; 76 self.webView.delegate = self;
54 self.webView.enableProgressBar = YES; 77 self.webView.enableProgressBar = YES;
  78 + self.webView.enablePictureTapGesture = YES;
55 79
56 [self.webView loadWebUrl:self.url]; 80 [self.webView loadWebUrl:self.url];
57 // [self.webView loadWebUrl:[[NSBundle mainBundle] pathForResource:@"untitled" ofType:@"html"]]; 81 // [self.webView loadWebUrl:[[NSBundle mainBundle] pathForResource:@"untitled" ofType:@"html"]];
@@ -68,6 +92,21 @@ @@ -68,6 +92,21 @@
68 // [self.webView loadHTMLString:html]; 92 // [self.webView loadHTMLString:html];
69 } 93 }
70 94
  95 +- (void)viewWillAppear:(BOOL)animated {
  96 + [super viewWillAppear:animated];
  97 +
  98 + if (self.blurView.superview) {
  99 + [NSObject cancelPreviousPerformRequestsWithTarget:self];
  100 + [self performSelector:@selector(hideBlurView) withObject:nil afterDelay:2];
  101 + }
  102 +}
  103 +
  104 +- (void)viewWillDisappear:(BOOL)animated {
  105 + [super viewWillDisappear:animated];
  106 +
  107 + [NSObject cancelPreviousPerformRequestsWithTarget:self];
  108 +}
  109 +
71 #pragma mark - YHExplorerDelegate 110 #pragma mark - YHExplorerDelegate
72 - (void)pageTitleUpdated:(NSString *)title 111 - (void)pageTitleUpdated:(NSString *)title
73 { 112 {
@@ -117,4 +156,61 @@ @@ -117,4 +156,61 @@
117 self.tv.text = [[NSString alloc] initWithFormat:@"url: %@\nopentype: %@\nopenParams:\n%@", freshUrl, openType, openParameters]; 156 self.tv.text = [[NSString alloc] initWithFormat:@"url: %@\nopentype: %@\nopenParams:\n%@", freshUrl, openType, openParameters];
118 } 157 }
119 158
  159 +// H5上点击了图片的事件
  160 +- (void)explorer:(YHExplorerViewController *)explorer didClickPicture:(NSDictionary *)pictureInfo {
  161 + NSLog(@"explorer didClickPicture: \n%@", pictureInfo);
  162 +
  163 + NSString *imageUrl = pictureInfo[@"url"];
  164 +
  165 + if (imageUrl.length == 0) {
  166 + return;
  167 + }
  168 +
  169 + CGFloat width = CGRectGetWidth(self.view.frame);
  170 + CGFloat height = CGRectGetHeight(self.view.frame)-CGRectGetMaxY(self.navigationController.navigationBar.frame);
  171 +
  172 + self.blurView.frame = CGRectMake((CGRectGetWidth(self.view.frame)-width)/2,
  173 + CGRectGetHeight(self.view.frame)+height,
  174 + width,
  175 + height);
  176 +
  177 + if (self.blurView.superview) {
  178 + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideBlurView) object:nil];
  179 + [self performSelector:@selector(hideBlurView) withObject:nil afterDelay:2];
  180 + } else {
  181 +
  182 + [self.view addSubview:self.blurView];
  183 + [UIView animateWithDuration:0.7
  184 + delay:0
  185 + usingSpringWithDamping:1
  186 + initialSpringVelocity:0.5
  187 + options:UIViewAnimationOptionCurveEaseInOut
  188 + animations:^{
  189 + CGPoint center = self.blurView.center;
  190 + self.blurView.center = CGPointMake(center.x, CGRectGetHeight(self.view.frame)-height/2);
  191 + } completion:^(BOOL finished) {
  192 + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideBlurView) object:nil];
  193 + [self performSelector:@selector(hideBlurView) withObject:nil afterDelay:2];
  194 + }];
  195 + }
  196 +
  197 + // 从url加载图片
  198 + NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
  199 + self.displayPictureView.image = [UIImage imageWithData:imageData scale:0];
  200 +}
  201 +
  202 +- (void)hideBlurView {
  203 + [UIView animateWithDuration:0.7
  204 + delay:0
  205 + usingSpringWithDamping:1
  206 + initialSpringVelocity:0.5
  207 + options:UIViewAnimationOptionCurveEaseInOut
  208 + animations:^{
  209 + CGPoint center = self.blurView.center;
  210 + self.blurView.center = CGPointMake(center.x, CGRectGetHeight(self.view.frame)+CGRectGetHeight(self.blurView.frame)/2);
  211 + } completion:^(BOOL finished) {
  212 + [self.blurView removeFromSuperview];
  213 + }];
  214 +}
  215 +
120 @end 216 @end