Saat ini dalam d3 jika Anda memiliki objek geoJSON yang akan Anda gambar, Anda harus mengukur dan menerjemahkannya untuk mendapatkan ukuran yang diinginkan dan menerjemahkannya untuk memusatkannya. Ini adalah tugas trial and error yang sangat membosankan, dan saya bertanya-tanya apakah ada yang tahu cara yang lebih baik untuk mendapatkan nilai-nilai ini?
Jadi misalnya jika saya punya kode ini
var path, vis, xy;
xy = d3.geo.mercator().scale(8500).translate([0, -1200]);
path = d3.geo.path().projection(xy);
vis = d3.select("#vis").append("svg:svg").attr("width", 960).attr("height", 600);
d3.json("../../data/ireland2.geojson", function(json) {
return vis.append("svg:g")
.attr("class", "tracts")
.selectAll("path")
.data(json.features).enter()
.append("svg:path")
.attr("d", path)
.attr("fill", "#85C3C0")
.attr("stroke", "#222");
});
Bagaimana caranya mendapatkan .scale (8500) dan .translate ([0, -1200]) tanpa sedikit demi sedikit?
Jawaban:
Berikut ini sepertinya kira-kira apa yang Anda inginkan. Skala tampaknya ok. Saat menerapkannya ke peta saya ada offset kecil. Offset kecil ini mungkin disebabkan karena saya menggunakan perintah translate untuk memusatkan peta, sementara saya mungkin harus menggunakan perintah pusat.
Dalam kode:
sumber
projection.fitSize([width, height], geojson)
( API docs ) - lihat jawaban @dnltsk di bawah ini.Jawaban saya dekat dengan jawaban Jan van der Laan, tetapi Anda dapat menyederhanakan banyak hal karena Anda tidak perlu menghitung centroid geografis; Anda hanya perlu kotak pembatas. Dan, dengan menggunakan proyeksi unit yang tidak berskala dan tidak diterjemahkan, Anda dapat menyederhanakan matematika.
Bagian penting dari kode ini adalah ini:
Setelah menghitung kotak pembatas fitur dalam proyeksi unit, Anda dapat menghitung skala yang sesuai dengan membandingkan rasio aspek dari kotak pembatas (
b[1][0] - b[0][0]
danb[1][1] - b[0][1]
) dengan rasio aspek kanvas (width
danheight
). Dalam hal ini, saya juga telah menskalakan kotak pembatas hingga 95% dari kanvas, daripada 100%, jadi ada sedikit ruang ekstra di bagian tepi untuk goresan dan fitur di sekitarnya atau lapisan.Kemudian Anda dapat menghitung terjemahan menggunakan pusat kotak pembatas (
(b[1][0] + b[0][0]) / 2
dan(b[1][1] + b[0][1]) / 2
) dan pusat kanvas (width / 2
danheight / 2
). Perhatikan bahwa karena kotak pembatas berada dalam koordinat proyeksi unit, itu harus dikalikan dengan skala (s
).Misalnya, bl.ocks.org/4707858 :
Ada pertanyaan terkait di mana cara memperbesar fitur tertentu dalam koleksi tanpa menyesuaikan proyeksi, yaitu , menggabungkan proyeksi dengan transformasi geometrik untuk memperbesar dan memperkecil. Itu menggunakan prinsip yang sama seperti di atas, tetapi matematika sedikit berbeda karena transformasi geometrik (atribut "transformasi" SVG) dikombinasikan dengan proyeksi geografis.
Misalnya, bl.ocks.org/4699541 :
sumber
* 500
ini asing di sini ... juga,b[1][1] - b[0][0]
harusb[1][1] - b[0][1]
dalam perhitungan skala.b.s = b[0][1]; b.n = b[1][1]; b.w = b[0][0]; b.e = b[1][0]; b.height = Math.abs(b.n - b.s); b.width = Math.abs(b.e - b.w); s = .9 / Math.max(b.width / width, (b.height / height));
Dengan d3 v4 atau v5 semakin mudah!
dan akhirnya
Selamat menikmati, Cheers
sumber
d3v4
dan baru saja menemukan metode ini.g
? Apakah itu wadah svg?g
harus diberi<g></g>
tagSaya baru mengenal d3 - akan mencoba menjelaskan bagaimana saya memahaminya tetapi saya tidak yakin semuanya sudah benar.
Rahasianya adalah mengetahui bahwa beberapa metode akan beroperasi pada ruang kartografi (lintang, bujur) dan lainnya pada ruang kartesius (x, y di layar). Ruang kartografi (planet kita) berbentuk bola (hampir) berbentuk bola, ruang kartesian (layar) datar - untuk memetakan satu di atas yang lain Anda memerlukan algoritma, yang disebut proyeksi . Ruang ini terlalu pendek untuk masuk ke dalam subjek proyeksi yang mempesona dan bagaimana mereka mendistorsi fitur geografis untuk mengubah bola menjadi bidang; beberapa dirancang untuk menghemat sudut, lainnya menghemat jarak dan sebagainya - selalu ada kompromi (Mike Bostock memiliki banyak koleksi contoh ).
Di d3, objek proyeksi memiliki properti pusat / penyetel, yang diberikan dalam unit peta:
Ada juga terjemahan, yang diberikan dalam piksel - di mana pusat proyeksi relatif terhadap kanvas:
Ketika saya ingin memusatkan fitur di kanvas, saya ingin mengatur pusat proyeksi ke tengah kotak pembatas fitur - ini berfungsi untuk saya ketika menggunakan mercator (WGS 84, digunakan di peta google) untuk negara saya (Brasil), tidak pernah diuji menggunakan proyeksi dan belahan lainnya. Anda mungkin harus membuat penyesuaian untuk situasi lain, tetapi jika Anda menerapkan prinsip-prinsip dasar ini, Anda akan baik-baik saja.
Misalnya, diberi proyeksi dan jalur:
The
bounds
metode daripath
hasil kotak bounding dalam piksel . Gunakan untuk menemukan skala yang benar, membandingkan ukuran dalam piksel dengan ukuran dalam unit peta (0,95 memberi Anda margin 5% dari yang paling cocok untuk lebar atau tinggi). Geometri dasar di sini, menghitung lebar / tinggi persegi panjang yang diberikan diagonal berlawanan sudut:Gunakan
d3.geo.bounds
metode untuk menemukan kotak pembatas di unit peta:Atur pusat proyeksi ke tengah kotak pembatas:
Gunakan
translate
metode untuk memindahkan pusat peta ke pusat kanvas:Sekarang Anda harus memiliki fitur di tengah peta diperbesar dengan margin 5%.
sumber
Ada metode center () yang dapat Anda gunakan yang menerima pasangan lat / lon.
Dari apa yang saya mengerti, translate () hanya digunakan untuk memindahkan piksel peta secara harfiah. Saya tidak yakin bagaimana menentukan skala.
sumber
Selain memusatkan peta di d3 diberi objek geoJSON , perhatikan bahwa Anda dapat memilih
fitExtent()
lebih dari itufitSize()
jika Anda ingin menentukan bantalan di sekitar batas objek Anda.fitSize()
secara otomatis mengatur lapisan ini ke 0.sumber
Saya sedang mencari-cari di internet untuk mencari cara bebas repot memusatkan peta saya, dan terinspirasi oleh Jan van der Laan dan jawaban mbostock. Berikut cara yang lebih mudah menggunakan jQuery jika Anda menggunakan wadah untuk svg. Saya membuat batas 95% untuk bantalan / batas dll.
Jika Anda mencari penskalaan yang tepat, jawaban ini tidak akan bekerja untuk Anda. Tetapi jika seperti saya, Anda ingin menampilkan peta yang terpusat pada sebuah wadah, ini sudah cukup. Saya mencoba untuk menampilkan peta mercator dan menemukan bahwa metode ini berguna dalam memusatkan peta saya, dan saya dapat dengan mudah memotong bagian Antartika karena saya tidak membutuhkannya.
sumber
Untuk menggeser / memperbesar peta Anda harus melihat overlay SVG pada Leaflet. Itu akan jauh lebih mudah daripada mengubah SVG. Lihat contoh ini http://bost.ocks.org/mike/leaflet/ dan kemudian Bagaimana mengubah pusat peta di leaflet
sumber
Dengan jawaban mbostocks, dan komentar Herb Caudill, saya mulai mengalami masalah dengan Alaska karena saya menggunakan proyeksi mercator. Saya harus mencatat bahwa untuk tujuan saya sendiri, saya mencoba untuk memproyeksikan dan memusatkan Amerika Serikat. Saya menemukan bahwa saya harus mengawinkan kedua jawaban dengan jawaban Jan van der Laan dengan pengecualian berikut untuk poligon yang tumpang tindih dengan belahan (poligon yang berakhir dengan nilai absolut untuk Timur - Barat yang lebih besar dari 1):
buat proyeksi sederhana dalam mercator:
proyeksi = d3.geo.mercator (). skala (1) .translate ([0,0]);
buat jalan:
path = d3.geo.path (). projection (proyeksi);
3. mengatur batas saya:
4.Tambahkan pengecualian untuk Alaska dan negara bagian yang tumpang tindih dengan belahan bumi:
Saya harap ini membantu.
sumber
Bagi orang yang ingin menyesuaikan vertikal dan horizontal, berikut adalah solusinya:
sumber
Bagaimana saya memusatkan Topojson, di mana saya harus mengeluarkan fitur:
sumber