GoogleMaps が Ctrl 押さないとズームしなくなってる
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 3
◆ デフォルトの仕様が変わって Ctrl 押さないとマウスでズーム操作できない
◆ gestureHandling プロパティで元の動作に戻すことは可能
◆ もっと便利にフォーカス中のみ Ctrl 不要になるようにした
◆ gestureHandling プロパティで元の動作に戻すことは可能
◆ もっと便利にフォーカス中のみ Ctrl 不要になるようにした
最近 ブログやオフィシャルサイトの GoogleMaps の埋め込みでこういう表示をよく見ます

夏くらいから でしょうか?
端から端まで地図があるページだと 地図のところでスクロールできなくなるのでありがたいのですが 地図がサイドバーの中など小さくある場合には毎回 Ctrl キーを押すのがとても面倒です
完全に地図検索用のページで ヘッダやフッタはあるものの地図を見るのがメインになってるページですらこの警告が出てきます
ここまで来ると便利だから流行ってる方法とかいうレベルじゃなく仕様変更でデフォルトでこうなってるように思えます
Change log を見てみると
https://developers.google.com/maps/documentation/javascript/releases?hl=ja
2017/8/16 に更新された 3.30 で gestureHandling プロパティが導入されたようです
これは 2016/11/15 の 3.27 で experimental version として利用可能になったプロパティです
greedy はこれまでと一緒で 地図内でマウスホイール回したり タップ操作でスワイプすれば地図がズームしたりパンされたりします
cooperative はこういったページ操作を邪魔しないためのもので ズームするには Ctrl キーを押さないとだめで タップでパンするには二本指じゃないとだめになります
none だとマウスやタップでのズームやパンが全くできなくなります
auto にすれば スクロールバーがあったり iframe の中なら cooperative それ以外なら greedy という風に自動でページの邪魔にならないようになります
これまでのに戻したいならオプションに {gestureHandling: "greedy"} を指定すれば良いです
初期化するところでこんな感じです
なのでこんなのを作りました
地図作成は initMap 関数を使います
ターゲットにする要素とオプションを渡します
やってることは 地図内をクリックしたときに gestureHandling を greedy に切り替え 地図外をクリックしたときに cooperative (auto) に切り替えています
リスナが click じゃなくて mousedown になっていますが これはいきなりドラッグした場合で地図の外でマウスを離すとパンしたのに地図内でクリックした扱いにならないからです
できれば Chrome Extension 化して全部のページの GoogleMaps で動くようにしたかったのですが どの要素が地図をホストしてるかのチェックと DOM 要素から GoogleMaps オブジェクトを取得するのが無理そうなので結局自身で作るサイトでしか使えない方法になりました
GoogleMaps のデフォルトがこういう動きするようになればいいのですけどね

夏くらいから でしょうか?
端から端まで地図があるページだと 地図のところでスクロールできなくなるのでありがたいのですが 地図がサイドバーの中など小さくある場合には毎回 Ctrl キーを押すのがとても面倒です
完全に地図検索用のページで ヘッダやフッタはあるものの地図を見るのがメインになってるページですらこの警告が出てきます
ここまで来ると便利だから流行ってる方法とかいうレベルじゃなく仕様変更でデフォルトでこうなってるように思えます
Change log を見てみると
https://developers.google.com/maps/documentation/javascript/releases?hl=ja
2017/8/16 に更新された 3.30 で gestureHandling プロパティが導入されたようです
これは 2016/11/15 の 3.27 で experimental version として利用可能になったプロパティです
gestureHandling
gestureHandling プロパティには 4 種類の値がセットできます- greedy
- cooperative
- none
- auto
greedy はこれまでと一緒で 地図内でマウスホイール回したり タップ操作でスワイプすれば地図がズームしたりパンされたりします
cooperative はこういったページ操作を邪魔しないためのもので ズームするには Ctrl キーを押さないとだめで タップでパンするには二本指じゃないとだめになります
none だとマウスやタップでのズームやパンが全くできなくなります
auto にすれば スクロールバーがあったり iframe の中なら cooperative それ以外なら greedy という風に自動でページの邪魔にならないようになります
これまでのに戻したいならオプションに {gestureHandling: "greedy"} を指定すれば良いです
初期化するところでこんな感じです
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 10,
center: {lat: 35.36105612, lng: 138.72711182},
streetViewControl: true,
gestureHandling: "greedy",
})
zoom: 10,
center: {lat: 35.36105612, lng: 138.72711182},
streetViewControl: true,
gestureHandling: "greedy",
})
cooperative をもっと便利にしたい
cooperative にするとページのスクロールを邪魔しないのですが ずっと Ctrl 押さなくても一度地図にフォーカス当てたらフォーカスはずすまでは地図操作をしてほしいですよねなのでこんなのを作りました
let active_google_maps = null
const elem2map = new WeakMap()
function initMap(elem, option){
const map = new google.maps.Map(elem, option)
elem2map.add(elem, map)
elem.classList.add("google-maps-host")
return map
}
function getMapsFromElement(elem){
return elem2map.get(elem)
}
window.addEventListener("mousedown", eve => {
const map_host = eve.target.closest(".google-maps-host")
if(map_host){
active_google_maps = getMapsFromElement(map_host)
// enable scroll zooming on got focus
active_google_maps.setOptions({gestureHandling: "greedy"})
}else{
if(active_google_maps){
// disable scroll zooming on lost focus
active_google_maps.setOptions({gestureHandling: "auto"})
}
}
}, true)
const elem2map = new WeakMap()
function initMap(elem, option){
const map = new google.maps.Map(elem, option)
elem2map.add(elem, map)
elem.classList.add("google-maps-host")
return map
}
function getMapsFromElement(elem){
return elem2map.get(elem)
}
window.addEventListener("mousedown", eve => {
const map_host = eve.target.closest(".google-maps-host")
if(map_host){
active_google_maps = getMapsFromElement(map_host)
// enable scroll zooming on got focus
active_google_maps.setOptions({gestureHandling: "greedy"})
}else{
if(active_google_maps){
// disable scroll zooming on lost focus
active_google_maps.setOptions({gestureHandling: "auto"})
}
}
}, true)
地図作成は initMap 関数を使います
ターゲットにする要素とオプションを渡します
やってることは 地図内をクリックしたときに gestureHandling を greedy に切り替え 地図外をクリックしたときに cooperative (auto) に切り替えています
リスナが click じゃなくて mousedown になっていますが これはいきなりドラッグした場合で地図の外でマウスを離すとパンしたのに地図内でクリックした扱いにならないからです
できれば Chrome Extension 化して全部のページの GoogleMaps で動くようにしたかったのですが どの要素が地図をホストしてるかのチェックと DOM 要素から GoogleMaps オブジェクトを取得するのが無理そうなので結局自身で作るサイトでしか使えない方法になりました
GoogleMaps のデフォルトがこういう動きするようになればいいのですけどね
COMMENT
コメント一覧 (3)
-
- 2017/10/22 15:33
-
ホイール=スクロールの他のソフトとの操作整合性をとったのですよ。ブラウザー自身もホイールはスクロールだし。
間違って拡大縮小してしまう方が圧倒的でしたからね。
-
- 2018/01/22 14:51
-
ユーザーサイドで解除できないのでしょうか?
userscriptで検索しても出ませんでした
-
- 2018/01/25 22:59
-
> ユーザーサイドで解除できないのでしょうか?
ユーザサイドでは難しいですね
GoogleMaps の処理は JavaScript で制御されているもので ページを作る人が GoogleMaps の API を使って色々な実装な仕方をしています
全部のページじゃなくてこのページだけで解除したい というのなら そのページの JavaScript を読んで GoogleMaps が初期化された後にオプションを上書きすることができるかもしれません
かもしれない というのは GoogleMaps のインスタンスがユーザスクリプトからアクセスできるようにされているかによって変わるからです
ユーザスクリプトからアクセスできないならどうしようもなくなります
シンプルなページならグローバルに参照を保持していたりするので そういうページならできます
ただ ページの JavaScript が更新されるとユーザスクリプトも更新する必要があります
一応難易度が高いですが 全ページ対応させる方法がなくもないです
それは GoogleMaps のライブラリをロードした直後にライブラリを上書きしてページ作る人が設定するオプションを無視してユーザスクリプトが指定したオプションになるようにすることです
複雑かつ変更の多い GoogleMaps の JavaScript を読む必要がありますし あまりおすすめはしません