写在前面

最近有这么一个需求,分享页面,分享的是web订单截图,既然是web 就会有超出屏幕的部分,
生成的图片还要加上我们的二维码,这就涉及到图片的合成了。
有了这样的需求,就是各种google.也算解决了自己的需求,另外,也总结了一下,对需求做了下拓展,目前是swift4.0版本。

整合成一个三方库,以下只是部分代码,详细代码及demo请见,github地址https://github.com/dudongge/DDGScreenShot


View生成图片

代码也比较简单 screenShotImage 就是截取后的图片
let context = UIGraphicsGetCurrentContext()
context?.saveGState()
context?.translateBy(x: -self.frame.origin.x, y: -self.frame.origin.y);
self.layer.render(in: context!)
let screenShotImage = UIGraphicsGetImageFromCurrentImageContext()
context?.restoreGState();
UIGraphicsEndImageContext()

ScrollView生成图片

只要实现原理是计算偏移量,每一屏绘制一次,放在内存里,最后将所有的图片组合成一张图片 screenShotImage就是最终图片
public func DDGContentScrollScreenShot (_ completionHandler: @escaping (_ screenShotImage: UIImage?) -> Void) { self.isShoting = true let snapShotView = self.snapshotView(afterScreenUpdates: true)
snapShotView?.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: (snapShotView?.frame.size.width)!, height: (snapShotView?.frame.size.height)!)
self.superview?.addSubview(snapShotView!) let bakOffset = self.contentOffset let page = floorf(Float(self.contentSize.height / self.bounds.height)) UIGraphicsBeginImageContextWithOptions(self.contentSize, false, UIScreen.main.scale) self.DDGContentScrollPageDraw(0, maxIndex: Int(page), drawCallback: { [weak self] () -> Void in
let strongSelf = self let screenShotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext() strongSelf?.setContentOffset(bakOffset, animated: false)
snapShotView?.removeFromSuperview() strongSelf?.isShoting = false completionHandler(screenShotImage)
}) } fileprivate func DDGContentScrollPageDraw (_ index: Int, maxIndex: Int, drawCallback: @escaping () -> Void) { self.setContentOffset(CGPoint(x: 0, y: CGFloat(index) * self.frame.size.height), animated: false)
let splitFrame = CGRect(x: 0, y: CGFloat(index) * self.frame.size.height, width: bounds.size.width, height: bounds.size.height) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.3 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in
self.drawHierarchy(in: splitFrame, afterScreenUpdates: true) if index < maxIndex {
self.DDGContentScrollPageDraw(index + 1, maxIndex: maxIndex, drawCallback: drawCallback)
}else{
drawCallback()
}
}
}

UIwebView生成图片 && wkwebView

绘制时大同小异,只是wkwebView 调用的绘制方法为:drawHierarchy 其核心代码如下
采用递归,直到拿到最后一个偏移量。
fileprivate func DDGRenderImageView(_ completionHandler: @escaping (_ screenShotImage: UIImage?) -> Void) {
let ddgTempRenderView = UIView(frame: CGRect(x: 0, y: 0, width: self.contentSize.width, height: self.contentSize.height))
self.removeFromSuperview()
ddgTempRenderView.addSubview(self) self.contentOffset = CGPoint.zero
self.frame = ddgTempRenderView.bounds DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.3 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in
let bounds = self.bounds
UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale) if (self.DDGContainsWKWebView()) {
self.drawHierarchy(in: bounds, afterScreenUpdates: true)
}else{
self.layer.render(in: UIGraphicsGetCurrentContext()!)
}
let screenShotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext() completionHandler(screenShotImage)
}
}
fileprivate func shotScreenContentScrollPageDraw (_ index: Int, maxIndex: Int, drawCallback: @escaping () -> Void) { self.scrollView.setContentOffset(CGPoint(x: 0, y: CGFloat(index) * self.scrollView.frame.size.height), animated: false)
let splitFrame = CGRect(x: 0, y: CGFloat(index) * self.scrollView.frame.size.height, width: bounds.size.width, height: bounds.size.height) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.3 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)) { () -> Void in
self.drawHierarchy(in: splitFrame, afterScreenUpdates: true) if index < maxIndex {
self.shotScreenContentScrollPageDraw(index + 1, maxIndex: maxIndex, drawCallback: drawCallback)
}else{
drawCallback()
}
}
}

两张图片合为一张(一张底图,一张logo)

在UIImage上做了拓展
let imageRef = self.cgImage
let w: CGFloat = CGFloat((imageRef?.width)!)
let h: CGFloat = CGFloat((imageRef?.height)!)
//以1.png的图大小为画布创建上下文
UIGraphicsBeginImageContext(CGSize(width: w, height: h))
self.draw(in: CGRect(x: 0, y: 0, width: w, height: h))
//先把1.png 画到上下文中
logo.draw(in: CGRect(x: logoOrigin.x,
y: logoOrigin.y,
width: logoSize.width,
height:logoSize.height))
//再把小图放在上下文中
let resultImg: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
//从当前上下文中获得最终图片
UIGraphicsEndImageContext()
return resultImg!

在图片上写文字/加标签

同样对UIimage 做了拓展,增加了几个参数
public func drawTextInImage(text: String,
textColor: UIColor,
textFont: CGFloat,
textBgColor: UIColor,
textX: CGFloat,
textY: CGFloat )->UIImage {
//开启图片上下文
UIGraphicsBeginImageContext(self.size)
//图形重绘
self.draw(in: CGRect.init(x: 0, y: 0, width: self.size.width, height: self.size.height))
//水印文字属性
let att = [NSAttributedStringKey.foregroundColor: textColor,
NSAttributedStringKey.font: UIFont.systemFont(ofSize: textFont),
NSAttributedStringKey.backgroundColor: textBgColor]
//水印文字大小
let text = NSString(string: text)
let size = text.size(withAttributes: att)
//绘制文字
text.draw(in: CGRect.init(x: textX, y: textY, width: size.width, height: size.height), withAttributes: att)
//从当前上下文获取图片
let image = UIGraphicsGetImageFromCurrentImageContext()
//关闭上下文
UIGraphicsEndImageContext()
return image!
}

结束语

空间有限,所注代码不全,我把上述功能整理成了最新的带三方库,
以后会加上图片的相关处理,比如美颜,剪切,马赛克,组图等,
附上我的git地址:https://github.com/dudongge/DDGScreenShot
有什么问题也可以联系我QQ:532835032
如果对您有帮助,请您不吝star一下,增加我更新的动力

附上github上READER.ME文件部分内容

## view截屏:
view.DDGScreenShot { (image) in
拿到 image
各种复杂装逼操作
、、、、
}
## ScrollView截屏:
scrollView.DDGContentScrollScreenShot { (image) in
拿到 image
各种复杂装逼操作
、、、、
}
## webView截屏:
webView.DDGContentscreenShot { (image) in
拿到 image
各种复杂装逼操作
、、、、
}
## wkwebView截屏: 方法和webView 一样,内部做了校验
webView.DDGContentscreenShot { (image) in
拿到 image
各种复杂装逼操作
、、、、
}
## image 加 logo
let image = image.composeImageWithLogo( logo: UIImage,
logoOrigin: CGPoint,
logoSize:CGSize)
传入 logo图片,logo位置 logo 大小 就可以得到一张生成好的图片
、、、、
## image 加 标签,水印,文字
let image = image.drawTextInImage(text: String,
textColor: UIColor,
textFont: CGFloat,
textBgColor: UIColor,
textX: CGFloat,
textY: CGFloat )
传入 文字、文字颜色、字体大小、背景颜色,字体起始位置 就可以得到一张生成好的带标签的图片
、、、、
注,此方法在提交pod有问题,故将方法屏蔽,有需要的可以拷贝代码,到本地 ## 使用pod
iOS 9.0+, Swift 4.0+(Compatiable)
使用pod 导入
pod 'DDGScreenShot', '~> 1.0.1'
```

欢迎查看DDGScreenShot

其余功能如下

  1. (一)DDGScreenShot — 复杂屏幕截屏(如view ScrollView webView wkwebView)
  2. (二)DDGScreenShot--iOS 图片处理--多图片拼接
  3. (三)DDGScreenShot--iOS 图片裁剪,切圆角,加边框,你还用cornerRadius,还有更高级的用法
  4. (四)DDGScreenShot—图片擦除功能
  5. (五)DDGScreenShot—截取图片的任意部分
  6. (六)DDGScreenShot —图片加各种滤镜高逼格操作
  7. (七)DDGScreenShot —图片加高斯模糊,老电影效果

DDGScreenShot — 复杂屏幕截屏(如view ScrollView webView wkwebView)的更多相关文章

  1. iOS中的截屏(屏幕截屏及scrollView或tableView的全部截屏)

    iOS中的截屏(屏幕截屏及scrollView或tableView的全部截屏) 2017.03.16 12:18* 字数 52 阅读 563评论 4喜欢 2 1. 截取屏幕尺寸大小的图片并保存至相册 ...

  2. java实现屏幕截屏功能

    最近在项目中遇到这样一个需求,用户生成推广海报想要发送给朋友,但是推广海报是用html网页写的,这时候想要分享给朋友的话只能用户自己手机截图,显然这样的用户体验是不友好的,如果可以给用户一个按钮实现一 ...

  3. android之截屏(包括截取scrollview与listview的)

    public class ScreenShot { // 获取指定Activity的截屏,保存到png文件 public static Bitmap takeScreenShot(Activity a ...

  4. iOS当前屏幕截屏

    需求描述: 有两个ViewController 我们记做 A.B ,其中B controller只是显示下半部分: 如下图效果: 实现这种的方案很多,可以用添加View方法,  也可以用UIWindo ...

  5. IOS 上架要求视频及屏幕截屏

    客户提供上架的资料 1.IOS 上架要求视频演示,录制一段视频,上传到优酷,需要url连接. 2.手机截屏,每个尺寸5张.5s/6/6p *5=15张.截屏图片分辨率. iPhone4s手机 3.5I ...

  6. delphi 屏幕截屏

    function GetScreenAll: TBitmap; // 截取全屏 var C: TCanvas; begin C := TCanvas.Create; result := TBitmap ...

  7. C# 实现屏幕截屏

    //屏幕宽            int iWidth = Screen.PrimaryScreen.Bounds.Width;            //屏幕高            int iHe ...

  8. [Xcode 实际操作]九、实用进阶-(15)屏幕截屏:截取当前屏幕上的显示内容

    目录:[Swift]Xcode实际操作 本文将演示如何截取屏幕画面,并将截取图片,存入系统相册. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UI ...

  9. iOS屏幕截屏

    #import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...

随机推荐

  1. 《java入门第一季》之泛型类引入

    首先用一个例子引入泛型类. 我定义一个Object类: package cn.it_03; public class ObjectTool { private Object obj; public O ...

  2. Dynamics CRM2011/2013 站点地图sitemap的翻译

    实体.属性字段.ribbon等的翻译可以通过解决方案来解决(具体可见我前面的博客:http://blog.csdn.net/vic0228/article/details/37690913),但解决方 ...

  3. Miscellaneous Articles

    标记一下,慢慢看  http://www.oracle-base.com/articles/misc/articles-misc.php Miscellaneous Articles DBA Deve ...

  4. JAVA之旅(十二)——Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口

    JAVA之旅(十二)--Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口 开始挑战一些难度了,线程和I/O方面的操作了,继续坚持 一. ...

  5. Leetcode_21_Merge Two Sorted Lists

    ->4->4,return 1->2->3->4->5->6. 思路: (1)题意为将两个有序链表合成一个有序链表. (2)首先,分别对链表头结点判空,如果都 ...

  6. 敏捷测试(8)--ATDD整体研发流程

    ATDD整体研发流程 有了前面的基于story的敏捷基础,接下来来介绍一下验收测试驱动开发的整个流程. 名词解释: ATD,即验收测试设计(acceptancetest design) PM,即需求整 ...

  7. Flash Media Live Encoder 使用帮助

    翻译了一下Flash Media Live Encoder的帮助内容. Flash Media Live Encoder包含两个工具: Flash Media Live Encoder GUI(图 ...

  8. Mahout 模糊kmeans

    Mahout  模糊KMeans 一.算法流程 模糊 C 均值聚类(FCM),即众所周知的模糊 ISODATA,是用隶属度确定每个数据点属于某个聚类的程度的一种聚类算法.1973 年,Bezdek 提 ...

  9. 在自己的服务器上安装GitBook

    更新时间:2016-08-05 更新说明: 由于在 Linux 内核的机器上安装 Calibre 需要安装的依赖库过多,故不推荐在此类机器上使用格式转换功能.你可以阅读 在自己的电脑上安装GitBoo ...

  10. 《java入门第一季》之面向对象静态内部类和非静态内部类的区别

    很感谢在内部类章节,"开心阳"先生给与的建议.使用静态内部类.这里就简单说一下静态内部类的使用. package com.devin; public class MyMain{ p ...