質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1385閲覧

wkwebviewの全体のスクリーンショットが撮れない

退会済みユーザー

退会済みユーザー

総合スコア0

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/10/02 04:21

編集2018/10/02 04:27

iPoneの標準機能と似たような機能を作成したいと考えております。
スクリーンショットを撮ったことを検知して、webView全体をimageViewに表示し、これをタップした際に保存するといった処理をしたいのですが、webview全体を取得できず、以下の画像のようになってしまいました。
原因がわからないので、何かアドバイスいただけると助かります。

また以下のメソッドを使ってもうまくいきませんでした。
https://developer.apple.com/documentation/webkit/wkwebview/2873260-takesnapshot

ソースコードを以下に示します。

swift

1// 2// ViewController.swift 3// ScreenShotSample 4// 5 6import UIKit 7import WebKit 8 9class ViewController: UIViewController { 10 11 @IBOutlet weak var sampleWebView: WKWebView! 12 @IBOutlet weak var screenShot: UIImageView! 13 let homeUrl = "https://qiita.com/trend" 14 15 override func viewDidLoad() { 16 super.viewDidLoad() 17 18 openUrl(urlString: homeUrl) 19 NotificationCenter.default.addObserver(self, 20 selector: #selector(ViewController.didTakeScreenshot(notification:)), 21 name: UIApplication.userDidTakeScreenshotNotification, 22 object: nil) 23 } 24 25 deinit { 26 NotificationCenter.default.removeObserver(self) 27 } 28 29 // UIApplicationUserDidTakeScreenshot の通知を受けて実行される 30 @objc func didTakeScreenshot(notification: Notification) { 31 print("shot") 32 print(sampleWebView.scrollView.contentSize.height) 33 print(sampleWebView.scrollView.contentSize.width) 34 let image = sampleWebView.GetImage() 35 print(image) 36 screenShot.image = image 37 screenShot.isUserInteractionEnabled = true 38 screenShot.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.saveImage(_:)))) 39 } 40 41 42 func openUrl(urlString: String){ 43 let url = URL(string: urlString) 44 let urlRequest = URLRequest(url: url!) 45 sampleWebView.load(urlRequest) 46 } 47 48 @objc func saveImage(_ sender: UITapGestureRecognizer) { 49 50 // クリックした UIImageView を取得 51 let targetImageView = sender.view! as! UIImageView 52 53 // その中の UIImage を取得 54 let targetImage = targetImageView.image! 55 56 // UIImage の画像をカメラロールに画像を保存 57// UIImageWriteToSavedPhotosAlbum(targetImage, self) 58 UIImageWriteToSavedPhotosAlbum(targetImage, self, nil, nil) 59 } 60} 61 62extension WKWebView { 63 func GetImage() -> UIImage{ 64 65 // キャプチャする範囲を取得. 66 let size = CGSize(width: self.scrollView.contentSize.width, height: self.scrollView.contentSize.height) 67 68 // ビットマップ画像のcontextを作成. 69 UIGraphicsBeginImageContextWithOptions(size, false, 0.0) 70 let context: CGContext = UIGraphicsGetCurrentContext()! 71 72 // 対象のview内の描画をcontextに複写する. 73 self.layer.render(in: context) 74 75 // 現在のcontextのビットマップをUIImageとして取得. 76 let capturedImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()! 77 78 // contextを閉じる. 79 UIGraphicsEndImageContext() 80 81 return capturedImage 82 } 83} 84 85

以下のように途切れてしまいます

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

あくまでviewとして見えている部分のレンダリングしかしてくれないので、html全体を画像をして保存したいのであれば
webView自体もそのサイズにする必要があります。
ちょっと試したところだと、autolayoutで上と左と右は画面ピタリにして、下だけ画面から500ほど飛び出すような指定をすると縦長の画像が撮れました。

ただ、そのようなレイアウトにすると一番下までスクロールできなくなるような弊害があるので、画面上見せるビューはそのままにして、全体スクリーンショットを撮る用のwebViewをhtmlのサイズと合うように作ってあげてurlを読み込ませて画像を作ってあげると良いと思います。(スクショ用のwebViewは表示せずに裏で持ってるだけのようなイメージ)
(contentSizeからhtmlのサイズ自体は取れてそうなので多分問題になりそうなところはないはず?)

具体的なコードを書いていく中で、わからない部分が出てきましたらコメントください。

=======回答追記

真っ白なが画像が撮れてしまう事象について少し確認してみました。
まず、iPhone SimulatorのiPhone XRで確認してみたところ、スクリーンショットが撮れました。
そこで実機のみで起こる事象かと考えて、iPhoneXの実機で確認したところ真っ白な画像になってしまいました。

もしかしたらサイズが大きいことが原因か?と考えて確認したところ、iPhoneX実機だと高さ2800はスクリーンショットが撮れ、2900だと白くなってしまうことを確認しました。(https://qiita.com/trendのself.sampleWebView.scrollView.contentSize.heightは5149でした。)

takeSnapshotの限界値があるのか?(高さ?サイズ?imageは返ってきていてerrorにはなってないからここは問題ない?imageの内容をimageViewに貼り付けて確認するとか。ここで白い画像が返ってきちゃっているなら、当初のfunc GetImage()のような取得の仕方だといけるかなどみてみる。)

UIImageWriteToSavedPhotosAlbumの問題なのか?(こちらも高さ?サイズ?の限界値があるかどうか?)

また、端末によっても限界値が違っているのかもしれません?(実機iPhone XRならいける?)

とりあえず、ざっと確認した内容を書かせていただきました。
詳しい内容までは調べていないのでさらに問題が起きそうで解決できなさそうであればコメントor質問ください。
(上記試してみて解決できそうであれば問題なし。そもそも仕様上無理なら分割して保存するとか?デフォルトアプリとかでできてるならできるのかも。高いのは無理と制限を設けて実装するでも良いのであれば良しとか)

投稿2018/10/02 06:37

編集2018/10/04 06:02
razuma

総合スコア1313

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/10/02 07:13

回答ありがとうございます。 とてもよくわかりました。一度挑戦してみます。
退会済みユーザー

退会済みユーザー

2018/10/03 10:10 編集

別のwebviewを作成すると再びurlをロードしなくてはいけないので、既存のwkwebviewをresizeして全画面のスクリーンショットを撮りたいのですが、 sampleWebView.frame = CGRect(x: 0, y: 0, width: defaultWidth, height: sampleWebView.scrollView.contentSize.height) sampleWebView.layoutIfNeeded() _ = self.sampleWebView.takeSnapshot(with: nil) { (image, error) in UIImageWriteToSavedPhotosAlbum(image!, self, nil, nil) } このようにして写真を保存したいと考えております。ですが真っ白なが画像が撮れてしまうので、アドバイスいただきたいです。
退会済みユーザー

退会済みユーザー

2018/10/05 17:10

回答追記ありがとうございます。頂いたアドバイス参考にさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問