アスペクト比を保ったまま画像を中央寄せ 拡大縮小をするWKWebViewのExtension


はじめに

こんにちは
画像をWKWebViewにて、コンテンツを中央寄せ,拡大縮小する表示をしたくなりましたが、実装について少し悩んだので書いて見たいと思います。
※サンプル画像

求める挙動について

表示領域(WKWebView)がそれぞれの時、中の画像は枠に合わせて拡大されます。
UIImageViewAspect Fitのような動作です。

ソースコード

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8'>
  <style type='text/css'>
    * {
        margin: 0;
        padding: 0;
    }
    html, body, div, img {
        width: 100vw;
        height: 100vh;
    }
    div {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    img {
        object-fit: contain;
        background-color: lightgray;
    }
  </style>
</head>
<body>
  <div><img src='https://qiita-image-store.s3.amazonaws.com/0/128250/39dd69dc-0c04-5de2-4e36-e6937c82c5ca.jpeg'></div>
</body>
</html>

WKWebView Extension

WKWebViewExt.swift
import WebKit

extension WKWebView {
    /**
     png画像, jpeg画像, gif画像をURLからロードします
     各画像はAspectFitで表示されます.
     - parameters:
        - url: ロードするアセットURL
        - imageBackgroundColor: 画像と枠の間のマージンがあった場合の背景色
     */
    func setImageBy(url: URL, imageBackgroundColor: UIColor = UIColor.white) {
        let html = "<!DOCTYPE html><html><head><meta charset='utf-8'><style type='text/css'>* {margin: 0;padding: 0;}html, body, div, img {height: 100vh;width: 100vw;}div {display: flex;align-items: center;justify-content: center;}img {object-fit: contain;background-color: #\(imageBackgroundColor.hex);}</style></head><body><div><img src='\(url.absoluteString)'></div></body></html>"
        loadHTMLString(html, baseURL: nil)
    }
}

extension UIColor {
    var hex: String {
        var r: CGFloat = 0
        var g: CGFloat = 0
        var b: CGFloat = 0
        var a: CGFloat = 0

        getRed(&r, green: &g, blue: &b, alpha: &a)

        let rgb = (Int)(r*255) << 16 | (Int)(g*255) << 8 | (Int)(b*255) << 0

        return String(format: "%06x", rgb)
    }
}

使い方

WKWebView表示領域からUIImageViewのAspectFitのように画像が表示されます。

MainViewController.swift
import UIKit
import WebKit

class MainViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // WKWebViewの作成
        let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 200, height: 300))
        //スクロールを拒否
        webView.scrollView.isScrollEnabled = false
        // borderをつける
        webView.layer.borderColor = UIColor.black.cgColor
        webView.layer.borderWidth = 1
        //URLから画像を設定
        webView.setImageBy(url: URL(string: "https://qiita-image-store.s3.amazonaws.com/0/128250/39dd69dc-0c04-5de2-4e36-e6937c82c5ca.jpeg")!, imageBackgroundColor: UIColor.lightGray)
        self.view.addSubview(webView)
        //センタリング
        webView.center = self.view.center
    }
}

気になったところ

vw vh を利用しないと画像が全て表示されない問題

WKWebViewだと、htmlをvwvhで指定しないとうまく表示されません。
HTMLを以下に設定

html, body, div, img {
    width: 100%;
    height: 100%;
}

WKWebViewと画像の間に謎の余白ができてしまう問題

これは、スクロールしなければ見た目上問題ないのですが、どうしても余白ができてしまいます。

webView.scrollView.isScrollEnabled = false

スクロールをOFFして、対応します。

参考にさせていただいた記事