美文网首页
截取ScrollView中的全部内容以及添加水印

截取ScrollView中的全部内容以及添加水印

作者: 翻炒吧蛋滚饭 | 来源:发表于2016-08-26 10:13 被阅读759次

    一、我们要做什么

    我们要做的是这种效果!
    打开一个网页,百度为例吧


    webView展示网页内容

    这个时候我们点击保存截图,我们要把整个网页保存为图片,然后在网页的结尾加上一个二维码,这样分享到微信什么的,就可以直接识别网页链接了。效果是酱婶儿的。


    相册中查看保存的图

    二、需要哪些知识点

    1、主要还是绘图
    2、二维码
    3、如果想做成home+power截屏时保存这张大长图,还要用到截屏的通知,这个最后说吧。

    三、Let's 整!

    第一页

    第一页就不说了,storyboard上拖个输入框、按钮什么的就ok了。
    输入网址,点击确定后传给第二个页面的webView去请求链接,展示网页。
    展示之后,我们要把整个网页全部绘制成图片。
    下面是保存截图按钮执行的代码

    - (IBAction)saveAction:(id)sender {
        // 获取scrollView
        UIScrollView *scrollView = self.webView.scrollView;
        UIImage* image = nil;
        
        // 开始绘制
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(scrollView.contentSize.width, scrollView.contentSize.height+100), NO, 0.0);
        {
            // 保存原有的scrollView偏移量和frame
            CGPoint savedContentOffset = scrollView.contentOffset;
            CGRect savedFrame = scrollView.frame;
            
            // 展开scrollView
            scrollView.contentOffset = CGPointZero;
            scrollView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height);
            
            // 将scrollView的layer渲染到上下文中
            [scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
            
            // 画背景
            UIImage *backImage = [UIImage createImageWithColor:[UIColor whiteColor]];
            [backImage drawInRect:CGRectMake(0, scrollView.contentSize.height-100, scrollView.contentSize.width, 100)];
            
            // 画二维码
            UIImage *qrImage = [QRCodeGenerator qrImageForString:self.url imageSize:300];
            [qrImage drawInRect:CGRectMake(scrollView.contentSize.width*0.5-40, scrollView.contentSize.height-100+10, 80, 80)];
            
            // 获取结果图片
            image = UIGraphicsGetImageFromCurrentImageContext();
            
            // 还原scrollView偏移量和frame
            scrollView.contentOffset = savedContentOffset;
            scrollView.frame = savedFrame;
        }
        UIGraphicsEndImageContext();
        
        if (image != nil) {
            // 写到相册
            UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
        }
    }
    

    讲解下原理:主要就是让webView的frame中的宽高等于自己的contentSize的宽高,这样webView就把自己的所有内容展示出来了,然后把webView的layer渲染到上下文中,再通过如下的库生成二维码图片(头文件QRCodeGenerator.h),再将二维码绘制到刚才的layer上。文字、图片什么的都可以这样绘制上去。最后再从上下文中获取绘制好的最后的图片,通过UIImageWriteToSavedPhotosAlbum方法,可以将图片保存到相册。


    生成二维码的库

    灰常简单就实现了。

    三、拓展

    这时如果说想用截屏来做的话,那就可以使用如下的通知来获取截屏事件。

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(screenShot:) name:UIApplicationUserDidTakeScreenshotNotification object:nil];
    

    关于图像上下文,绘图中比较难理解的还是图形上下文,很多人应该不理解为什么上下文就突然出现在这里了,它是做什么用的?这时看看下面这两篇就差不多可以理解的差不多了。
    上下文是什么,了解上下文是什么、干嘛用的
    iOS绘图上下文的理解,这样就了解了上下文栈是干什么的,配合上面的文章就知道上下文的原理和用途了。
    顺便,tableView、collectionView什么的,都是继承自ScrollView的,所以都可以用以上方法进行处理,其他的各种控件,拿到layer也都可以渲染出来保存为图片,截屏也就很方便了。下面贴下,截取显示屏幕的方法

        CGSize imageSize = CGSizeZero;
        UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
        if (UIInterfaceOrientationIsPortrait(orientation))
            imageSize = [UIScreen mainScreen].bounds.size;
        else
            imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
        
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
        CGContextRef context = UIGraphicsGetCurrentContext();
        for (UIWindow *window in [[UIApplication sharedApplication] windows])
        {
            CGContextSaveGState(context);
            CGContextTranslateCTM(context, window.center.x, window.center.y);
            CGContextConcatCTM(context, window.transform);
            CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
            if (orientation == UIInterfaceOrientationLandscapeLeft)
            {
                CGContextRotateCTM(context, M_PI_2);
                CGContextTranslateCTM(context, 0, -imageSize.width);
            }
            else if (orientation == UIInterfaceOrientationLandscapeRight)
            {
                CGContextRotateCTM(context, -M_PI_2);
                CGContextTranslateCTM(context, -imageSize.height, 0);
            } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
                CGContextRotateCTM(context, M_PI);
                CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
            }
            if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)])
            {
                [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
            }
            else
            {
                [window.layer renderInContext:context];
            }
            CGContextRestoreGState(context);
        }
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    

    主要思想还是获取当前window,渲染他的layer,同时对屏幕的旋转情况做了处理,如果app不支持屏幕旋转,就可以省去了。

    四、Demo如下

    https://github.com/ZhaoheMHz/ScrollViewScreenShot

    相关文章

      网友评论

          本文标题:截取ScrollView中的全部内容以及添加水印

          本文链接:https://www.haomeiwen.com/subject/grhasttx.html