Location and Maps
MapView는 구글 맵을 앱에서 사용할 수 있게 해 줍니다.
코로나에서의 MapView는 현재까지 iOS만 지원 됩니다. 안드로이드에서 안될 뿐만 아니라 코로나 시뮬레이터에서도 안 됩니다.
테스트 하려면 맥에 XCode 시뮬레이터 깔아 놓고 하던가 애플 디바이스를 구입하셔야 합니다.
Constructor
myMap = native.newMapView(left,top,width,height)
특정 영역에 MapView를 표시하고 코로나 display object를 반환합니다. 이 object는 다른 display object처럼 움직이거나 회전할 수 있습니다.
Map attributes
myMap.mapType = "standard"
myMap.mapType = "satellite"
myMap.mapType = "hybrid"
mapType은 일반 타입의 지도, 위성에서 보는것 같은 타입의지도, hybrid지도를 선택할 수 있습니다.
안드로이드나 애플 앱을 이용해서 구글 맵 표시를 해 보셨다면 쉽게 이해 하실 겁니다.
myMap.isZoomEnabled = true
확대 축소를 가능하게 해 줍니다. 디폴트는 true입니다.
myMap.isScrollEnabled = true
스크롤을 가능하게 해 줍니다. 디폴트는 true 입니다.
myMap.isLocationUpdating = true
현재 위치를 표시할 수 있도록 합니다. 사용자가 이동하면 계속 업데이트 될 겁니다. 디폴트는 false입니다.
isVisible= myMap.isLocationVisible
표시되고 있는 지역 내에 현재 위치를 표시할 수 있는지 없는지를 리턴합니다.
이 값은 read only 입니다.
Map functions
latitude, longitude = myMap:getAddressLocation( "gough and post, sf" )
latitude, longitude = myMap:getAddressLocation( "120 university, palo alto, ca" )
latitude, longitude = myMap:getAddressLocation( "eiffel tower" )
주어진 스트링으로 검색해서 그 위도와 경도 값을 리턴합니다. 이것은 구글 맵 HTTP 메소드를 이용하게 됩니다. 지도에 마커를 표시할 수도 있고 해당 지점이 중앙으로 오도록 할 수도 있습니다.
myLocation = myMap:getUserLocation
사용자의 현재 위치를 반환합니다. 그 내부의 값들은 아래와 같습니다.
myLocation.longitude
myLocation.latitude
myLocation.altitude
myLocation.accuracy
myLocation.time
myLocation.speed
myLocation.direction
myLocation.isUpdating -- a Boolean that flags whether the location is currently updating
myMap:setRegion(latitude,longitude,latitudeSpan,longitudeSpan,isAnimated)
화면에 출력하는 지역을 새로운 지역으로 바꿉니다.
myMap:setCenter(latitude,longitude,isAnimated)
화면에 출력하는 지역을 해당 위도 경도를 중앙으로 하는 지역으로 바꿉니다.
myMap:addMarker(latitude,longitude,{title="Displayed Title", subtitle="subtitle text"})
지도위 특정 지점에 핀을 표시합니다. 그리고 그 핀을 터치하면 위 텍스트가 표시됩니다.
myMap:addMarker(latitude,longitude)
특정 지점에 핀을 표시합니다.
myMap:removeAllMarkers()
핀을 모두 제거합니다.
Address Lookup from Position (Reverse Geocoding)
위도와 경도는 대략적인 주소값으로 바꿀 수 있습니다. 이것을 하려면 구글의 reverse geocoding server에 해당 값을 주고 원하는 값을 받는 작업을 해야 합니다. 그러므로 이 결과 값은 구글이 가지고 있는 자료의 정확성에 따라서 오차가 날 수 있습니다.
이 기능을 사용하기 위해서 mapAddress 이벤트 리스너를 activate 시켜야 합니다. 이 리스너가 액티브 상태이면 nearestAddress() 함수로 근처의 주소 데이터를 가지고 올 수 있습니다.
local function mapAddressHandler( event )
-- handle mapAddress event here
print( "The specified location is in: " .. event.city .. ", " .. event.country )
end
myMap:nearestAddress( latitude, longitude )
Runtime:addEventListener( "mapAddress", mapAddressHandler )
이 이벤트 객체는 다음과 같은 attributes를 가진 핸들러 함수를 리턴합니다.
event.street -- the street name
event.streetDetail -- the street number (or other specifier for location on the street)
event.city -- the city or town
event.cityDetail -- additional city information, such as neighborhood
event.region -- the state, province, or similar region within the country
event.regionDetail -- the region below the state level (e.g., the county, in the U.S.)
event.postalCode -- the postal code
event.country -- the country name
event.countryCode -- the standard country abbreviation
만약에 에러가 있으면 event.isError 에 true값이 할당 됩니다.
위 지도 이미지들은 각각 mapType을 normal, satellite, hybrid로 한 것입니다.
소스를 볼까요?
display.setStatusBar( display.HiddenStatusBar )
_W = display.contentWidth;
_H = display.contentHeight;
-- Create a native MapView (requires XCode Simulator build or device build)
-- You can create multiple maps, if you like...
--
myMap = native.newMapView( 0, 0, _W, _H )
--myMap.mapType = "normal" -- other mapType options are "satellite" or "hybrid"
--myMap.mapType = "satellite"
myMap.mapType = "hybrid"
-- The MapView is just another Corona display object, and can be moved or rotated, etc.
myMap.x = display.contentWidth / 2
myMap.y = 120
-- Initialize map to a real location, since default location (0,0) is not very interesting
myMap:setCenter( 37.331692, -122.030456 )
local function callMap()
-- Fetch the user's current location
-- Note: in XCode Simulator, the current location defaults to Apple headquarters in Cupertino, CA
local currentLocation = myMap:getUserLocation()
local currentLatitude = currentLocation.latitude
local currentLongitude = currentLocation.longitude
-- Move map so that current location is at the center
myMap:setCenter( currentLatitude, currentLongitude, true )
-- Look up nearest address to this location (this is returned as a "mapAddress" event, handled above)
myMap:nearestAddress( currentLatitude, currentLongitude )
end
-- A function to handle the "mapAddress" event (also known as "reverse geocoding")
--
local mapAddressHandler = function( event )
local locationText =
"Latitude: " .. currentLatitude ..
", Longitude: " .. currentLongitude ..
", Address: " .. event.streetDetail .. " " .. event.street ..
", " .. event.city ..
", " .. event.region ..
", " .. event.country ..
", " .. event.postalCode
local alert = native.showAlert( "You Are Here", locationText, { "OK" } )
end
-- A listener for the address lookup result
-- (This could also be a table listener on the map itself, in case you have more than one simultaneous map.)
Runtime:addEventListener( "mapAddress", mapAddressHandler )
timer.performWithDelay( 1000, callMap ) -- get current location after 1 second
첫 세줄은 status바를 없애고 화면 너비와 높이를 구한 부분입니다.
첫번째로 myMap이라는 변수에 mapView를 대입합니다. native.newMapview를 이용하는데요 이때 x,y,너비,높이 를 지정해서 표시되는 지도영역의 크기를 설정할 수 있습니다.
이 영역은 코로나의 display object로서 그 위치와 크기를 재설정 할 수 있고 여러개를 만들수도 있습니다. 경우에 따라서는 움직이게 할 수도 있겠구요. 만약에 필요하다면 말이죠.
그 다음은 setCenter 로 위도와 경도를 맞춰 줍니다. 그러면 그 위도와 경도가 화면 중앙에 표시 될 겁니다.
그 다음 callMap() 함수에는 현재 유저가 있는 위치와 현재 위치의 위도 경도를 구해서 이것으로 setCenter를 다시 해 줍니다.
그리고 가장 가까운 곳의 주소지를 얻어 옵니다.
그 다음 mapddressHandler 함수에서는 위도, 경도, 거리, 도시, 지역, 국가, 우편번호 등의 정보를 표시할 수 있도록 해 줍니다.
마지막에는 이 두 함수를 불러올 리스너들이 있습니다.
코로나 SDK의 mapView도 아주 간편하게 사용할 수 있네요.
이 소스를 기본으로 이것 저것 많이 시도해 보시면 좋을 것 같네요.
맥이 있어야 되고 xCode가 세팅 돼 있어야 되든가 아이폰 같은 애플 디바이스가 있어야 되는 한계가 있지만요.
그럼...
We desperately need a speed control as the animation just play crazy
앱을 쌈박하게 만들기 위해서는 애니메이션 스피드 조절 기능이 완전 필요합니다.
What is the best way to control the speed of the animation?
Would it be a case of using a timer and calling something like
myAnim:nextFrame()
애니메이션의 스피드 조절하는 가장 좋은 방법이 뭐지요?
myAnim:nextFrame() 함수를 타이머를 이용해서 부르는 것이 방법이 될까요?
@Paul – your suggestion would probably work well in some cases, although if you had more than a few clips onscreen, you’d want to test it on target devices to see the performance. I don’t think timers are necessarily that expensive, but they might add up if you had a lot of functions constantly polling the system time.
The movieclip library is primarily designed for a Flash-like model, in which there’s a global framerate for everything. For greater timing control, or for complex animation cases, we’d recommend using Game Edition and the sprite-sheet feature.
In addition to using texture memory much more efficiently (one big image rather than lots of little ones), that feature includes an animated-sprite API that lets you set different animation speeds for different sprites, or even for different sequences within the same sprite. Also, it’s a time-based API rather than frame-based, so the total animation time will remain the same even on slower devices that need to drop frames — the engine automatically handles all this under the hood.
@Paul - 당신의 방법이 잘 적용되는 케이스도 있을 거예요. 아마 무비크립이 적거나 특정한 디바이스에서만 테스트를 원한다면 더 그럴거예요. 하지만 내 생각엔 타이머는 앱을 좀 헤비하게 만들것 같네요.
무비클립은 플래쉬를 모델로 디자인 된 겁니다. 기본적으로 전체 frame rate가 있고 이것이 모든 무비클립에 동일하게 적용됩니다. 좀 더 타이밍 콘트롤을 하고 싶거나 복잡한 애니메이션을 원한다면 Game Edition과 Sprite sheet를 사용하기를 권장합니다.
더군다나 sprite API는 메모리도 효율적으로 운용할 수 있어요. 그리고 각 애니메이션 마다 다른 스피드를 줄 수도 있구요. 스프라이트 애니메이션은 time base 입니다. movieclip은 프레임 베이스이구요. 그래서 사양이 낮은 기계에서도 각 애니메이션별 스피드 차이는 동일하게 나타날 겁니다.
@Chan, You should use the Sprite library instead of the Movieclip library because it gives you better control over the animations. You do have a onComplete listener with Sprites.
@Chan, 무비클립 라이브러리 보다는 스프라이트 라이브러리를 이용해야 애니메이션의 속도 컨트롤이 더 수월합니다. 그리고 스프라이트에는 onComplete리스너도 있습니다.