YCanvasMaps
6 months before today I released and open sourced YCanvas library. Since it powers some of my projects nicely (onBoard, Train Lord), some of you requested me to create map implementation as well as Feathers UI component so you can easily integrate it into your own projects. I have decided to take this challenge and wrapped the original library by some more specific functionality. It took me some time, but finally, the extended library is out and ready to be used in any flash, AIR or mobile project.
Sources of the new library called YCanvasMaps is available from repository. It extends the original lib and introduces some tools for easier integration:
- Component implementation that can be added into Feathers scene.
- Advanced mouse and touch transformation managers for panning and zooming the map with gestures.
- Layer for adding markers over the map.
- Stroke implementation and stroke layer for adding strokes.
- Partition (map tile) implementation with smooth revealing.
There are two application projects available – web and mobile. The web version is also available online on ycanvas.yoz.sk/maps. The mobile version can me compiled from sources and deployed to Android or iOS device. Both reuse the same sources and explores the possibilities with YCanvas maps:
- Feathers components to controll the map.
- Demo map tile configurations using tiles from various providers like OpenStreetMap, MapQuest, ArcGIS…
- Big map with strokes and markers implementation.
- Overlay map that can load additional tiles over the main map.
- Small map that keeps synchronized with the main one.
- Example of long routes rendered as strokes (Rome to Paris…)
Watch YCanvasMap running on Android (Samsung Note 10.1):
Both, the web and the mobile version runs smooth at 60 fps when compiled for release. I tried to write documentation (asdoc) right into the code so it may help you with your implementation, in case it does not feel free to contact me.
Jozef,
This is AMAZING! Well done! [drool]
I can’t wait to start playing with this.
wow,
thank you very much , just about to try to make map app
very good lib and example
thanks again
this is great, can this support google maps?
hi radu, it can support any map tile provider while:
– bitmap tiles are provided (latest google implementation uses vector data instead of tiles)
– crossdomain.xml is available (bitmapdata is accessed in order to be uploaded to gpu)
related to google:
– there are still implementations using tiles see https://developers.google.com/maps/documentation/javascript/examples/map-simple
– google does not provide crossdomain.xml afaik, so you can not use it with YCanvas in webbrowser, however it should be ok on mobile devices.
– have a good look at google policy/rights
why are you interested in google tiles specificaly?
Hi,
I just discovered ycanvas, and I have to admit that I am really really enthusiastic about it. You did a great job, thank you !
I’m working on a project that uses OpenScales for now, but OpenScales doesn’t use the GPU so it’s extremely laggy 🙁 So i’m considering to use ycanvasmap instead !
I have hower one question : is it possible to use local OSM tiles instead of the provided servers ? My application must be usable without an internet connection 🙁
Thanks in advance !
Hi Jul,
I think there should be no problem accessing local tiles instead of those on internet. So, how do you access your tiles locally? If via local http, than it is as easy as update some links in Maps.as
What I would like is to access the files directly from the file system (the tiles are on the sdcard of an Android tablet). If possible without using http.
should be possible as well. You should be able to access filesystem from air app http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118666ade46-7fe4.html – update Partition.load() method to access the system instead of requesting url
Oh. My. God.
In fact that does work without updating Partition.load() ! All I had to do is add an entry in Maps.as like this :
public static function get OSM2():MapConfig
{
if(!_OSM2)
_OSM2 = createMapConfig([
“file://”+File.documentsDirectory.nativePath+”/myMaps/${z}/${x}/${y}.png”]);
return _OSM2;
}
And that works like a charm ! That’s sooo awesome ! Thank you !
Let’s see if I can fully replace OpenScales 😉
Btw I don’t know if it’s normal or not but on GitHub the file “YCanvasLibrary.swc” is missing 🙁
Jul, great to hear it was that easy. I would not expect URLLoader would work with filesystem, but cool!
Regarding .swc, I decided not to upload these binaries into the source repository while one can compile them himself easily
Great work Jozef ! Currently playing with YCanvasMap for an upcoming mobile app 🙂
Getting the thing to work in my app was easy and straightforward, but for some reason it refuses to show up when added in a Feathers Screen (and using a ScreenNavigator and a Slide transition).
Did you try that already ? Any idea what might go wrong ? I’m going to sleep right now but will look further into this tomorrow evening.
hi Mate,
I believe invalidating viewport should do the job for you. have a look at MapDisplay.invalidateStarlingViewPort() method. This method needs to be called manualy when the map viewport is changed related to global/starling coordintes (e.g. when parent display object is moved – should be the case with ScreenNavigator with Slida transition)
Made a typo on my pseudo yesterday ^^
Exactly, I already do the display.invalidateStarlingViewPort() in the draw() function of the screen. If I resize my window slightly once the screen is displayed then the YCanvasMap shows up nicely.
The problem seems to be that the Screen’s draw() function is called once, then the screen gets animated by the TransitionManager and draw() never gets called again since there is supposedly no need for it.
Gonna look into finding a smart way to handle that 🙂
I’ll probably modify some of your code a bit as the eventListeners on the stage are a bit troublesome right now : I don’t display the map all the time, so for now I just commented out the hitTest on every click in the MouseTransformationManager… hacking my way through for now, then I’ll clean up !
Thanks !
Well, listening for FeathersEventType.TRANSITION_COMPLETE on the ScreenNavigator when showing up the map screen works pretty good 🙂
yep, FeathersEventType.TRANSITION_COMPLETE sounds good. YCanvas works using its flash-global view port rectangle. this one needs to be invalidated whenever any property of this rectangle is being changed – final tween event sounds good. Go ahead and update any code you need, if you find some places to optimize it, feel free to push on github.
btw may I know which starling version did u use ?
brainzzz168, the latest code in master is using 1.4rc, but there is a tag in repo called 1.3 that use that version. so you can use the one you like, or even do merge of latest code into 1.3 because there has been some improvements since
thx , since it’s looks like feathers 1.1 got some rectangle conflict with starling 1.3
I’ll try the newest starling
Jozef,
I got the latest version from http://ycanvas.yoz.sk/maps/ up and running as a mobile app (running in simulator on my Mac Book Pro). I can’t seem to PAN the map like I can from the website. Any idea what might be wrong?
I haven’t modified anything. In the resize function I even added:
mapMain.transformationManager.allowMove = true;
but it has no effect.
Mike
mikeciz,
the code should run out of the box (allowMove should be true by default). I havent tested it on simulator but rather on real devices. One finger gestures to pan the map, two fingers to pan and zoom. Does your simulator properly dispatch touch events? you should be able to check that out with some breakpoints in trainsformation manager
Good idea. I tested it on my tablet and it works wonderfully! YCanvas is wonderful! The previous version I had worked on the simulator. Any idea what had changed to make that stop working? My thought is that I’d like the app to run on both tablet’s and desktops (AIR).
mikeciz,
great to hear it works for you now. YCanvas should work for both mobile and desktop air out of the box. With air you do not even have to care about crossdomain.xml files, so you will be able to access google map tiles as well. I am not sure about the issue with simulator but I may take a look once I have some spare time and a mac 🙂
Hi Jozef, I’m back !
First, a huge thank you for YCanvasMap, I fully implemented it in my project and that works like a charm. It’s a really really great job 🙂
I have a little question : I want to display a circle on the map that shows a range (for exemple : 10 meters around a point). Do you have an idea how I could do that ? I successfully displayed a circle on the map, but there’s 2 main issues :
– I don’t know how to convert x meters to y pixels ?
– How to manage the zoom on the map ? The circle should be smaller when we’re zooming out and bigger when we’re zooming in…
I checked your “GeoUtils” class but couldn’t find a method that do what I want 🙁
Thanks in advance !
Jul’
hi Jul, welcome back,
its good to hear you have good progress with the lib. So, “how to convert x meters to y pixels ?”
1. GeoUtils.y2lat(center.x) returns lat of current position
2. GeoUtils.pixelsPerMeter(lat) returns resolution at base level/zoom according to provided lat
3. lets say GeoUtils.pixelsPerMeter(lat) returns 5 and you want to draw circle with radius = 100 meters, then simply 5 * 100 = 500 pixels is your radius.
4. use MapLayer (see MapHelperMain.polygonLayer) to add your polygon/circle with proper radius in pixels. You do not need to care about zoom in your Circle class, MapLayer handles that.
As you said, the circle will scale according to zoom as well as according to lat. Beware that even with the same zoom, circle with radius 100 meters will have different size close to poles than on equator. more details about mercator projection here http://en.wikipedia.org/wiki/Mercator_projection
Hi,
Thanks for your answer ! It’s just perfect, that’s exactly what I wanted ! That’s awesome. !
I have another question/remark for you : are you sure that the method “distance” in your GeoUtils class is working ? I tried to use it with these parameters :
GeoUtils.distance(7.16552, 47.36683, 7.16627, 47.36618)
and it returns a distance of 6217.96 meters. However, there’s something like 100 meters between them, not 6000 🙁
Have a nice day !
Hi Jul,
GeoUtils.distance takes arguments in radians. Use GeoUtils.distanceDeg if you work with degrees. Also make sure the order of args is correct (lon1, lat1, lon2, lat2)
Ha, that works great now ! Thank you !
you are welcome!
Joz,
YCanvas is working beautifully for us! Many thanks. I’m stuck on one particular thing. I have the possibility of a map with thousands of markers on it. It works, however, the gui can get a little sluggish as you might expect. What I don’t understand is that the entire app gets slower even when I’m not moving the map around.
For example, if I add a simple popup dialog on the screen above the map it comes in slower.
Is there some background redrawing of the map even though it isn’t changing that I’m not aware of?
I’m going to add a function to make visible = false for markers outside the bounds of the screen. That helps a TON but I still have the situation where the map is zoomed farther out and needs to show lots of markers.
Mike
hi Mikeciz,
the way how YCanvas/starling/stage3d works it redraws all the stuff for every frame, even when there has been no change. You can check out some optimization techniques on starling forum. Here are just few of my toughs to improve the performance:
– reuse the same texture for markers, do not create new one for each
– mouse movement can affect the performance in case there is a lot of taouchable elements. starling tries to calculate target object everytime/perframe you move your mouse. try disabling touchable for each element you do not need to be
– chrome PPAPI flash plugin is very slow with stage3d, if it is your case please vote here https://code.google.com/p/chromium/issues/detail?id=309540
good luck with your app. feel free to share when done
Thanks for the reply. I was able to come up with a good solution. I created a worker (multi threading, yeah!) that sets visible=false for all the markers off the screen AND groups markers that highly overlap and the current scale.
great stuff Mikeciz
Hi Jozef;
Thanks for the amazing YCanvas. Im working with starling and the performance is superb! congrats!
Im working with feathers too and i have a question.
when i use the maps with feather’s drawers, i cant click on the openned menu because the maps touch is overlayed. How can i disable the maps touch to use the underneath menu?
thanks !!
I got it!
I look deep in the classes to find out where are the Touch code to disable them, but i found a more simple solution.
For those who have the same problem, here is what i do.
I just put “_display.touchable = false” when the drawer is open and when i close it i put the option back to “true”.
thanks!
Hi Josef,
Thank you for your wonderful code/piece of art you share. I use YCanvas displaying map on mobile device but I experience problem on pinch zooming. When pinch to zoom it was not centered where the point located. It’s little bit off.
Please guide me how to fix this issue.
Many thanks.
hi Je,
have a look at MobileTransformationManager available in ApplicationExplorerAndroid. That manager uses pinch to zoom and the “lock point” is the touch point that does not move
Hi,
first of all, thanks for the great component. I’ve just started playing around with it and it works quite fine, even on my old iPhone4 🙂
One question: I’m using Starling/Feathers for displaying the YCanvas map. Unfortunately, I can’t move the map on Desktop/simulator – on the device itself it works just fine. What do I have to do to enable moving the map on Desktop?
Many thanks,
– Stephan
hi Stephan,
you can use mouse or touch (or any other implementation) to control the ycanvas. have a look at https://github.com/jozefchutka/YCanvas/tree/master/YCanvasMapLibrary/src/main/actionscript/sk/yoz/ycanvas/map/managers you will find MouseTransformationManager and TouchTransformationManager that will help you get started
Hi Jozef,
I hope you’re doing well !
I still use YCanvasMap in my application and it still works like a charm, thanks again for your great work !
I have a small question for you : is it possible to scale the map so it always shows the same “area” regardless of the resolution of the device ?
I don’t think my explanation is very clear so let’s take an example : in my app I show a map of a city (let’s say Paris) and I don’t let the user zoom in or out. To do this I disable the zoom in the transformation manager and I set the scale of the map to 1/370 (I use local tiles of level 10). I have a few markers on the map too.
My problem is that the map is never scaled. So if I launch my app on a device with a low resolution (for example 1280×800), the map will display only the city and will be quite big on the screen (that’s what I want). But if I launch the app on a full HD screen (1920×1200), the map will be quite smaller and I’ll see a lot more area around the city. That’s normal because the tiles will still be 250px wide.
Is there a proper way in YCanvasMap to scale up the map to 1.5 so the same area is displayed on both screens ? I found out that if I set the scaleX/scaleY to the Starling.root I have the result that I want, but then the map doesn’t work correctly anymore (the zoom and the possibility to center the map are fu**ed up). And that scales up all the other Starling component, that I would prefer to resize manually).
Thanks in advance for your help and if you don’t understand what I mean or if you need more informations don’t hesitate to contact me !
hi Jul,
there is no exact method build in. You can however simply implement it on your side. For smaller areas like cities its sufficient to multiply map scale by the amount of pixels based on your base device. So if the maps is ok on your 800×600 device and you want to show it on 1920×1080 device, use some simple formula for scale. I.e.
Thanks for your answer, it’s very right and that seems to do the trick ! My only problem now is that for the Ipad, it zooms a little too far and it doesn’t use the level 10 tiles, but it uses the level 11. Is it possible to force YCanvasMap to use a defined level ?
Jul, for retina displays, have a look at LayerFactory.getLayerIndex() method and related asdoc on https://github.com/jozefchutka/YCanvas/blob/master/YCanvasMapLibrary/src/main/actionscript/sk/yoz/ycanvas/map/layers/LayerFactory.as#L50
That’s exactly what I needed, thank you sooo much !
Jozef,
How would you recommend pinning an image to a specific region on the map?
Would it be possible to fill a polygon with a texture?
My main application is for nautical charts. I have a PNG of a nautical chart and I know the Lat/Long of each corner pixel, so how can I pin the corners of the PNG to its corresponding Lat/Long positions on the main map?
Thank so much for your work on YCanvas its awesome!!
Brendan
Hi Brendan, it has been a while since I worked on that lib, however there is a demo you can use to get some ideas. Have a look at http://ycanvas.yoz.sk/markers/ , start clicking on the map and notice these pins are added and would remain on the same position when you zoom/pan the map. Sources for this app can be found here https://github.com/jozefchutka/YCanvas/tree/master/ApplicationMarkers
Hello,
I’M using ycanvas map for a mobile app and i try to add another tile layer, for now i have 18 layers (from exemple setting) is it possible to do this ?
I post another message, but not in the right place sorry for that… this is à short version.
Hi! Congratulations for the game. Want to report a problem with the income. I get the money only if i stay online. If I dispach the trains and close the page I dont get any money when the trains reach their destinations.