Google API v3 でヒートマップを作成しています。例を挙げます。地震のマグニチュードを考えてみましょう。各点に重みを割り当てて、その大きさを指定します。ただし、ズームアウトすると、Googleはポイントの密度を考慮します。ポイントが多い場所ほど赤くなります。たとえば、マグニチュード 3 とマグニチュード 8 の 2 つの地震が数マイル以内で発生した場合、最初の地震は緑/青、2 番目の地震は赤になります。しかし、ズームアウトしてマップ内の 2 つのポイントが近づくと、Google マップは重みではなくポイントの数を考慮し、その結果、読み取られたように見えます。私はそれが平均、つまり (3+8)/2=5.5 であることを望みます...どんな色を表すにせよ。これは可能ですか?
5 に答える
あなたが私のようで、オーバーレイを生成する処理時間や能力がなく、既存のライブラリを好みに合わせて変更できない場合は、ある程度まともな回避策があります。
Google マップのヒートマップ ライブラリを使用し、maxIntensity と dissipating を false に設定しました。maxIntensity を選択した値に設定すると、0 または設定値ではなく、ヒートマップ ポイントが互いに関連して色付けされるという問題が解決されます。Dissipating を false に設定すると、ズーム レベルを変更したときに発生する自動半径設定が無効になります。
次に、ズーム レベルが変化するたびにイベントを作成し、そのイベントで半径を、そのズーム レベルで最も正確な方法でデータを表すと思われる値に設定しました。
ここで、マップ上のデータポイントが混ざり合って大きな赤い塊に追加されるという問題を取り除くために、使用するズーム レベルごとにマップ上に個別のグリッドを作成することにしました。同じグリッド ポイント内にボックス化されたすべての値を平均し、グリッドがヒートマップ ポイントが重ならないようにするのに十分な大きさであることを確認しますが、円の束のように見えないように十分に小さくします。(滑らかな外観を得るには、グリッドをマップ上のヒートポイント半径の約 0.4 倍のサイズにする必要があることがわかりました)。
ヒートマップ ポイントの半径は、Google によってピクセル単位で設定されます。ピクセルを緯度/経度に変換する方法がわからなかったので、特定の半径の円を通過する線を引いて測定し、これらの線の間の距離を測定しました。小さな国以上のマッピングを計画していない場合、この変換方法は非常にうまく機能します。
パフォーマンスに関しては、これは私が思っていたほど悪くはありません。約 2300 ポイントを読み込んでいますが、ズーム レベルごとにグリッドを作成する前と同じ速さでマップが読み込まれます。実際には、ズーム レベルを変更してもデータ ポイントが更新されることはありません。
上記のすべてのコードの一部を次に示します。
マップ設定:
map.heatmap.set('maxIntensity', 12000);
map.heatmap.set('dissipating', false);
ズーム レベルごとにグリッドと半径を変更します。
map._on({
obj: map.gMap,
event: "zoom_changed",
callback: function(){
var zoomLevel = map.zoom();
switch(zoomLevel){
case 7:
map.heatmap.setData(gridData[zoomLevel]);
map.heatmap.set('radius', 0.04);
break;
case 8:
map.heatmap.setData(gridData[zoomLevel]);
map.heatmap.set('radius', 0.03);
break;
case 9:
map.heatmap.setData(gridData[zoomLevel]);
map.heatmap.set('radius', 0.02);
break;
case 10:
map.heatmap.setData(gridData[zoomLevel]);
map.heatmap.set('radius', 0.01);
break;
case 11:
map.heatmap.setData(gridData[zoomLevel]);
map.heatmap.set('radius', 0.005);
break;
case 12:
map.heatmap.setData(gridData[zoomLevel]);
map.heatmap.set('radius', 0.0025);
break;
case 13:
map.heatmap.setData(gridData[zoomLevel]);
map.heatmap.set('radius', 0.00225);
break;
default:
map.heatmap.setData(gridData[zoomLevel]);
map.heatmap.set('radius', 0.000625);
}
}
});
私のグリッドは PHP で生成されており、おそらく人によって異なるように見えますが、例として、私が使用する関数を次に示します。
function getHeatGrid($gridSize){
$mapGrid = false;
$mapData = false;
$radius = $gridSize * 2.8 * 0.3; //grid size is multiplied by 2.8 to convert from the heat map radius to lat/long values(works for my lat/long, maybe not yours). * 0.3 is arbitrary to avoid seeing the grid on the map.
$string = file_get_contents("mapData.json");
$json_a = json_decode($string, true);
forEach($json_a as $key => $value){
$row = intval(round(($value['center_longitude'] / $radius)));
$column = intval(round(($value['center_latitude'] / $radius)/68*111)); //around 52.0;5.0 latitude needs to be scaled to make a square grid with the used longitude grid size
if(isset($mapGrid[$row][$column])){
$mapGrid[$row][$column] = round(($value['solarValue'] + $mapGrid[$row][$column]) / 2);
} else {
$mapGrid[$row][$column] = $value['solarValue'];
}
}
forEach($mapGrid as $long => $array){
forEach($array as $lat => $weight){
$mapData[] = array(
"center_longitude" => $long * $radius,
"center_latitude" => ($lat * $radius)/111*68,
"solarValue" => $weight
);
}
}
return $mapData;
}
残念ながら、現在私が働いている会社のクライアント向けに非公開にされているため、マップを表示することはできませんが、公開された場合はリンクを追加して、この方法がどのように機能するかを確認できるようにします.
これが誰かに役立つことを願っています。
ルーカス
マップの上にヒートマップ画像を重ねることでそれを行うことができます。https://github.com/jeffkaufman/apartment_pricesに非常に優れたオープン ソースの例があります。
定義によるヒートマップは、ポイント密度と各ポイントに割り当てられた重みを考慮します。少なくとも Google のヒート マップは、Google との共同作業から知る限り、このように機能します。したがって、実際に必要なのはヒートマップではなく、値に応じて色付けされるポイントのマップです。
また、マップに色を付けるために、Google ヒートマップが考慮する密度/重みの比率を変更する必要がありましたが、方法が見つかりませんでした。現在、ヒートマップの主な要因は密度であり、重量の変化は色にほとんど影響しません。
この例では、マップ上のレイヤーとしてヒートマップを使用しています。