寫在前面
最近有這么一個(gè)需求意蛀,分享頁(yè)面,分享的是web訂單截圖健芭,既然是web 就會(huì)有超出屏幕的部分县钥,
生成的圖片還要加上我們的二維碼,這就涉及到圖片的合成了慈迈。
有了這樣的需求若贮,就是各種google.也算解決了自己的需求,另外痒留,也總結(jié)了一下谴麦,對(duì)需求做了下拓展,目前是swift4.0版本伸头。
整合成一個(gè)三方庫(kù)匾效,以下只是部分代碼,詳細(xì)代碼及demo請(qǐng)見(jiàn)恤磷,github地址https://github.com/dudongge/DDGScreenShot
DDGScreenShot 部分功能演示
View生成圖片
代碼也比較簡(jiǎn)單 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生成圖片
只要實(shí)現(xiàn)原理是計(jì)算偏移量面哼,每一屏繪制一次,放在內(nèi)存里扫步,最后將所有的圖片組合成一張圖片 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
繪制時(shí)大同小異魔策,只是wkwebView 調(diào)用的繪制方法為:drawHierarchy 其核心代碼如下
采用遞歸,直到拿到最后一個(gè)偏移量河胎。
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的圖大小為畫布創(chuàng)建上下文
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()
//從當(dāng)前上下文中獲得最終圖片
UIGraphicsEndImageContext()
return resultImg!
在圖片上寫文字/加標(biāo)簽
同樣對(duì)UIimage 做了拓展,增加了幾個(gè)參數(shù)
public func drawTextInImage(text: String,
textColor: UIColor,
textFont: CGFloat,
textBgColor: UIColor,
textX: CGFloat,
textY: CGFloat )->UIImage {
//開(kāi)啟圖片上下文
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)
//從當(dāng)前上下文獲取圖片
let image = UIGraphicsGetImageFromCurrentImageContext()
//關(guān)閉上下文
UIGraphicsEndImageContext()
return image!
}
結(jié)束語(yǔ)
空間有限仿粹,所注代碼不全搁吓,我把上述功能整理成了最新的帶三方庫(kù),
以后會(huì)加上圖片的相關(guān)處理吭历,比如美顏堕仔,剪切,馬賽克晌区,組圖等摩骨,
附上我的git地址:https://github.com/dudongge/DDGScreenShot
有什么問(wèn)題也可以聯(lián)系我QQ:532835032
如果對(duì)您有幫助,請(qǐng)您不吝star一下朗若,增加我更新的動(dòng)力
附上github上READER.ME文件部分內(nèi)容
## view截屏:
view.DDGScreenShot { (image) in
拿到 image
各種復(fù)雜裝逼操作
恼五、、哭懈、灾馒、
}
## ScrollView截屏:
scrollView.DDGContentScrollScreenShot { (image) in
拿到 image
各種復(fù)雜裝逼操作
、遣总、睬罗、轨功、
}
## webView截屏:
webView.DDGContentscreenShot { (image) in
拿到 image
各種復(fù)雜裝逼操作
、容达、古涧、、
}
## wkwebView截屏: 方法和webView 一樣花盐,內(nèi)部做了校驗(yàn)
webView.DDGContentscreenShot { (image) in
拿到 image
各種復(fù)雜裝逼操作
羡滑、、算芯、柒昏、
}
## image 加 logo
let image = image.composeImageWithLogo( logo: UIImage,
logoOrigin: CGPoint,
logoSize:CGSize)
傳入 logo圖片,logo位置 logo 大小 就可以得到一張生成好的圖片
也祠、昙楚、近速、诈嘿、
## image 加 標(biāo)簽,水印削葱,文字
let image = image.drawTextInImage(text: String,
textColor: UIColor,
textFont: CGFloat,
textBgColor: UIColor,
textX: CGFloat,
textY: CGFloat )
傳入 文字奖亚、文字顏色、字體大小析砸、背景顏色昔字,字體起始位置 就可以得到一張生成好的帶標(biāo)簽的圖片
、首繁、作郭、、
注弦疮,此方法在提交pod有問(wèn)題夹攒,故將方法屏蔽,有需要的可以拷貝代碼胁塞,到本地
## 使用pod
iOS 9.0+, Swift 4.0+(Compatiable)
使用pod 導(dǎo)入
pod 'DDGScreenShot', '~> 1.0.1'
```
歡迎查看DDGScreenShot