質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • PHP

    20318questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • JavaScript

    16382questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • JSON

    1147questions

    JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Googleマップの表示と読み込み方法について

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 540

ssk

score 269

やりたいこと

1.検索ボタンがクリックされるまでGoogleマップは非表示になっているので、
マーカーはなしでノーマルのマップを表示させたいです。

2.数が多くなることを想定して、今のマップに表示されている範囲のみ
マーカーを読み込むようにしたいです。

<!--検索ボタンがクリックされた時に実行するGoogleMapに関するコード-->
<script type="text/javascript">
$(function() {
    $('#MapSearch').submit(function(event) {
        event.preventDefault();//送信をキャンセル
        var $form = $(this);//対象のフォーム要素を取得
        // 送信ボタンを取得
        // (後で使う: 二重送信を防止する。)
        var $button = $form.find('button');

        $.ajax({
            url: "/hoge/ajax/mapsearch.json",
            type: "GET",
            data: $form.serialize(),
            dataType: "json",
            timeout: 10000,
            // 送信前
            beforeSend: function(xhr, settings) {
                // ボタンを無効化し、二重送信を防止
                $button.attr('disabled', true);
            },
            // 応答後
            complete: function(xhr, textStatus) {
                // ボタンを有効化し、再送信を許可
                $button.attr('disabled', false);
            },
        }).done(function initMap(jsonDataList) {
                                    var map;
                                    var infoWindow;
                                    ns = google.maps;
                                    mapOptions = {
                                        zoom: 12,
                                        minZoom : 10,
                                        maxZoom : 20,
                                        center: new ns.LatLng(35.665595, 139.739),
                                    };
                                    map = new ns.Map($("#map")[0], mapOptions);
                                    json = jsonDataList;
                                    json.jsonDataList.forEach(function (place) {
                                        var marker = new ns.Marker({
                                            position: new ns.LatLng(place.lat, place.lng),
                                            map: map
                                        });
                                        ns.event.addListener(marker, 'click', function () {//情報ウィンドウ
                                            if (!infoWindow) {
                                                infoWindow  = new ns.InfoWindow();
                                            }
                                            infoWindow.setContent(place.info);//place
                                            infoWindow.open(map, marker);
                                        });
                                    });
                                google.maps.event.addDomListener(window, 'load', initMap);
        }).fail(function (response) {
            alert("error");
        });    
    });
});
</script>

 <script async defer
      src="https://maps.googleapis.com/maps/api/js?key=APIキー">
</script>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2017/02/10 11:26

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 2

checkベストアンサー

+1

マーカーはなしでノーマルのマップを表示させたい

マップを表示させているコード(具体的に言うとmap = new ns.Map($("#map")[0], mapOptions);までのコード)をsubmitイベントの外に出せばいいですね。

今のマップに表示されている範囲のみマーカーを読み込むようにしたい

サーバで管理する方法と、クライアントで管理する方法があります。

サーバで管理する場合、実装によっては地図を移動させるたびに読み込みが発生し、結果として遅くなる可能性があります。地図をいくつかの範囲に分割し、表示エリアから読み込むべき範囲を取得し、再読み込みが必要であるかどうか制御する必要があるでしょう。位置情報DBに範囲IDフィールドを設けておくと応答が改善する可能性があるので、検討してみてください。参考:一次元ハッシュコードによる空間半径検索 - Qiita

クライアントで管理する場合、いくつかのライブラリがありますので利用をしてみるのもいいでしょう。ズームレベルによってはクラスタリングを検討するのもいいかもしれません。
https://github.com/googlemaps/v3-utility-library/blob/master/markermanager/examples/google_northamerica_offices.html
https://github.com/googlemaps/js-marker-clusterer

いずれにせよ、V2の時代よりもGoogleマップAPIは高速化しているので、100程度のマーカーであればそのままAPIに投げた方がよきにはからってもらえると思います。

 追記

すっかり忘れてましたが、はるか昔にgeohash管理ライブラリを作ったことがありました。緯度経度を渡すとその範囲のgeohashの組み合わせを返します。読み込み済みの範囲も管理していて、内部でパズルみたいに組み合わせをしたりしてます。プロトタイプ汚染とかしててお行儀の悪いレガシーコードですが、せっかくなので貼っておきますね。

function GeostringStack(max, min){
    //定数
    var GEOSTRING_LIMIT = max; //探索最小限度
    var SLICE_MARGIN = 0.00001; //スライスマージン
    var SLICE_LIMIT = Math.floor(min/2); //スライスグリッド
        var DY = 1.0/(Math.pow(2,SLICE_LIMIT));
        var DX = 1.0/(Math.pow(2,SLICE_LIMIT));
    var MAP_SIZE = {y:180, x:360}; //世界地図座標の範囲

    //Geohashモジュール
    function Geostring (data, bound, depth){
        var to_bits = function(f,depth){
            re = [];
            for (var i=1; i<depth+1; i++){
                re.push( Math.floor(f*2).toString() )
                f = (f*2)-Math.floor(f*2)
            }
            return re
        }

        var bitstring = function(data,bound,depth){
            var y = data[0];
            var x = data[1];
            y = to_bits((y-bound[0])/(bound[2]-bound[0]),depth)
            x = to_bits((x-bound[1])/(bound[3]-bound[1]),depth)
            bits =''
            for (var i=0; i<x.length; i++){
                bits += x[i] + y[i]
            }
            return bits
        }

        this.toString = function(){
            return this.hash;
        }

        this.union = function(yourHash){
            var myHash = this.hash;
            var yourHash = yourHash.toString();
            var returnHash = '';
            for ( var i=0; i<Math.min(myHash.length, yourHash.length); i++){
                if (myHash.charAt(i) == yourHash.charAt(i)){
                    returnHash += myHash.charAt(i);
                }else{
                    break;
                }
            }
            return new this.myConstructor(returnHash, bound, depth)
        }

        this.bbox = function(){
            var bits= this.hash;
            var depth = Math.floor(bits.length/2);
            var minx = 0.0;
            var miny = 0.0;
            var maxx = 1.0;
            var maxy = 1.0;
            for (var i=0; i<depth+1; i++){
                if (bits.charAt(i*2)) minx += parseInt(bits.charAt(i*2))/(Math.pow(2,i+1));
                if (bits.charAt(i*2+1)) miny += parseInt(bits.charAt(i*2+1))/(Math.pow(2,i+1));
            }
            if (depth){
                maxx = minx + 1.0/(Math.pow(2,depth+bits.length%2));
                maxy = miny + 1.0/(Math.pow(2,depth));
            }else if (bits.length == 1){
                // degenerate case
                maxx = Math.min(minx + .5, 1.0);
            }
            minx = origin[1]+minx*size[1];
            maxx = origin[1]+maxx*size[1];
            miny = origin[0]+miny*size[0];
            maxy = origin[0]+maxy*size[0];
            return [miny, minx, maxy, maxx];
        }

        this.myConstructor = arguments.callee

        var bound  = bound ? bound : [-90,-180,90,180];
        var depth  = depth ? depth : 32;
        var origin = bound.slice(0,2);
        var size   = [bound[2]-bound[0], bound[3]-bound[1]];
        if (data instanceof Array){
            this.hash = bitstring(data,bound,depth);
        }else{
            this.hash = data;
        }
    }

    //配列関数の拡張
    if (!Array.prototype.map){
        Array.prototype.map = function(f){
            var re = []
            for ( var i=0; i<this.length; i++){
                re.push( f(this[i]) )
            }
            return re;
        }
    }
    if (!Array.prototype.max){
        Array.prototype.max = function(){
            return this.slice(0).sort().reverse()[0];
        }
    }
    if (!Array.prototype.min){
        Array.prototype.min = function(){
            return this.slice(0).sort()[0];
        }
    }
    if (!Array.prototype.contains){
        Array.prototype.contains = function (v){
            for( var i=0; i<this.length; i++){
                if (this[i] == v) {return true; break;}
            }
        }
    }
    //定数
    var IS_FOUND = 1;
    var IS_EMPTY = 2;
    var IS_PARTIAL = 3;

    this.index = function(boxArray){
        var slicedBox = this.slice(boxArray);
        var boundsGeostring;
        var boundsGeostrings = [];
        for (var i=0; i<slicedBox.length; i++){
            boundsGeostring =
                new Geostring([slicedBox[i].sw.lat+SLICE_MARGIN, slicedBox[i].sw.lng+SLICE_MARGIN])
                    .union( new Geostring([slicedBox[i].ne.lat-SLICE_MARGIN, slicedBox[i].ne.lng-SLICE_MARGIN]) );
            boundsGeostrings = boundsGeostrings.concat( this.search( boundsGeostring.toString().substring(0,GEOSTRING_LIMIT) ) );
        }
        return boundsGeostrings
    }
    this.slice = function(bbox){//SLICE_LIMITで切り分け
        if (bbox instanceof Array) {
            box = { sw:{lat:bbox[0]/MAP_SIZE.y, lng:bbox[1]/MAP_SIZE.x}, ne:{lat:bbox[2]/MAP_SIZE.y, lng:bbox[3]/MAP_SIZE.x} };
        }else{
            box = bbox;
        }
        return subSlice(box).map(function(b){
            return { sw:{lat:b.sw.lat*MAP_SIZE.y, lng:b.sw.lng*MAP_SIZE.x}, ne:{lat:b.ne.lat*MAP_SIZE.y, lng:b.ne.lng*MAP_SIZE.x} } 
        });

        function subSlice(box){//再帰関数
            var yCutoff = box.sw.lat-box.sw.lat%DY+DY;
            var xCutoff = box.sw.lng-box.sw.lng%DX+DX;
            var f = ( ( yCutoff < box.ne.lat )<<1 ) + ( xCutoff < box.ne.lng )
            switch (f){
                case 0:
                    return [box];
                    break;
                case 1:
                    return [{ sw:{lat:box.sw.lat, lng:box.sw.lng}, ne:{lat:box.ne.lat, lng:xCutoff} }].concat(
                        subSlice({ sw:{lat:box.sw.lat, lng:xCutoff}, ne:{lat:box.ne.lat, lng:box.ne.lng} }))
                    break;
                case 2:
                    return [{ sw:{lat:box.sw.lat, lng:box.sw.lng}, ne:{lat:yCutoff, lng:box.ne.lng} }].concat(
                        subSlice({ sw:{lat:yCutoff, lng:box.sw.lng}, ne:{lat:box.ne.lat, lng:box.ne.lng} }))
                    break;
                case 3:
                    return [{ sw:{lat:box.sw.lat, lng:box.sw.lng}, ne:{lat:yCutoff, lng:xCutoff} }].concat(
                        subSlice({ sw:{lat:box.sw.lat, lng:xCutoff}, ne:{lat:yCutoff, lng:box.ne.lng} })).concat(
                        subSlice({ sw:{lat:yCutoff, lng:box.sw.lng}, ne:{lat:box.ne.lat, lng:xCutoff} })).concat(
                        subSlice({ sw:{lat:yCutoff, lng:xCutoff}, ne:{lat:box.ne.lat, lng:box.ne.lng} }))
                    break;
            }
        }
    }
    this.search = function(geostr){//読み込むGeostringを探索
        var isContain = false;
        for ( var i=1; i<=geostr.length; i++){
            if ( this.stack[i].contains( geostr.substring(0,i) ) ) {isContain = true; break;}
        }
        if (isContain) {
            return []
        }else{
            var list = this.subSearch(geostr)
            if (list.state == IS_FOUND){
                return false;
            }else{
                this.stack[geostr.length].push(geostr);
                return list.list;
            }
        }
    }
    this.subSearch = function(substr){//searchで使用する再帰関数
        if ( this.stack[substr.length].contains( substr ) ){
            return {'state': IS_FOUND, 'list': []};
        }else{
            if (substr.length>=GEOSTRING_LIMIT){
                return {'state': IS_EMPTY, 'list': [substr]};
            }else{
                var add0 = this.subSearch(substr+'0');
                var add1 = this.subSearch(substr+'1');
                var state = add0.state | add1.state; //IS_FOUND同志の時IS_FOUND、IS_EMPTY同志の時IS_EMPTY
                var list = (state == IS_EMPTY) ? [substr] : add0.list.concat(add1.list); //IS_EMPTY同志の時、リスト作り直し
                return {'state': state, 'list': list}
            }
        }
    }
    this.clearStack = function(){
        this.stack = new Array(GEOSTRING_LIMIT);
        for (var i=0; i<=GEOSTRING_LIMIT; i++) this.stack[i] = [];
    }

    //イニシャライズ
    this.clearStack();
}

動作例

var a = new GeostringStack(29,22);
a.index([35.8,139.8,35.9,139.9]);
//["1110110100001110011111", "1110110100001111001010"]
a.index([35.8,139.8,35.9,139.9]);
//[]
a.index([35.85,139.85,35.95,139.95]);
//["11101101000011101101010101", "111011010000111100101110", "11101101000011111000000", "11101101000011111000010000"]
a.index([35.85,139.85,35.95,139.95]);
//[]

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/11 00:51

    ご回答ありがとうございます。
    色々な情報までいただき、助かります><

    1の方は実装することができました。
    基本ができておらず、申し訳ございません。。。

    2の方はいただいた情報を参考に実装を進めてまいります。

    キャンセル

+1

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/11 00:49

    情報、ありがとうございます。
    リンク先を参考に実装を進めてまいります。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    20318questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • JavaScript

    16382questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • JSON

    1147questions

    JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。