この投稿では、HTMLでmacOSのオリジナルのスクリーンセーバを作れる方法を紹介します。
macOSのスクリーンセーバを作ってみたいけど、SwiftもObjective-Cも分からない、分かるのはHTMLやCSS、JavaScriptなどウェブ関連技術だけ、というウェブ系プログラマむけの解説です。
ちなみに僕は、この投稿で紹介する方法で、JavaScriptの人気ライブラリをひたすら紹介するスクリーンセーバを作りました:
JavaScriptの人気ライブラリを紹介しまくるスクリーンセーバが完成した😌
— suin❄️TypeScript入門書執筆中 (@suin) April 30, 2020
需要があれば公開するかも pic.twitter.com/tOnUhMIbh8
Swiftなどを知らなくても、CSSやJavaScriptでアニメーションを頑張れば、こういった動きのあるスクリーンセーバが作れるわけです。
スクリーンセーバをHTMLで作る手順
Xcodeで新規プロジェクトを作る
まず最初に、スクリーンセーバのプロジェクトの下準備をしていきます。
Xcodeを起動して、新規プロジェクトを作ります。
その際、「Screen Saver」のテンプレートを選びます:
「Product Name」「Organization Name」「Organization Identifier」は適当に:
Swiftの接着剤コードを準備する
macOSは標準でHTMLだけでスクリーンセーバが作れるわけではないので、HTMLをスクリーンセーバ上に描画するためのコードは、Swiftで書いておく必要があります。
ここでは、スクリーンセーバとHTMLの接着剤となるSwiftのコードを用意する手順を説明していきます。
まず、先程新規作成したプロジェクトから、不要なObjective-Cのファイルを消します:
代わりに、消したファイルと同じファイル名 + .swift
で空のファイルを作ります。「MyScreenSaver」を右クリックして「New File」をクリックします。
ファイル形式は「Swift File」にします:
ファイル名は「MyScreenSaverView.swift」にします:
作成時に↓と聞かれますが、「Don't Create」を選びます:
Swiftファイルが作成されたら、デフォルトで入っているコードは消し、下記コードをコピペして上書き保存します:
importScreenSaverimportWebKitclassMyScreenSaverView:ScreenSaverView,WKNavigationDelegate{privatevarwebView:WKWebView!convenienceinit(){self.init(frame:.zero,isPreview:false)}overrideinit!(frame:NSRect,isPreview:Bool){super.init(frame:frame,isPreview:isPreview)setupWebView()}requiredpublicinit?(coder:NSCoder){super.init(coder:coder)setupWebView()}privatefuncsetupWebView(){letwebConfiguration=WKWebViewConfiguration()// webkitがローカルファイルを参照できるようにする設定webConfiguration.preferences.setValue(true,forKey:"allowFileAccessFromFileURLs")// webViewをスクリーンの大きさに合わせるwebView=WKWebView(frame:NSRect(x:0,y:0,width:frame.width,height:frame.height),configuration:webConfiguration)webView.navigationDelegate=self// webViewの背景を透明にするwebView.setValue(false,forKey:"drawsBackground")// スワイプでの戻る/進むを無効にするwebView.allowsBackForwardNavigationGestures=false// ピンチで拡大/縮小できる機能を無効にするwebView.allowsMagnification=false// ローカルのHTMLを読み込むiflethtmlPath=Bundle(for:type(of:self)).path(forResource:"html",ofType:nil){lethtmlUrl=URL(fileURLWithPath:htmlPath,isDirectory:true)letindexUrl=URL(fileURLWithPath:htmlPath+"/index.html",isDirectory:false)webView.loadFileURL(indexUrl,allowingReadAccessTo:htmlUrl)}}funcwebView(_webView:WKWebView,didFinishnavigation:WKNavigation!){// ページが遷移したタイミングでwebViewをスクリーンセーバに表示するself.addSubview(webView)}// マウスが動いたときにスクリーンセーバが解除されるようにする(その1)overridefunchitTest(_aPoint:NSPoint)->NSView?{self}// マウスが動いたときにスクリーンセーバが解除されるようにする(その2)overridevaracceptsFirstResponder:Bool{true}}
このSwiftコードが何をしているか簡単に説明すると、スクリーンセーバが起動したらWebView(埋め込み版のSafariのようなもの)を起動し、html/index.html
を読み込み、それをスクリーンセーバ上に表示するといった処理が書かれています。
Swift側の準備は以上です。
HTMLファイルを作る
次に、スクリーンセーバのグラフィックデザインを実装していく場所であるindex.html
を作っていきます。
まず、html
フォルダを作りたいので、「MyScreenSaver」フォルダを右クリックして「Add Files to "MyScreenSaver"」をクリックします:
すると、Finderのダイアログが出てくるので、「New Folder」をクリックし、「html」フォルダを作ったら「Add」をクリックして閉じます。
次に、index.htmlを作るために、htmlフォルダを右クリック、メニューから「New File」を選びます:
「File」というファイルが作られるので、「index.html」に名前を変えておきます。
index.htmlの中身は適当に何か書いておきます:
<style>h1{color:black;background:white;font-size:30vh;animation:blink1sstep-endinfinite;}@keyframesblink{75%{opacity:0.0;}}</style><h1>Hello World</h1>
以上でHTMLファイルの準備は完了です。
スクリーンセーバを実行できるように設定する
続いて、スクリーンセーバを実行するための設定をしていきます。
Xcodeのメニューバーにある「MyScreenSaver」をクリックするとメニューが出るので、そこから「Edit Scheme」を選びます:
「Run」の「Info」タブの「Executable」セレクトメニューから「Other」を選び、ScreenSaverEngine.appに設定します:
ScreenSaverEngine.appは/System/Library/CoreServices/ScreenSaverEngine.app
にあります。macOSのバージョンによって、ありかが異なる場合があります。
次に、「Arguments」タブを開き、
-window
-module "$(EXECUTABLE_NAME)"
の引数設定を追加します:
更に、実行ごとにスクリーンセーバを自動的にインストールするように設定します:
open -W "${CODESIGNING_FOLDER_PATH}"
以上で、スクリーンセーバを実行するための設定は完了です。
スクリーンセーバを実行してみる
準備が整ったので、スクリーンセーバを実行してみましょう。
スクリーンセーバを実行するには、Command+Rを押すか、XcodeのRunボタン(▶アイコン)を押します。
実行が開始すると、設定アプリが立ち上がり、スクリーンセーバをインストールするか聞かれるので「Install」を選択します:
すると、スクリーンセーバがインストールされ、スクリーンセーバの選択画面にプレビューが表示されるようになります。
この状態で、設定アプリを閉じると、今度はスクリーンセーバを確認するためのウィンドウが表示されます:
index.htmlに書いた内容が表示されるはずです。
あとは、index.htmlを作り込んでいくと、オリジナルのスクリーンセーバが作れます。
ちなみに、実行したときに、インストールされたスクリーンセーバは、実行が終了しても残るので、設定アプリで自分が作ったスクリーンセーバを選択しておけば、Xcodeを閉じてもそのスクリーンセーバが使われるようになります。
Safariを使った動作確認がおすすめ
HTMLを直してはXcodeの「Run」でスクリーンセーバをインストールし直して確認する、というのは開発体験としてかったるいので、HTML側ごりごり書いていくときはSafariで動作確認するのをおすすめします。Safariを使うと、ウェブインスペクタも使えるのでデバッグがはかどります。
ChromeやFirefoxではなくSafariを使う理由は、Swiftのコードで使っているWKWebView
が他ブラウザの環境よりSafariに近いからです。
普段、Swiftを書かない人は、Xcodeも慣れていないと思うので、HTMLをいじるときはVSCodeなど自分の好きなエディタを使ってもいいです。
Safariで動作確認するときは、html/inde.html
を開くだけです。HTMLを直したら、リロードする。普段のウェブアプリの開発と同じ要領です。
スクリーンセーバの作りにもよりますが、fetch()
などで外部APIを叩いたりするときは、Same Origin Policyにひっかかってしまうことがあります。その場合は、Safariの「Devloper」→「Disable Cross-Origin Restrictions」をオンにしておくと良いです:
また、フルスクリーンでの動作確認をするときは、「View」→「Always Show Toolbar in Full Screen」のチェックを外しておくと良いです:
おわり
macOSのスクリーンセーバを作るのに、Swiftの知識はほぼ不要です。
慣れ親しんだHTMLやJavaScriptを駆使して、自分だけのスクリーンセーバを作ってみてはいかがでしょうか。
最後までお読みくださりありがとうございました。Twitterでは、Qiitaに書かない技術ネタなどもツイートしているので、よかったらフォローしてもらえると嬉しいです→Twitter@suin