问题
Hello I want to make a flash map of Europe where when you mouse over or out of each country something will happen, like changing the color of the country.
See this image
If I roll over Norway and then Sweden, Sweden will not be set to blue because Norway's bounding box is on top of Sweden, so I have to go a bit lower to roll over Sweden where it does not instersect with Norway.
Is there a better way to achieve the same functionality? Like using Bitmap pixels.
I have a sprite sheet of all cointries in png format. I embed this sprite sheet and than create Sprite AS3 class that uses copyPixels() to copy from the sprite sheet to innet variable BitmapData.
Here is my class
public class Country extends Sprite
{
private var newBitmap:Bitmap;
private var tintColor:Color = new Color();
public function Country(bitmapData:BitmapData)
{
newBitmap = new Bitmap(bitmapData);
tintColor.setTint (0x0000ff, 0.6);
this.useHandCursor = true;
this.buttonMode = true;
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void
{
addChild(newBitmap);
addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
}
private function onMouseOver(e:MouseEvent = null):void
{
newBitmap.transform.colorTransform = tintColor;
}
private function onMouseOut(e:MouseEvent = null):void
{
newBitmap.transform.colorTransform = new ColorTransform();
}
}
bitmapData is created at runtime using copyPixels() like this
var countiresArray:Array = Resources.allCointriesJSON["frames"];
var newX:Number = countiresArray[i]["frame"]["x"];
var newY:Number = countiresArray[i]["frame"]["y"];
var newW:Number = countiresArray[i]["frame"]["w"];
var newH:Number = countiresArray[i]["frame"]["h"];
bitmapData .copyPixels(Resources.allCountries.bitmapData, new Rectangle(newX, newY, newW, newH), new Point(0, 0));
where newX,NewY, newW and newH are taken from exported JSON file that is created when using TexturePacker
回答1:
Without converting your country images to vectors, you will need to check the alpha values of pixels under the mouse to get accurate interactions. Luckily, someone's already written and open sourced a utility that should do the job: InteractivePNG.
You'll just need to put your bitmaps inside an InteractivePNG
instance instead of a Sprite
.
回答2:
I had a similar problem but with an interactive object. The solution was to have a image that acted as a map for the clicks. This is a technique used in OpenGL for detecting clicks on 3d objects and scenes.
For example in your case, you'd have an image with all the countries. This image would not be loaded in the display list. Each country would have an exact different color. for example Sweden would be 0xff0000
, Norway 0x00ff00
, etc. Let's call this image colored-map.jpg
Then after clicking on the Europe-map.jpg
, the one that the user sees, you'd check the mouse coordinates, and then go look in the colored-map.jpg
to know the color of the clicked pixel. Then you'd know which country the user clicked, and could overlay the Norway.png
.
This technique is way better in performance terms that having lots of PNGs in the display list. At any time you would only have the Europe-map.jpg
, maybe 1 PNG of the selected country, and then the colored-map.jpg
loaded into a Bitmap
object. If you are targeting mobile performance optimization is a must.
Check this function. It's just as an example to get you going... it's not a full implementation.
var countriesArray = [{color:0xff0000, image:"Norway.png"},{color:0x00ff00, image:"Sweden.png"}];
public function checkPoint(mouseX,mouseY):String {
var testPixel:uint = coloredMap.bitmapData.getPixel(mouseX,mouseY);
for (var country in countriesArray) {
if( country.color == testPixel ) {
return country.image;
}
}
return null;
}
来源:https://stackoverflow.com/questions/17260893/making-a-flash-country-map