Leaflet: ์ง€๋„ ์ค‘์•™์— ์˜คํ”„์…‹์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2012๋…„ 07์›” 31์ผ  ยท  31์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: Leaflet/Leaflet

์•ˆ๋…•. ๋ทฐํฌํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ง€๋„์˜ ์ค‘์‹ฌ์„ ์˜คํ”„์…‹ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ •๋ง ๋ฉ‹์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚ด ์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ์™ผ์ชฝ์— ์ง€๋„๋ฅผ ์˜ค๋ฒ„๋ ˆ์ดํ•˜๋Š” ํฐ ์ƒ์ž๊ฐ€ ์žˆ๊ณ  ์ง€๋„ ์ค‘์•™์ด ์˜ค๋ฅธ์ชฝ์— ๋” ์˜ค๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚ด๊ฐ€ ํŒฌ์ด๋‚˜ ์„ผํ„ฐ๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ ์‹ค์ œ๋กœ ํŠน์ • ์–‘์˜ ํ”ฝ์…€ ๋˜๋Š” ๋ทฐํฌํŠธ์˜ ๋ฐฑ๋ถ„์œจ์„ ์˜คํ”„์…‹ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ง€๋„ ์ˆ˜์ค€ ์„ค์ •์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋งŽ์€ JS ๋งคํ•‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ด ๊ธฐ๋Šฅ์„ ์›ํ–ˆ์ง€๋งŒ ์•„์ง ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ API์—์„œ ์ƒ๋‹นํžˆ ๋‚ฎ์€ ์ˆ˜์ค€์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ์—†๊ณ  ๊ทธ๋ƒฅ ์ƒ๊ฐํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ์ฝ”๋“œ๋ฅผ ๋‚ด๋ ค๋†“๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฉ‹์ง„ ํ”„๋กœ์ ํŠธ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‹ค์Œ์€ ํ˜„์žฌ https://github.com/codeforamerica/lv-trucks-map(http://clvfoodtrucks.com/ ์˜ ๋ผ์ด๋ธŒ ์‚ฌ์ดํŠธ)์— ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์—์„œ ์˜คํ”„์…‹์„ ์‚ฌ์šฉํ•˜์—ฌ panTo๋ฅผ ๊ตฌํ˜„ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. L.map ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์ง€๋„ ๊ฐ์ฒด์—์„œ "๊ธฐ๋ณธ์ ์œผ๋กœ" ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ง€๋„๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์ „์— JavaScript ์ฝ”๋“œ์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

L.Map.prototype.panToOffset = function (latlng, offset, options) {
    var x = this.latLngToContainerPoint(latlng).x - offset[0]
    var y = this.latLngToContainerPoint(latlng).y - offset[1]
    var point = this.containerPointToLatLng([x, y])
    return this.setView(point, this._zoom, { pan: options })
}

panTo() ์™€ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜์ง€๋งŒ [xOffset, yOffset] ํ˜•์‹์˜ ๋ฐฐ์—ด์ธ ์ถ”๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜ offset ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์ˆ˜์ •ํ•˜์—ฌ setViewOffset() ๋ฉ”์„œ๋“œ๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  31 ๋Œ“๊ธ€

์‹ค์ œ๋กœ Leaflet์—์„œ๋Š” ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒƒ์€ map.containerPointToLatLng ๋ฉ”์†Œ๋“œ์ž…๋‹ˆ๋‹ค. ์ง€๋„์˜ ์™ผ์ชฝ ์ƒ๋‹จ ๋ชจ์„œ๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ผ๋ถ€ ํ”ฝ์…€ ์ขŒํ‘œ๋ฅผ ์ง€๋ฆฌ์  ์œ„์น˜๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•ฉ๋‹ˆ๋‹ค.

var centerPoint = map.getSize().divideBy(2),
    targetPoint = centerPoint.subtract([overlayWidth, 0]),
    targetLatLng = map.containerPointToLatLng(centerPoint);

map.panTo(targetLatLng);

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๊นŒ?

์ด๋ด. ๊ทธ๊ฒƒ์€ ์ผ์ข…์˜ ์ˆ˜ํ–‰์ด๋ฉฐ ์•„๋งˆ๋„ ์ถฉ๋ถ„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์—์„œ ๋ฌธ์ œ๋Š” ๋ทฐํฌํŠธ๊ฐ€ ์ค‘์‹ฌ์— ๋‘๊ณ  ์‹ถ์€ ์œ„์น˜๋ผ๊ณ  ๊ฐ€์ •ํ•œ ๋‹ค์Œ ์˜คํ”„์…‹ํ•˜์—ฌ ๋‘ ๋‹จ๊ณ„ ์ด๋™์ด ๋  ๊ฒƒ์ด๋ผ๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์œ„๋„-๊ฒฝ๋„๋ฅผ ์ทจํ•˜๋Š” ๊ฒƒ๊ณผ๋Š” ๋ฐ˜๋Œ€๋กœ ์˜คํ”„์…‹ํ•œ ๋‹ค์Œ ํŒจ๋‹ํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์›€์ง์ž„.

์•„ ์ œ ๊ณ„์‚ฐ์ด ์ •ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜คํ”„์…‹ ์ค‘์‹ฌ์ด ๋Œ€์ƒ ์ง€์ ์— ์žˆ๊ณ  ์˜คํ”„์…‹์ด overlayWidth / 2 ์™€ ๊ฐ™๋„๋ก ์‹ค์ œ ์ง€๋„ ์ค‘์‹ฌ์„ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ผ ๋™์ž‘์— ๋Œ€ํ•œ ์ž‘์—… ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var targetPoint = map.project(targetLatLng, targetZoom).subtract([overlayWidth / 2, 0]),
    targetLatLng = map.unproject(targetPoint, targetZoom);

map.setView(targetLatLng, targetZoom);

์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ๊ฒช์—ˆ๋˜ ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ๋ถˆํˆฌ๋ช…ํ•œ ์‚ฌ์ด๋“œ๋ฐ”๊ฐ€ ์ง€๋„ ์ƒ๋‹จ์— ์˜ค๋ฒ„๋ ˆ์ด๋˜์—ˆ์Šต๋‹ˆ๋‹ค. fitBounds()๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ์•ฝ๊ฐ„ ๋–จ์–ด์ ธ ์žˆ๊ณ  ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด์— ๋Œ€ํ•œ ํ’€ ๋ฆฌํ€˜์ŠคํŠธ๋ฅผ ๊ณ ๋ คํ•˜๊ณ  ์žˆ์—ˆ์ง€๋งŒ ์•ฝ๊ฐ„์˜ ์ž‘์—…์ด ๋  ์ˆ˜ ์žˆ๊ณ  ์ถฉ๋ถ„ํžˆ ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์ด๋“œ๋ฐ”๋ฅผ ์ง€๋„ ์˜†์œผ๋กœ ์˜ฎ๊ธฐ๋Š” ๊ฒƒ์œผ๋กœ ๋์ด ๋‚ฌ์Šต๋‹ˆ๋‹ค.

@mourner ๊ทธ๊ฒƒ์€ ๋งŽ์€ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. project() ๋ฉ”์„œ๋“œ๋ฅผ ๋†“์นœ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@ajbeaven ์ฒ˜๋Ÿผ (GeoJSON) ๋ ˆ์ด์–ด์— ๋Œ€ํ•œ ์˜คํ”„์…‹ fitBounds๋Š” ๋งค์šฐ ํ›Œ๋ฅญํ•˜์ง€๋งŒ ํ›จ์”ฌ ๋” ๋ณต์žกํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ทฐํฌํŠธ์˜ ๊ฒฝ๊ณ„๊ฐ€ ํšจ๊ณผ์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜๊ณ  ์žˆ๊ณ  ํ•œ ๋ฒˆ์˜ ํ˜ธ์ถœ๋กœ ์˜คํ”„์…‹์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜คํ”„์…‹๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์–ด๋Š ์ชฝ์ด๋“ , ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž์ฒด์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ด์ง€ ์•Š๋‹ค๋ฉด ์ž์œ ๋กญ๊ฒŒ ๋‹ซ์œผ์‹ญ์‹œ์˜ค. ์ œ๊ณต๋œ ์ฝ”๋“œ๋กœ ๋‚ด ํŠน์ • ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌ ํ•ด์š”.

fitBounds ๋Š” ์ข€ ๋” ์žฅํ™ฉํ•˜์ง€๋งŒ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์ด https://github.com/CloudMade/Leaflet/blob/master/src/map/Map.js#L275 ๋ฉ”์„œ๋“œ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ๋ถ™์—ฌ๋„ฃ๊ณ  ์‚ฌ์šฉํ•˜๋Š” ํฌ๊ธฐ๋ฅผ ์ˆ˜์ •ํ•œ ๋‹ค์Œ ์‚ฌ์šฉํ•˜์„ธ์š”.

var targetZoom = altGetBoundsZoom(map, bounds);
// ... calculate targetLatLng as above
map.setView(targetLatLng, targetZoom);

์•ˆ๋…•. fitBounds ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ LatLng[] ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์œ„์—์„œ ์ œ๊ณตํ•œ ์ฝ”๋“œ ์กฐ๊ฐ์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ์ง€๋งŒ ์šด์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
๋‚ด ์›น์—๋Š” ์ง€๋„๋ฅผ ์•„๋ž˜์— ํ‘œ์‹œํ•˜๋ ค๋Š” ์‚ฌ์ด๋“œ๋ฐ” ์˜ค๋ฒ„๋ ˆ์ด๊ฐ€ ์žˆ์ง€๋งŒ ์ด ์˜ค๋ฒ„๋ ˆ์ด ์•„๋ž˜์— ๋งˆ์ปค๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š๋„๋ก ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. (์ง€๋„ ์ค‘์‹ฌ์„ ์˜คํ”„์…‹ํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์ง€๋งŒ ์ˆ˜๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

fitBounds ์— ๋Œ€ํ•œ ์ „์ฒด ์ฝ”๋“œ ์กฐ๊ฐ์„ _offset map_์— ๊ฒŒ์‹œํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?
์œ„์— ์“ฐ์‹  ๋‚ด์šฉ์ด ๋งŽ์ด ํ—ท๊ฐˆ๋ฆฌ๋„ค์š”. ๋ฌธ์ œ๋Š” ํฌ์ธํŠธ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— targetLatLng ๋‚˜ targetPoint $๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ใ…‹ ์ปจํ…Œ์ด๋„ˆ์˜ ๊ฐ ๋ฉด์— ์„ธ๋ฏธ ์˜ค๋ฒ„๋ ˆ์ด๋œ ๊ณต๊ฐ„์˜ ์–‘์„ ์ •์˜ํ•˜๋Š” ์˜ต์…˜์ด ์žˆ์œผ๋ฉด ์ •๋ง ๋ฉ‹์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์—ฌ์ „ํžˆ ์ง€๋„๋ฅผ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์ง€๋งŒ ๋งˆ์ปค์— ์ปจํŠธ๋กค์„ ๋ฐฐ์น˜ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ๋‚ด๊ฐ€ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์ด๊ฒƒ์€ ๊ฒฐ์ฝ” ํ›Œ๋ฅญํ•œ ์ฝ”๋“œ ์ธ์Šคํ„ด์Šค๋Š” ์•„๋‹ˆ์ง€๋งŒ ์•„์ด๋””์–ด๋Š” ์žˆ์Šต๋‹ˆ๋‹ค) ๋˜ํ•œ Leaflet ๋งต์ธ ๋งต ์†์„ฑ์„ ๋ณด์œ ํ•˜๋Š” ๊ฐ์ฒด์— ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์•ฑ์…‹๋ทฐ
appSetBounds
appGetBoundsZoom

https://github.com/MinnPost/minnpost-my-boundaries/blob/master/visualizations/index.html#L556

๋‚ด์žฅ๋œ ์ด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ ๋‹ค์‹œ ์—ฝ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ ๋’ค์— ์ง€๋„์™€ ํ•จ๊ป˜ 550px์˜ ํ™”๋ฉด ์™ผ์ชฝ์— ๋ชฉ๋ก์ด ์žˆ์–ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ํ† ๋ก ์„ ์ ‘ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. L.Map์˜ ์ผ๋ถ€ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์„ ์žฌ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์šธ ๊ฒƒ์ด๋ผ๊ณ  ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์•„์ด๋””์–ด์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๋ชจ๋‘ ํ•ด๊ฒฐ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ์ง€๋งŒ 100% ํ™•์‹ ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

MapCenterOffsetMixin = {
    UIOffset: [550, 0], // x, y
    getBounds: function(){
        var a=this.getPixelBounds(),
            b=this.unproject(new L.Point(a.min.x+this.UIOffset[0],a.max.y+this.UIOffset[1]), this._zoom,!0),
            c=this.unproject(new L.Point(a.max.x,a.min.y),this._zoom,!0);
            return new L.LatLngBounds(b,c)
    },
    _latLngToNewLayerPoint: function (latlng, newZoom, newCenter) {
        var targetPoint = this.project(newCenter, newCenter).subtract([this.UIOffset[0]/2, this.UIOffset[1]/2]),
            newCenter = this.unproject(targetPoint, newZoom);
        var topLeft = this._getNewTopLeftPoint(newCenter, newZoom).add(this._getMapPanePos());
        return this.project(latlng, newZoom)._subtract(topLeft);
    },
    _getCenterLayerPoint: function () {
        return this.containerPointToLayerPoint(this.getSize().divideBy(2).add([this.UIOffset[0]/2, this.UIOffset[1]/2]));
    },
    _resetView: function (a, b, c, d) {
        var e = this._zoom !== b;
        // Change the center
        var targetPoint = this.project(a, b).subtract([this.UIOffset[0] / 2, this.UIOffset[1]/2]),
            a = this.unproject(targetPoint, b);
        d || (this.fire("movestart"), e && this.fire("zoomstart")), this._zoom = b, this._initialTopLeftPoint = this._getNewTopLeftPoint(a);
        if (!c) L.DomUtil.setPosition(this._mapPane, new L.Point(0, 0));
        else {
            var f = L.DomUtil.getPosition(this._mapPane);
            this._initialTopLeftPoint._add(f)
        }
        this._tileLayersToLoad = this._tileLayersNum, this.fire("viewreset", {
            hard: !c
        }), this.fire("move"), (e || d) && this.fire("zoomend"), this.fire("moveend"), this._loaded || (this._loaded = !0, this.fire("load"))
    }
}

L.Map.include(MapCenterOffsetMixin);

@averrips ์˜ฌ๋ ค ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ์†”๋ฃจ์…˜์€ ํ˜„์žฌ ์ž˜ ์ž‘๋™ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค ... Firefox์—์„œ ํ™•๋Œ€/์ถ•์†Œ ์ปจํŠธ๋กค์ด ์ด์ œ ๊นจ์ง„ ๊ฒƒ์„ ์ œ์™ธํ•˜๊ณ  :( ์ผ์ข…์˜ "catchall"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. TypeError: t is undefined

๋‹ค์Œ์€ ์ง€๋„์— ์žˆ์–ด์•ผ ํ•˜๋Š” fitBoundsPadded์˜ ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค.
fitBounds์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ์›ํ•˜๋Š” ํŒจ๋”ฉ์„ ์ „๋‹ฌํ•˜๋ฏ€๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

map.fitBoundsPadded(myBounds, new L.Point(0, 0), new L.Point(0, 150));

๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ:

    fitBoundsPadded: function (bounds, paddingTopLeft, paddingBottomRight) { //(LatLngBounds, Point, Point)

        var zoom = this.getBoundsZoom(bounds);
        var zoomToTry = zoom;

        while (true) {
            var newTopLeft = this.unproject(this.project(bounds.getNorthEast(), zoomToTry).add(paddingTopLeft), zoomToTry);
            var newBottomRight = this.unproject(this.project(bounds.getSouthWest(), zoomToTry).add(paddingBottomRight), zoomToTry);

            var paddedBounds = new L.LatLngBounds([bounds.getSouthWest(), bounds.getNorthEast(), newTopLeft, newBottomRight]);

            var zoom2 = this.getBoundsZoom(paddedBounds);

            if (zoom2 == zoomToTry) {
                return this.fitBounds(paddedBounds);
            } else {
                zoomToTry--;
            }
        }
    },

๋งˆ์Šคํ„ฐ์—์„œ ๊ตฌํ˜„! ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

map.fitBounds(bounds, [20, 30], [40, 50]); // bounds, topLeftPadding, bottomRightPadding

๋˜๋Š” ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋งŒ ์ „๋‹ฌํ•˜๋ฉด ์˜ค๋ฅธ์ชฝ ํ•˜๋‹จ ํŒจ๋”ฉ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ์™ผ์ชฝ ์ƒ๋‹จ๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

์„œ๋ช…์ด ์กฐ๊ธˆ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

map.fitBounds(bounds, {
    padding: [20, 30]
});

map.fitBounds(bounds, {
    paddingTopLeft: [20, 30],
    paddingbottomRight: [40, 50]
});

๋‹ค๋ฅธ ๊ธฐ๋Šฅ์— ํŒจ๋”ฉ์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ž‘์—…์ด ๊ณ„ํš๋˜์–ด ์žˆ์Šต๋‹ˆ๊นŒ?

์•„๋งˆ๋„, ์˜ˆ. setView ๋ฐ panTo ์ด์ƒ.

๋ชจ๋“  ๋ฉด์— ๋™์ผํ•œ ํŒจ๋”ฉ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ”๋กœ ๊ฐ€๊ธฐ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ™์€.

map.fitBounds(bounds, { padding: 20 });

ํ˜„์žฌ ๋Œ€์‹ ...

map.fitBounds(bounds, { padding: [20, 20] });

@averrips Mixin์ด ๋งŽ์€ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์•„์ง ์†”๋ฃจ์…˜์„ ์ฐพ์„ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์—ฌ๊ธฐ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค(์ •๋ง ์‰ฝ์Šต๋‹ˆ๋‹ค).

 ๊ธฐ๋Šฅ ์ค‘์‹ฌ(์ง€๋„, ์œ„๋„, ์˜คํ”„์…‹, ์˜คํ”„์…‹) {
 var ์„ผํ„ฐ = map.project(latlng);
 ์ค‘์‹ฌ = ์ƒˆ๋กœ์šด L.point(center.x+offsetx,center.y+offsety);
 var ๋Œ€์ƒ = map.unproject(์ค‘์•™);
 map.panTo(๋Œ€์ƒ);
 }

"setView" ๋ฐ "panTo"์—๋„ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.
๊ฐ์‚ฌ ํ•ด์š”!

๋˜ํ•œ ์™ผ์ชฝ | ์˜ค๋ฅธ์ชฝ ์ปจํŠธ๋กค๋„ ํŒจ๋”ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋‹ค์Œ์€ ํ˜„์žฌ https://github.com/codeforamerica/lv-trucks-map(http://clvfoodtrucks.com/ ์˜ ๋ผ์ด๋ธŒ ์‚ฌ์ดํŠธ)์— ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์—์„œ ์˜คํ”„์…‹์„ ์‚ฌ์šฉํ•˜์—ฌ panTo๋ฅผ ๊ตฌํ˜„ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. L.map ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์ง€๋„ ๊ฐ์ฒด์—์„œ "๊ธฐ๋ณธ์ ์œผ๋กœ" ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ง€๋„๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์ „์— JavaScript ์ฝ”๋“œ์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

L.Map.prototype.panToOffset = function (latlng, offset, options) {
    var x = this.latLngToContainerPoint(latlng).x - offset[0]
    var y = this.latLngToContainerPoint(latlng).y - offset[1]
    var point = this.containerPointToLatLng([x, y])
    return this.setView(point, this._zoom, { pan: options })
}

panTo() ์™€ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜์ง€๋งŒ [xOffset, yOffset] ํ˜•์‹์˜ ๋ฐฐ์—ด์ธ ์ถ”๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜ offset ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์ˆ˜์ •ํ•˜์—ฌ setViewOffset() ๋ฉ”์„œ๋“œ๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณ ๋งˆ์›Œ, ๋ฃจ!

์ฐธ๊ณ ๋กœ ์ด ๊ตฌ์„ฑ์€ Foursquare ํ™ˆํŽ˜์ด์ง€์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ˆ˜ํ‰ ์˜คํ”„์…‹์„ ์—๋ฎฌ๋ ˆ์ดํŠธํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
https://gist.github.com/missinglink/7620340

@louh๋‹˜ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

@missinglink ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค!

ํ™•๋Œ€/์ถ•์†Œ ์ž‘์—…์—๋„ ์†”๋ฃจ์…˜์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

        var MapCenterOffsetMixin = {
            getMapOffset: function() {
                console.log('getMapOffset');
                return [$('#left-panel').offset().left, 0];
            },
            getBounds: function(){
                console.log('getBounds');
                var offset = this.getMapOffset(),
                    bounds = this.getPixelBounds(),
                    sw = this.unproject(new L.Point(bounds.min.x + offset[0], bounds.max.y + offset[1]), this._zoom, !0),
                    ne = this.unproject(new L.Point(bounds.max.x, bounds.min.y), this._zoom, !0);

                return new L.LatLngBounds(sw, ne)
            },
            _oldLatLngToNewLayerPoint: L.Map.prototype._latLngToNewLayerPoint,
            _latLngToNewLayerPoint: function (latlng, newZoom, newCenter) {
                console.log('_latLngToNewLayerPoint');
                var offset = this.getMapOffset(),
                    targetPoint = this.project(newCenter, newCenter).subtract([offset[0] / 2, offset[1] / 2]);
                newCenter = this.unproject(targetPoint, newZoom);

                return this._oldLatLngToNewLayerPoint(latlng, newZoom, newCenter);
            },
            _getCenterLayerPoint: function () {
                console.log('_getCenterLayerPoint');
                var offset = this.getMapOffset();
                return this.containerPointToLayerPoint(this.getSize().divideBy(2).add([offset[0] / 2, offset[1] / 2]));
            },
            _oldResetView: L.Map.prototype._resetView,
            _resetView: function (center, zoom, preserveMapOffset, afterZoomAnim) {
                console.log('_resetView');
                var offset = this.getMapOffset(),
                    targetPoint = this.project(center, zoom).subtract([offset[0] / 2, offset[1] / 2]);
                center = this.unproject(targetPoint, zoom);

                this._oldResetView(center, zoom, preserveMapOffset, afterZoomAnim);
            }
        };
        L.Map.include(MapCenterOffsetMixin);

ํ•˜์ง€๋งŒ ํ™•๋Œ€/์ถ•์†Œ์— ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. https://github.com/Mappy/Leaflet-active-area. ๋ฉ‹์ง„! :)

'map.fitBounds(bounds, topLeftPadding, bottomRightPadding)' ํ•จ์ˆ˜๋Š” ํ”ฝ์…€์ด ์•„๋‹Œ ์œ„๋„๋ฅผ ์กฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ™•๋Œ€/์ถ•์†Œ ์ˆ˜์ค€์— ๋”ฐ๋ผ ์ง€๋„๊ฐ€ ์กฐ์ •๋˜๋Š” ์ •๋„์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•˜์ง€๋งŒ, ์กฐ์ •์ด ํ™•๋Œ€/์ถ•์†Œ ์ˆ˜์ค€์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๋Š” ์„ค์ • ํฌ๊ธฐ ์‚ฌ์ด๋“œ ๋ฐ” ๋˜๋Š” ์ƒ์œ„ ๋ฉ”๋‰ด์™€ ๊ฐ™์ด ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์ œ๊ธฐํ•˜๋Š” ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ขŒํ‘œ๊ฐ€ ์•„๋‹Œ ํ”ฝ์…€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํŒจ๋”ฉ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋‚ด์žฅ ์ „๋‹จ์ง€ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

topLeftPadding ๋ฐ bottomRightPadding ์˜ˆ์ƒ ๊ฐ’(ํ”ฝ์…€): http://leafletjs.com/reference.html#map -fitboundsoptions

์–ด๋–ค ์ด์œ ์—์„œ์ธ์ง€ ์ €์—๊ฒŒ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด 15์˜ ํ™•๋Œ€/์ถ•์†Œ ์ˆ˜์ค€์—์„œ ๋งˆ์ปค๋ฅผ ์ค‘์•™์— ๋†“์€ ๋‹ค์Œ ์ด ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค...
map.fitBounds(pointsArray, {paddingTopLeft: [0,0], paddingBottomRight: [800,0], maxZoom: map.getZoom()});
๊ทธ๋Ÿฐ ๋‹ค์Œ 19์˜ ํ™•๋Œ€/์ถ•์†Œ ์ˆ˜์ค€์—์„œ ๋งˆ์ปค๋ฅผ ์ค‘์•™์— ๋†“๊ณ  ๋‹ค์‹œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ ˆ๋ฒจ 15์—์„œ๋Š” ์ด๋™ํ•˜๋Š” ์–‘์ด ๊ฑฐ์˜ ๋ˆˆ์— ๋„์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ ˆ๋ฒจ 19์—์„œ๋Š” ํŽ˜์ด์ง€์˜ ์ ˆ๋ฐ˜ ์ •๋„๋ฅผ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ํ•จ์ˆ˜ ํ˜ธ์ถœ์—์„œ ๋ญ”๊ฐ€ ์ž˜๋ชปํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰