iOS 复杂屏幕截屏(如webView wkwebView)

栏目: IOS · 发布时间: 6年前

### 写在前面

```

最近有这么一个需求,分享页面,分享的是web订单截图,既然是web 就会有超出屏幕的部分,

生成的图片还要加上我们的二维码,这就涉及到图片的合成了。

有了这样的需求,就是各种google.也算解决了自己的需求,另外,也总结了一下,对需求做了下拓展,目前是swift4.0版本。

```

***

整合成一个三方库,以下只是部分代码,详细代码及demo请见,[github地址](https://github.com/dudongge/DDGScreenShot)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一下,增加我更新的动力

```

欢迎查看[DDGScreenShot](https://github.com/dudongge/DDGScreenShot)

### 其余功能如下

1. [(一)DDGScreenShot  — 复杂屏幕截屏(如view ScrollView webView wkwebView)](https://www.jianshu.com/p/058ff2c51851)

2. [(二)DDGScreenShot--iOS 图片处理--多图片拼接](https://www.jianshu.com/p/4d76cb9848b5)

3. [(三)DDGScreenShot--iOS 图片裁剪,切圆角,加边框,你还用cornerRadius,还有更高级的用法](https://www.jianshu.com/p/3bcba21246c1)

4. [(四)DDGScreenShot—图片擦除功能](https://www.jianshu.com/p/a2359e6cc69d)

5. [(五)DDGScreenShot—截取图片的任意部分](https://www.jianshu.com/p/3a70b437a479)

6. [(六)DDGScreenShot —图片加各种滤镜高逼格操作](https://www.jianshu.com/p/d61182d9a6a6)

7. [(七)DDGScreenShot —图片加高斯模糊,老电影效果](https://www.jianshu.com/p/9d2c62bf4be8)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

产品的视角:从热闹到门道

产品的视角:从热闹到门道

后显慧 / 机械工业出版社 / 2016-1-1 / 69.00

本书在创造性的提出互联网产品定义的基础上,为读者提供了一个从0基础到产品操盘手的产品思维培养方法! 全书以互联网产品定义为基础,提出了产品思维学习的RAC模型,通过认识产品、还原产品和创造产品三个阶段去培养产品思维和产品认知。 通过大量的图片和视觉引导的方法,作者像零基础的用户深入浅出的描绘了一条产品经理的自我修养路径,并且提供了知识地图(knowledge map)和阅读雷达等工具,......一起来看看 《产品的视角:从热闹到门道》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具