見出し画像

Day 5: Googleマップを夜になったら自動的にダークモードにする

My Ideal Map App という、Googleマップのユーザー体験を改善するウェブアプリを制作している(詳しくは Day 1 を参照)。

改善点の一つとして、夜になったら地図の配色が自動的にダークモードに変わるようにしたい。

GoogleマップのiOS/Androidアプリは、ダークモードに設定できるが、夜の間だけ自動的にダークモードになるようには設定できない。日中に外を歩いているときにダークモードの地図を見るのは、違和感があるし、スクリーンが全体的に暗くなるので周りが明るい中では見えにくい。かといって、太陽が出ているかどうかでいちいち設定を変えるのは面倒くさい。

日が暮れるころにダークモードに変えるのは、スマホの電池残量の観点からも好ましい。日中に出歩いた後は、電池残量が少なくなっている。有機EL(英語では"OLED")スクリーンのスマホ(iPhone X, 11, 12など)ならば、ダークモードによって電池消費量を減らすことができる(理由については Purdy 2019 を、証拠については PhoneBuff 2019 を参照)。

もう一つの利点は、ダークモードによって目に入る「ブルーライト」の量を減らせること。ブルーライトは、メラトニンという眠気をもたらすホルモンの分泌を抑制する(科学的根拠については、Harvard Health Publishing 2020を参照)。夜、就寝まで数時間の時に、アプリが自動的にダークモードになるようにすれば、日が暮れることで自然にメラトニンが分泌されて眠くなるプロセスが阻害されずに済む。

(ちなみに、ブルーライトによって目が疲れやすくなる、という通説は科学的根拠がないらしい(メディカルプライム神田 2021)。)

---

もちろん、最善のUXデザインは、ユーザーがダークモードにするかどうか自分の好みで設定できるようにする(Babich 2019 参照)ことだが、デフォルトの設定は、アプリ制作者がユーザーにとってベストだと思うものにするべきだ。

では、どうやってwebアプリに埋め込んだGoogleマップを、時刻によって自動的にダークモードにするのか。私が色々学んだ結果として実行したことを、デザインとプログラミングの両方について、以下に記す。

Googleマップのダークモードをカスタム設定する

まずは、Googleマップのダークモード用の配色を設定する。

前回の記事で記した通り、アプリに埋め込むGoogleマップの配色をカスタム設定するには、Google Maps Platform ウェブサイト上で行うのがベスト。

そして、配色をカスタム設定するには、まず Feature type (道路、水域、お店など)、次に Element type (形についてなのか、ラベルについてなのか)、最後に Stylers (色)を設定する。

画像1


Google Maps Platform の配色カスタム設定画面(筆者によるスクリーンショット)

具体的には、以下の7つのステップを通して設定した。

#1: 白黒表示にする

まず、地図全体を白黒表示にする。

Feature type: All
Element type: All
Stylers > Saturation: -100

画像2

Saturation を -100 に設定した、京都中心部の地図(筆者によるスクリーンショット)

白黒表示にすることで、個別の地図要素の色の設定が容易になる。色が変わったところがすぐにわかり、思った通りの色になったかどうかが容易にチェックできるから。また、重要ではない地図要素の色をわざわざ設定する必要がなくなる。

---

全体を白黒表示にしたら、色が暗い順番に配色していく。ライトモードの配色(前回の記事を参照)をした時は、色が明るい順から配色していったが、ダークモードでそれをやってしまうと、真っ黒よりも暗い色が必要になる事態(笑)を招くリスクがあるから。

ライトモードでは、道路、緑地、水域、市街地の順に、明度を低くしていった(その理由については、前回の記事を参照)。ダークモードでも、この明度の順番を踏襲する。二つの配色の間に、ある程度の一貫性を持たせて、アプリとしての統一性を保つために。

というわけで、一番暗い色の地図要素である市街地から色を設定していく。

2. 市街地

「市街地」とは、街の道路に囲まれた区域のこと。英語で city blocks という表現があるのだけど、日本語での定訳がないので、「市街地」という表現にした。

前回の記事でも書いたように、グーグルマップでは、市街地の色を直接指定することはできない。そこで、以下のように設定する。

Feature type: All
Element type: All
Stylers > Lightness: -77

画像3

Lightness を -77 に設定した、京都中心部の地図(筆者によるスクリーンショット)

Lightness を-77にすることで、市街地の色が #2b2b2b になる。この色にした理由は二つある。

理由1:真っ黒は避けるべき

ウェブデザインにおいては、真っ黒は10年以上前の雰囲気を生んでしまう。個人的には、Facebook にあっと言う間に取って代わられた MySpace を思い出してしまう。私が作る My Ideal Map App は今までにないwebアプリを目指しているので、そのようなレトロな雰囲気はふさわしくない。

また、有機EL(OLED)スクリーン上では、真っ黒は "black smear" (「黒い油っぽい汚れ」) と呼ばれる不快な現象を起こす。ユーザーがスクリーンを指でスクロールさせる速さに、有機ELスクリーンを構成する LED 光源が光を発したり消したりするスピードが追いつかず、真っ黒な部分(光が消えている部分)がブレてしまう(Edwards 2018 などを参照)。

したがって、真っ黒は、スクロールできないウェブページ(例えば、Google検索のトップページ)でのみ使うべき。スクロールがユーザー体験のコアである地図アプリには、全くもってふさわしくない。

理由2:明度が真っ黒の約1.5倍

ではどれぐらい暗い灰色が良いのか?

Google のデザインシステムである Material Design のガイドラインでは、ダークモードでの最も暗い色を #121212 に設定しているが、なぜその灰色なのかについての説明はない。

私としては、真っ黒ではない、とユーザーに認識してほしい。色を区別する最低限の明度差として私が参照するのは、1.5倍という数字。経験上、この値を下回ると、色の差が認識しずらくなる。

真っ黒より明度が1.5倍ほど高い灰色として、#2b2b2b を市街地の色として選んだ。

画像5

contrast-ratio.com のスクリーンショット

3. 水域

川や運河や海や湖などの水域は、以下のように設定した。

Feature type: Water
Element type: Geometry
Stylers > Color: #344d4d

画像5

水域の色を #344d4d に設定した、京都中心部の地図(筆者によるスクリーンショット)

夕方以降、岸辺にカップルが等間隔で座る(笑)ことで有名な鴨川の位置がわかるようになった。

水の色はシアンである(水の分子はシアン以外の色の光を吸収するから)。なので、色相は、HSL色空間で180度に設定する。

明度については、市街地よりも1.5倍明るくすることで、色の違いを認識できるようにする。市街地自体は黒よりも1.5倍明るく設定したので、水域は黒よりも2.25倍(1.5の二乗)明るくなる。

彩度については、純色のシアンを10%、灰色を90%混ぜた色にする(詳しくは、前回の記事の3.3節を参照)。

このような色の選び方を可能にしてくれるのは、私が自作した無料webアプリ、Triangulum Color Picker しかない。結果として選んだ色は、#344d4d となった。

画像6

Triangulum Color Picker のスクリーンショット

4. 緑地

公園や山地などの緑地の色は以下のように設定した。

山地:

Feature type: Landscape > Natural
Element type: Geometry
Stylers > Color: #4c664c

公園:

Feature type: Points of interest > Park
Element type: Geometry
Stylers > Color: #4c664c

画像8

緑地の色を #4c664c に設定した、京都中心部の地図(筆者によるスクリーンショット)

料亭やバーが立ち並ぶ先斗町エリアにポツンと存在する先斗町公園の場所が明らかになった。

緑地の色は、緑地だとすぐわかるように緑色にしたい。なので、色相は、HSL色空間で120度に設定。

明度は、水域の色の1.5倍となるように設定。結果として、市街地の色の2.25倍になるので、それぞれが認識できるようになる。黒との明度差は、3.375倍(1.5の三乗)となる。

彩度は、純色の緑10%と灰色90%を混ぜた色にする。同様に純色10%に設定した水域の色と調和させるため。前回の記事の3.3節に書いた通り、純色の割合が等しい色は調和し、自然界に見られる明暗に似た配色になる。このことを主張した20世紀初頭の化学者 Wilhelm Ostwald が、その理由を説明した文献を見つけることができないのだが(知っていたら是非教えてください)、おそらく、自然界に存在する物体のほとんどは表面が凸凹していて、人間の目に届く反射した太陽光の量が表面の場所によってばらつき、その物体の固有色に様々な明るさの灰色を混ぜた色になる。その様子に我々人間の目が慣れているからだろう。

Triangulum Color Picker を用いて、上記の三条件を満たす色を探すと、#4c664c となった。

画像9

Triangulum Color Picker のスクリーンショット

5. 道路

ダークモードでの道路は暗めのオレンジ色に設定した。

Feature type: Road
Element type: Geometry > Fill
Stylers > Color: #ae6f2f

道路の輪郭線は消す(理由は、前回の記事の4.2節を参照)。

Feature type: Road
Element type: Geometry > Stroke
Stylers > Visibility: Off

画像9

道路の色を #ae6f2f に設定した、京都中心部の地図(筆者によるスクリーンショット)

道路をオレンジ系の色にすることで、夜の街の雰囲気が少し出た。左下の交差点は、Kocchi十一などのストリートミュージシャンがよく出没する四条河原町。

Googleマップのカスタム配色パターンのレポジトリである Snazzy Maps に、Limos Night と名付けられた配色がある。全体的に暗い灰色である中に、道路が焦げ茶色で描かれているのを見て、夜の街っぽいな、と思った。

何故なのか、すぐには気付けなかったのだが、My Ideal Map App のムードボード(Day 3 参照)を作った際に利用したパリの夜景の写真を見たときに理解できた。

画像10

パリ凱旋門付近の航空写真(画像元:不明)

夜のパリは、オレンジ色の街灯に照らされて美しい。焦げ茶色は、オレンジ色を暗くした色。この風景を思い出したから、夜の街っぽいと思ったのだ。

My Ideal Map App のデザインコンセプト(詳しくは Day 2 を参照)は、"Dye Me In Your Hue From The Sky" (「空からあなた色に私を染めて」)。空から見た風景である地図を、関心のある場所を保存していくことで、自分色に染めていく。したがって、地図の配色は、空から見た風景を思い起こさせるものにしたい。まさにこの写真のような風景を。

したがって、道路の色は、色相を HSL 色空間における 30度(オレンジ)に設定。

明度は、緑地の1.5倍、すなわち、水域の2.25倍(1.5の二乗)、すなわち、市街地の3.375倍(1.5の三乗)。結果として、ユーザーがタップするUI要素は隣り合う色との明度差を少なくとも3:1にするべき、というWeb Content Accessibility Guideline (§1.4.11 of WCAG 2.1) を満たすことができる。道路は、ユーザーがタップするUI要素。道をたどるように地図をスクロールさせるには、道路の場所を指で押さえてスワイプする必要があるから。したがって、道路と常に隣り合う市街地との明度差は十分確保する必要がある。

彩度は、純色のオレンジ50%と灰色50%を混ぜた色になるようにする。色々試してみたが、純色の割合が50%以下だと単なる茶色になってしまい、50%以上だと他の色との調和が取れなかった。

Triangulum Color Picker を用いて、上記の三条件を満たす色を探すと、#ae6f2f となった。

画像11

6. 建物

まず、デフォルト設定である3D表示をオフにする(理由は、前回の記事の3.6節を参照)。

Feature type: Landscape > Human-made > Buildings
Element type > Building style: Footprints

そして、建物の輪郭を明るめの灰色にする。

Feature type: Landscape > Human-made > Buildings
Element type: Geometry > Stroke
Stylers > Color: #757575

画像12

建物の輪郭線の色を #757575 に設定した、京都中心部の地図(筆者によるスクリーンショット)

京都の夜の繁華街である先斗町や木屋町に、建物がひしめき合っている様子がよくわかるようになった。

建物全体の色ではなく輪郭線の色だけを指定するのは、地図全体の印象を変えないため。

最初は「建物も窓から光が漏れるから、輪郭線をオレンジにしよう」と短絡的に思い、暗いオレンジ色を試してみたのだが、道路と同じような色合が目立ちすぎ、狭い道との違いもわかりにくくなる。したがって、無彩色のグレーにした。

明度については、最初、市街地のグレーの1.5倍の明るさにしてみたが、建物の輪郭線がはっきり見えなかった。ライトモードの地図の配色デザインでは、明度差1.5倍で問題なかったのだが(前回の記事の4.6節参照)、ダークモードでは基準となる明度が非常に低いため、1.5倍では足りない。

そこで、Web Content Accessibility Guideline (§1.4.11 of WCAG 2.1)にならって、明度3倍にした。市街地の色 #2b2b2b の明度を3倍にした灰色が、#757575だった。

画像13

contrast-ratio.com のスクリーンショット

この辺が、ダークモードの配色デザインが簡単ではない理由だと思う。

7. ラベル

地名などのラベルは、以下のように設定した。

文字自体の色

Feature type: All
Element type: Labels > Text > Text fill
Stylers > Color: #929292

文字の輪郭線

Feature type: All
Element type: Labels > Text > Text outline
Stylers > Color: #2b2b2b

画像14

ラベルの色を #929292、輪郭線の色を#2b2b2bに設定した、京都中心部の地図(筆者によるスクリーンショット)

これでようやく文字が読めるようになった。

Web Content Accessibility Guideline (WCAG 2.1) の 1.4.3 節に、小さい文字は、背景色との明度差を最低4.5倍にするべき、とある。これは、80歳の人の平均的な視力でも文字がはっきり読めるようにするため (Accessibility Guidelines Working Group 2021)。

市街地の色が #2b2b2b なので、これと明度差が4.5倍以上になる無彩色は#929292となる。

画像15

contrast-ratio.com のスクリーンショット

しかし、この灰色は、オレンジ色の道路を背景にすると、明度差が足りない。そこで、文字の輪郭線を、市街地と同じ灰色 #2b2b2b に設定する。すると、市街地を背景とした場合は何も変わらないが、道路を背景とした時は、文字の灰色と隣り合う色との明度差が4.5倍ルールを満たすので、十分に読める。グラフィックデザイナーがよく使う技であり、Mapbox(Google Maps API のライバル)による地図デザインの手引書にも書いてある(Lee, undated, p. 29)。

---

以上でダークモードの配色設定はおしまい。ラベルの表示設定は、ライトモードと同じにした(前回の記事の第4節を参照)。

デザインが完成したら、次はプログラミングの番である。

夜になったらダークモードが表示されるようにする

Googleマップの公式ドキュメントには、配色やラベル表示の設定を自動的に変える方法について、どこにも書いていない。以下は独自に調べて見つけた方法。

1. 前提知識

ウェブページに埋め込んだGoogleマップに、カスタム設定を反映させるには、Google Maps Platform ウェブサイト上で Map ID をカスタム設定内容とリンクさせ、その Map ID を JavaScript コード内で参照すればいい。

私のように React を使ってウェブアプリを作っている場合、以下のようなコードとなる。

map = new google.maps.Map(googlemap.current, {
 center: {lat: 35.011636, lng: 135.768029}, // Kyoto City
 zoom: 17,
 mapId: '4hde5345723cdegs'
}); 

ここで、4hde5345723cdegs という文字列が(架空の)Map ID。googlemap.current という変数は、地図を埋め込む <div> エレメントを指す。

const Map = () => {
 const googlemap = useRef(null);
 ...
 return <div ref={googlemap} />;
};

ここで出てくる useRef()の使い方については、React の公式ドキュメントを参照。

地図の配色をダークモードに変えるには、Map ID の文字列を、ダークモードにリンクさせたものに変更すればいい。その変更が、夜6時から朝6時前までの間のみ、有効になるようにする。

2. ユーザーの現地時間

ユーザーの現地時間をJavaScriptコード上で読み出すには、Date() という関数を使う。

  const currentTime = new Date();

"new Date()" によって、ユーザーの現地時間を UNIX時間(1970年1月1日午前0時から何秒経ったか)で読み出すことができる。この値を、currentTime という変数として表す。

もちろん、UNIX時間では扱いにくいので、24時間表示に直す必要がある。日付や分秒は不要なので、今何時台なのかだけを知るために、.getHours()というメソッドを用いる。

  const currentHour = currentTime.getHours();

24時間表示で今何時台なのかを、currentHour という変数として表す。

この変数の値が、6未満、または、18以上であれば、ユーザーのいる場所では夜6時から朝6時前までの間、ということになる。

 let nightMode;
 if (currentHour < 6 || currentHour >= 18) {
   nightMode = true;
 } else {
   nightMode = false;
 }

6未満または18以上であれば、nightModeという変数が true という値を取り、それ以外の場合は false という値をとるようにする。

なお、理想としては、朝6時・夕方6時ではなく、ユーザーのいる場所の日の出・日の入り時刻を利用したい。数年前まで住んでいたストックホルムのような高緯度にある都市は、夏には夜10時ごろまで明るく、冬には昼3時ごろに暗くなる。

しかし、現時点では、アプリ自体の完成を優先すべきなので、Version 1.0.0 をリリースしてから、日の出・日の入り時刻でダークモードを切り替える仕様に変更する予定。

3. Map ID を時間帯で変更

ここで、最初に説明したGoogleマップの配色設定をするコードに戻り、ternary operator を使って、時間帯によって、Map ID が切り替わるようにする。

const mapIdDaytime = 'fw2s9334gso24ckk';
const mapIdNighttime = '4hde5345723cdegs';

map = new google.maps.Map(googlemap.current, {
 center: {lat: 35.011636, lng: 135.768029}, // Kyoto City
 zoom: 17,
 mapId: nightMode ? mapIdNighttime : mapIdDaytime
}); 

変数 nightMode が true の値を取るなら、mapIdNighttime の値として設定したダークモード用の Map ID、そうでなければ、ライトモード用の Map ID になる(なお、コードに用いた Map ID の文字列は、架空のもの)。

ここで、最後のところを

mapId: nightMode ? '4hde5345723cdegs' : 'fw2s9334gso24ckk'

と書いてしまうと、望み通りの結果にはなるのだが、後日このコードを見たときに何が何だか分からなくなる。

対処法としては、以下のようにコメントを記入して説明書きとする方法がある。

 mapId: nightMode ? '4hde5345723cdegs' : 'fw2s9334gso24ckk'
 // '4hde5345723cdegs' is map ID for nighttime mode 
 // 'fw2s9334gso24ckk' for daytime mode

しかし、この方法はまずい。将来 Map ID の文字列を変更する必要が生まれた場合、このコメントを修正するインセンティブがどこにもない。修正しなくてもコードはエラーを出すことなく思った通りに実行されてしまうからだ。そうなると、間違ったコメントのせいで余計にわかりにくいコードになってしまう。

その代わりとして、コメントではなく、コードの一部である変数の名前を説明書きとして利用する。

const mapIdDaytime = 'fw2s9334gso24ckk';
const mapIdNighttime = '4hde5345723cdegs';
...
mapId: nightMode ? mapIdNighttime : mapIdDaytime

こうすれば、実行されるコードを読むだけで、何をしようとしているのかがすぐにわかる。そして、Map ID を変更する必要があれば、この部分自体を変更する必要があるので、「説明書き」を変更し忘れることもない。

このプログラミングのテクニックは、前職で社会科学分野のデータサイエンティストをしているときに、経済学での第一線のデータサイエンティストである Matthew Gentzkow と Jesse M. Shapiro が2014年に書いたメモ(Gentzkow and Shapiro 2014)を読んで学んだ。

今はデータ分析ではなくウェブ制作のためにプログラミングをする日々だが、このメモから学んだことは今も役立っている。

デモ

以上、この記事で説明したコードを用いたデモを、Cloudflare Page を用いてウェブ上にアップした。クリックすると、もし、あなたのいる場所の現地時間が夜6:00から朝5:59の間であれば、ダークモードの地図が、それ以外の時間帯はライトモードの地図が表示されるはずである。(そうでなかったら、バグレポートをコメントでお願いします。)

夜6時以降ダークモードになる My Ideal Map App のユーザー体験の一例を最後に記して、この記事を終わりにしたい。

ユーザー体験(その4)

スウェーデンに住んでいたときに知り合ったポーランド人の友人が京都に訪ねてきてくれた。京都のおばんざい料理を食べて欲しかったので、夕食時に、お気に入りの店である「おせん」に連れて行った。

画像16

おせん(画像元:&Travel

カウンター席に二人で座り、大将や女将さんとの会話を通訳しながら楽しんだ。締めは、このお店の名物、たぬきごはん。

画像17

おせん名物「たぬきごはん」(ごはんの上に乗っているのは厚揚げと葛餡)(画像元:&Travel

食べ終わった後、どこか他の場所で呑もうということになったので、スマホを取り出し、My Ideal Map App を立ち上げて、右下のボタンをタップして表示されるタグ一覧から "Bars" を選択。地図上に、現在位置周辺にある、私が "Bars" というタグと共に保存した店が表示される。その中に、祇園・日(にち)というお気に入りのバーを見つけた。しばらく行ってなかったから、ぱっと思いつかなかった。こういうときに My Ideal Map App は思い出させてくれるので重宝する。

画像18

祇園・日のインテリア(画像元:祇園Niti

しかし、この祇園・日、路地を入ったわかりにくいところにあって、店の場所を覚えるのは無理。なので、スマホのスクリーンに地図を表示させながら、歩いて行く。

My Ideal Map App の地図は、夕方以降はダークモードになるので、スマホのスクリーンが暗い中で眩しくてチカチカするということがない。Google Maps アプリであれば、わざわざ何度かタップして設定をダークモードに変えないといけない。

無事辿り着くことができ、友人は祇園・日での時間をとても楽しんでくれた。

翌朝、別用で My Ideal Map App を使うと、朝になったら自動的にダークモードがオフになるので、ライトモードの地図が表示された。日中にダークモードの地図を見るのは違和感があるので、この機能は助かる。

それに、太陽の動きとリンクしてUIが変わるところが、お気に入り。通常のアプリにはない、温かさを感じる。うまく説明できないのだが、自然を支配しようとせずに、自然に寄り添うところが、そう思わせるのかもしれない。

---

と、ここまで書いてきて、本当に My Ideal Map App が欲しくなってきた(笑)。早くリリースできるように、がんばろうっと。

注: この記事は、英語で書いた同内容の記事を和訳すると同時に日本人向けに編集したものです。

引用文献

メディカルプライム神田(2021)「ブルーライトは悪者?むやみにカットしないで」『医療お役立ちコラム』2021年5月1日

Accessibility Guidelines Working Group (2021) “Understanding Success Criterion 1.4.3: Contrast (Minimum)”, Understanding WCAG 2.1, Jul 27, 2021 (last updated).

Babich, Nick (2019) "8 Tips for Dark Theme Design", UX PLanet, Jul 30, 2019.

Edwards, Marc (2018) “I’m not a fan of pure black in UI…”, Twitter, Oct 20, 2018.

Gentzkow, Matthew and Jesse M. Shapiro (2014) "Code and Data for the Social Sciences: A Practitioner's Guide", mimeograph.

Harvard Health Publishing (2020) "Blue light has a dark side", the website of Harvard Medical School, Jul 7, 2020.

Lee, Amy (undated) "The Guide to Map Design", the website of Mapbox.

PhoneBuff (2019) "Dark Mode vs. Light Mode Battery Test", YouTube, Oct 20, 2019.

Purdy, Kevin (2019) "Does Dark Mode Really Save Battery on Your Phone?", Ifixit, Jun 3, 2019.


この記事が気に入ったらサポートをしてみませんか?