JS map with regions - javascript
Afternoon,
I have a requirement to have an interactive map where you can hover over a region (Australasia, East & South East Asia, South Asia etc.), have a "tooltip" or "hoverbox" with some info and then click and get redirected to a region page.
I started looking at Google Visualisation GeoChart with the intention of hijacking the click event but you can only select countries not regions.
Any suggestions for a JS library etc?
Many thanks.
I ended up using http://jvectormap.owl-hollow.net/ and overriding the onLabelShow, oRegionOver, onRegionOut and onRegionClick methods. Quite a simple and elegant plugin.
Well one way is to set the map as background image of a div and match its dimension using CSS. Then register a mouse move listener over that div. Now whenever the mouse moves check its coordinate and using that figure out which region is under it.
Now it would be interesting to crack the second problem. How to store the dimension of an irregular shape. Well one way could be divide the image into grids, could be one pixel thick or multiple pixels, depending on how much accuracy you need. Then store it in an array like (0 => (1, 5), 1 => (0, 6),..). In this case it says, for row 0 the region starts at column 1 and ends at column 5. On row 1, the region starts at column 0 and ends at 6; and so on.
I hope this make sense.
Related
In photoshop scripting how do you loop each selection and apply a gradient effect during each iteration?
Please ignore the blue line. Basically, I want to use select > color range or magic wand to make some selections and for each selected patch I would like to apply some gradient in the center of the patch. Pseudo code would be: select current active layer apply color range or magic wand selection for each sub selection in main selection: do: calculate the center coordinate of the current sub-selection area apply a custom gradient using the coordinate as the starting point I am not sure if this is do able because I don't know if the color range or magic want selection contains "sub-selections". By sub-selections I mean each individual patch in the above image.
There're no sub-selections, however you can transform selection to Path object, each individual path can be used for iteration. Depending on selection you have (color range may give semi-transparent selections), you may want to save current selection as a separate channel first and modify the selection to make it 100% non-transparent. To calculate center, I guess something like this should work: Find centerpoint of polygon in JavaScript because you can get all the coordinate for control points of each subpath. And then you'll need to create selection islands one by one so that gradients won't influence each other. To do that you can use path points as points for Lasso selection and then intersect these lasso-selections with original selection channel to regain lost transparency.
enlarge / animate map or change viewBox
i have this http://bl.ocks.org/nkhine/raw/3150901/ where if you click on a country the code re-renders the map (only USA, UK and Afganistan topo files present) i am stuck on how to animate the 'country' so that it 'moves' to the center of the screen and also fit the map to the users' viewport? what i am doing is to fadeout and then remove the 'svg g' element for the id='countries' https://gist.github.com/nkhine/3150901#file-client-js-L120 and then add the id='country' within which i am drawing the country based on the topo file provided. i tried to remove the entire svg and re-create it, but this does not 'feel' to be the correct approach! what would be the correct way to alter the viewBox without having to redraw the entire SVG? any advice much appreciated
I believe you need to change your .on("click") function to translate the image using the centroid of the country that has been clicked on, see the d3 example here http://bl.ocks.org/mbostock/2206590.
Google Maps polygon/overlay - deleting
As a follow-on to a previous question... I am having no luck deleteing an overay that I have drawn on the map, so that I can start over. My sequence: 1) draw the map 2) the user selects a city 3) I make an ajax call to get the boundary coordinates for the selected city, and within the ajax success block, I draw a boundary around that city - to be complete, I draw a polygon on the map that completely covers the viewport, except for a "hole" punch in it that exposes the city. Great, so far 4) The user selects a new city 5) Same ajax call, but it starts with trying to wipe out the overlay by setting the "map" to null. That doesn't work. The new city has a border around it, but the overlay has become darker, and the original "hole" is still poked through. I'm using: negativeSpacePolygon.setMap( null ); to try and clear out the overlay. What am I missing?
See the "hide"/"show" buttons on this example from your last question: http://www.geocodezip.com/v3_polygon_example_complex_hole.html
Making Javascript TileEngine Scrollable in Canvas
The basis for the code is from John E. Graham's blog http://johnegraham2.com/blog/2010/09/25/project-javascript-2d-tile-engine-with-html5-canvas-part-4-using-zones-for-further-optimization/ It works perfectly for drawing a screen's worth of tiles, but I cannot for the life of me figure out how to adjust it 1 row/column at a time based on pressing up, down, left, or right keys. Here is an example with the transparency to help visualize the zones http://simplehotkey.com/Javascript/canvas.html (loading positions of 1,188 tiles but only draws a couple hundred to fill the screen) I had it loading an array with 70,000 entries and it was still quick because it's only drawing whats on the screen, but cannot figure out how to slide everything based on input... I've come up with a couple ideas and am not sure what's the best way. One screen worth of tiles is shown here: tilesArray = [ 0,0,0,0,0,0,0,1,2,9,6,0,0,7,0,0,1,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0,9,0, 0,9,9,9,9,9,9,0,7,2,0,0,0,0,0,1,2,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,0,7,2,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]; Where 0 is a wall tile (around perimeter), 9 a floor tile, 7 a door and a couple other random tiles. That is exactly what is loaded to the screen, but I cannot figure out how to shift everything 1 tile in either direction based on input, up, down, left, right. The one idea I'm leaning towards now, is just to use that array above as the basis for rendering, and somehow feeding the new values into it based on keyboard input, from another array. Maybe slicing from another, much larger array (holding all the tiles for the entire level) and using that slice to populate the array that's actually rendered??? That's replacing every tile every frame though... for getting player input I was using: //Key listener document.onkeydown = function(e){ e = e?e:window.event; console.log(e.keyCode + "Down"); switch (e.keyCode){ case 38: //UP KEY Game.inputReaction('up'); //Game.moveDir('up'); break; case 40: //DOWN KEY //Game.inputReaction(40); //Game.moveDir('down'); break; case 37: //Left Key //Game.inputReaction(37); break; } } The other alternative is to try to adjust the tiles already on the screen and add new tiles but this engine isn't using global variables so I'm not sure how to affect the tile engine programatically based on input....like I can add another method (inputReaction(num)) and trigger some actions from my keyboard input (console.log()) but I can't access the other methods actually drawing the tiles. Or maybe I have to make a copy of the object, change it and return it? but it's pretty complex. I think it might be easier to adjust the array values that are being fed into the "engine" (array above) rather than changing around how the engine is calculating what's being drawn. Can you confirm this?
Add a camera abstraction that you can move around on the map, then shift the drawing positions according to the camera position. When the camera moves south 10px, all tiles move north 10px, same with east and west. Since you only draw the tiles that are visible, there won't be much of a performance loss. The renderer looks at the camera to figure out what needs to be drawn and you can expose the camera object to the outside to manipulate it. That way you only need to change the camera position to change what is shown on the screen. I did this in a proof of concept tiling engine a year ago and I was able to smoothly scroll and scale huge tilemaps. If you start changing the array itself, your performance will suffer and you won't be able to scroll smoothly since you can only go in steps of one tile and not one pixel.
How can this object be appended to a specific tile on an isometric map?
I have an isometric map that has selectable tiles. The map is formed by a matrix such as $('div').gameMap({map:[[{"tile":"tile_0","object":"anObjectOnTile"},{"tile":"tile_3","object":""}], [{...}]],mapsize:3}); If the tile has something within the object:"", then that tile has that object (in my case, an image of an oil derrick) on top of that tile. There is a Place button which when clicked should place an oil derrick object on top of the currently selected tile. However, I have run into two problems: Knowing which tile is currently selected Adding a single oil derrick At first I wanted to figure a way to modify the map's matrix to insert the object's name (oilDerrick) into the tile's object parameter, but now I think the better solution would be to append the oilDerrick to the tile. I can't figure out how to append to the particular tile and not every tile. I've got the code set up to look at and play with: http://jsfiddle.net/briz/jdhPW/13/ There's an oilDerrick object set up in the map's matrix for you to view, which can be removed by deleting the word oilDerrick in the matrix I played with $(".tile").append($('.oilDerrick')); though I knew that would append to every tile. But I simply do not know enough about appending yet to figure out how to limit it to a single instance. Each tile has a unique ID. I also tried this in order to add an oilDerrick to a certain tile: $("#placeButton").click(function() { for (var y in config.map) { for (var x in config.map[y]) { document.getElementById(obj.attr('id') + '_tile_' + x + '_' +y).appendChild(".oilDerrick"); } } } But this came to no avail as well. I think I'm heading in the right direction though? Can anyone help?
I did some modifications. There a little mess in your code. For example, your using jquery but there is a lot of direct DOM manipulation. .style.background = ... // should be .css("background",...) And the most important: document.getElementById(...) // should be $("#...") Easier, don't you think? Then, the problem is simple solved by creating a var currentTile and when the user select one tile, it save it. When click in 'place', $(currentTile).append($('.oilDerrick')); And the oil derrick move to where to selected tile. Anyway, more details you can see in the link.