SwiftUIでアプリ内のhtmlファイルを表示して、さらにJavaScriptでカメラを利用するための作業メモです。
htmlファイルをXcodeに取り込み
1 Xcodeでプロジェクトを作成します。
2 表示したいhtmlや画像の入っているフォルダをプロジェクトにドラッグ&ドロップします。
3 Added folder オプションが表示されます。
4 ここで「Create folder reference」を選択してから「Finish」ボタンを押します。
5 htmlのフォルダが追加されます。これで内部htmlファイルとして利用できます。
Added folder オプションの違いについて、詳しくはこちらのサイトを参照願います。
https://qiita.com/OSR108/items/c0bbe020662acc415ddb
アプリ内htmlファイルの表示
こちらのサイトの内容をほぼそのまま利用しました。解説を公開していただいていることに感謝いたします。
https://note.com/npaka/n/n3acc1e1b8036
https://qiita.com/kamimi01/items/9cefe1e73ab5b88051c6
ContentView.swiftにプログラムを記入
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
@Binding var assetName: String
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
let fileName = NSString(string: assetName)
let pathPrefix = fileName.deletingPathExtension
let pathExtension = fileName.pathExtension
if pathPrefix.isEmpty || pathExtension.isEmpty {
return
}
if let url = Bundle.main.url(forResource: pathPrefix, withExtension: pathExtension) {
uiView.loadFileURL(url, allowingReadAccessTo: url)
}
}
}
struct ContentView: View {
@State private var isShownLocalAsset = true
@State private var shownAssetName = "html/index.html"
var body: some View {
VStack {
Spacer()
}
.fullScreenCover(isPresented: $isShownLocalAsset) {
WebView(assetName: $shownAssetName)
}
}
}
これでhtmlファイルを表示できます。
shownAssetName = "html/index.html"
この値はXcodeに取り込んだフォルダ名や表示したいhtmlファイルに従って変更してください。値を「https://qiita.com」に変更すると、「Qiita」を表示するアプリができます。
アプリとして使うための微調整
WKWebViewを利用してhtmlファイルを表示した場合、次のような特徴があります。
〇アドレスが表示されません
内部htmlを利用するので、これでOKです。
〇「<」もどるボタンが表示されません
内部htmlを利用するので、これもOKと考えます。
〇アンカーリンク(aタグ)でリンク先のページを表示します
×リンクがtarget=”_blank”(ターゲットブランク)が指定されている場合には表示されません。
→ 別ウィンドウ、別タブの表示ができません。
→ 「こういうもの」という基本で内部htmlファイルを作成しましょう。
→ 外部サイト(https)のurlを記入すれば、そのサイトを開くことができます。
※ httpサイトの場合には、info.plistに許可の追加が必要となります。
〇画面より表示が長い場合、スクロールバーが表示されます
→ 表示長が画面内に収まっているとき、タッチして上下をすると、画面がビヨーンと移動(バウンス)します。これを防ぐには、htmlファイルのcssでスクロール禁止にします。
html {
overflow: hidden;
}
〇2本指で拡大縮小(ピンチイン、アウト)ができます
拡大縮小を禁止したい場合には、htmlファイルで設定します。
<meta content="user-scalable = no">
このタグを記入すると、ページが拡大縮小できないようになります。
〇Javascriptでカメラを利用してhtmlに表示したいときには
info.plistに「Privacy – Camera Usage Description」を追加して「アプリでカメラを利用します」と理由を記入します。
→ しかし、初めの1枚は撮影しますが、Javascriptの作動が止まります。作動していますが、画面表示が更新されません。
→ 解決方法がありました。Qiitaはありがたいですね。
https://qiita.com/tomi2518/items/a093dd1a30b26ef62f69
func makeUIView(context: Context) -> WKWebView {
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true // インライン再生を許可
config.mediaTypesRequiringUserActionForPlayback = [] // すべてのメディアの自動再生を許可
return WKWebView(frame: .zero, configuration: config)
}
これで、Javascriptでカメラを画像をhtmlファイルに表示して、アプリにできます。
カメラ画像を表示できるコード
完成したコードはこちら
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
@Binding var assetName: String
func makeUIView(context: Context) -> WKWebView {
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true // インライン再生を許可
config.mediaTypesRequiringUserActionForPlayback = [] // すべてのメディアの自動再生を許可
return WKWebView(frame: .zero, configuration: config)
}
func updateUIView(_ uiView: WKWebView, context: Context) {
let fileName = NSString(string: assetName)
let pathPrefix = fileName.deletingPathExtension
let pathExtension = fileName.pathExtension
if pathPrefix.isEmpty || pathExtension.isEmpty {
return
}
if let url = Bundle.main.url(forResource: pathPrefix, withExtension: pathExtension) {
uiView.loadFileURL(url, allowingReadAccessTo: url)
}
}
}
struct ContentView: View {
@State private var isShownLocalAsset = true
@State private var shownAssetName = "html/index.html"
var body: some View {
VStack {
Spacer()
}
.fullScreenCover(isPresented: $isShownLocalAsset) {
WebView(assetName: $shownAssetName)
}
}
}
最後に
表示幅、文字の大きさなどは実機で確認する必要がありますが、htmlで記載しているのでアプリ作成が容易になると思います。
enchant.jsで記載したhtmlページを入れて動かしてみました。問題なく作動しました。過去の作品を手直しして公開したいと考えています。
kotlinでアプリ内のhtmlファイルを表示する方法は?
Android SudioのKotlinでアプリ内のhtmlファイルを表示してJavaScriptでカメラを利用する方法はこちらをご覧ください。
https://qiita.com/mvm43236/items/7de8906a8ea80ba00603