0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SwiftUIでアプリ内のhtmlファイルを表示してJavaScriptでカメラを利用する方法

Last updated at Posted at 2024-09-18

SwiftUIでアプリ内のhtmlファイルを表示して、さらにJavaScriptでカメラを利用するための作業メモです。

htmlファイルをXcodeに取り込み

1 Xcodeでプロジェクトを作成します。
2 表示したいhtmlや画像の入っているフォルダをプロジェクトにドラッグ&ドロップします。
3 Added folder オプションが表示されます。
スクリーンショット 2024-09-09 8.18.06.png

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にプログラムを記入

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ファイルに表示して、アプリにできます。

カメラ画像を表示できるコード

 完成したコードはこちら

ContentView.swift
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

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?