In this tutorial, we are going to use what we have learned in the Power Apps Canvas Map control post to build a little location guesser game.
This is what our game should look like at the end:
You can find the unmanged package of the final solution below:
But let’s do it from scratch.
- Pre-requisit
- Initiate your project
- Insert map control
- Set the start button
- Set map control actions
- Display result and move to next location
- Display the final score
- Conclusion
1. Pre-requisit
It means you need a premium licence to use it. However, if you are just curious about how it works and if you want to learn how to implement it, you can use the developer plan.
You probably should have a look at my whole article regarding the map control on PowerApps.
The geo-spatial features must be activated to use the map control.
Go to admin.powerplatform.com then select the environment which is going to hold your Canvas app with the map control.
Go to the settings > Products > Features and search for the Map and adress services part.
Limited will be enough for this tutorial.
2. Initiate your project
I have prepared an unmanged package with the container and locations pre-filled.
Import the solution into your environment.
Edit the PowerApp application, and let me explain the tree view.
Container | Description |
---|---|
ctnShowResult | Popin to show, while location clicked which display the result. |
ctnLocationToFind | Header container whoch containes the information of the location to find. |
ctnStartGame | Popin to show at the begining to initiate the fame and at the end to show the score. |
ctnMapOuter | Container which will contains our map control. |
Also, in App.Formulas, you can find a fx_loactions variable which will containes our cities, latitude and longitude of the cities. You can add or edit a city.
fx_locations = [ { name : "Paris", latitude : 48.866669, longitude : 2.33333 }, { name : "Chennai", latitude : 13.067439, longitude : 80.237617 }, { name : "Santiago", latitude : -33.308510, longitude : -70.114059 }, { name : "Seattle", latitude : 47.6062095, longitude : -122.3320708 }, { name : "Brisbane", latitude : -27.4710107, longitude : 153.0234489 }, { name : "Windhoek", latitude : -22.570000, longitude : 17.083611 }, { name : "Kuala Lumpur", latitude : 3.15977195, longitude : 101.709998 } ];
3. Insert map control
Click on ctnMapOuter, Insert then search for the Map control and click on Map.
Rename the map control mapSpot
Make it take all the parent container spaces.
Turn on Use default location
Adjust the start map position to center it in the world map by changing the default latitude to 20 and default longitude to 0.
Set the default zoom level to 2 to unzoom the map.
The road style (default style) displays cities if you zoom in, so let’s switch to satellite.
Turn off Compass control and Pitch control. We don’t need these options.
Turn off shabe labels. Sahre are going to be use to draw a line in between two points.
4. Set the start button
Click on the btnStartGame component and have a look at the OnSelect property.
So we must save user result in a collection, let’s say colLocationSpotted. To make sure our collection is going to match our input, we will ClearCollect our collection with the datas in formulas (fx_locations), then we will clear the collection. Now PowerApps now the input data format of the collection.
Then we will set the score to 0. Let’s name this variable gloScore.
We will create a variable gloToSpot which will be the variable of the city to find. Let’s set it with our first value un fx_locations.
// At first Connection, preset collection with fx_locations to have the right object format ClearCollect( colLocationSpotted, fx_locations ); // Restart collection spotted Clear(colLocationSpotted); // Set score back to 0 Set( gloScore, 0 ); // Set the actual city to spot to empty Set( gloToSpot, First(fx_locations) )
When you click on start, we want this popin to disapear.
The idea is when we are looking for a spot hide it, if we are not looking for a sport, display it.
Select the container, go to visible parameter and we want to hide this container if gloToSpot is blank or error.
IsBlankOrError(gloToSpot.name)
We need to let the user knows which spot he has to find.
Go to the text component txtCanYouSpot, and in the Text properties, let’s display gloToSpot.
And instead of showing nothing on the start popin, let’s put a message “Click on start to play”.
If( IsBlankOrError(gloToSpot.name), "Click on start to play", "Can you spot: " & gloToSpot.name )
5. Set map control actions
When an user click on the map we want:
- Save the result clicked
- Show the current spot he has to find
- Draw a line in between these two points
To save the result, when clicked on the map, we want:
- The spot the user has to find
- The latitude he clicked
- The longitude he clicked
- The score. For the score we are going to calculate the distance in between GPS point by using Pythagore theroem. And will calculating distance in between two points. We are going to turn into non-negative number (Abs)
To show the current sport he had to find and the result, we are going to store both of them into a collection. Set the color red for the one he has to find and blue for the guesses.
And then, we are going to collect the shape of the line. To find out the geojson, I have simply draw a line before, export the geo json and change with my attributes. See my post regarding the map control.
Finally we are setting a variable to display the result.
To do so, on the attribute OnMapClick of the map, paste the code below:
// Save its result Collect( colLocationSpotted, { name: gloToSpot.name, latitude: mapSpot.ClickedLocation.Latitude, longitude: mapSpot.ClickedLocation.Longitude, score: Round( Sqrt((Abs(gloToSpot.latitude - mapSpot.ClickedLocation.Latitude) * Abs(gloToSpot.latitude - mapSpot.ClickedLocation.Latitude)) + (Abs(gloToSpot.longitude - mapSpot.ClickedLocation.Longitude) * Abs(gloToSpot.longitude - mapSpot.ClickedLocation.Longitude))), 0 ) } ); // Get two points to display ClearCollect( colSpotAndToSpotPoints, { name: gloToSpot.name, latitude: gloToSpot.latitude, longitude: gloToSpot.longitude, color: RGBA( 255, 0, 0, 1 ) }, { name: "Your guess", latitude: mapSpot.ClickedLocation.Latitude, longitude: mapSpot.ClickedLocation.Longitude, color: RGBA( 0, 0, 255, 1 ) } ); // Draw a line (shape) in between the two points ClearCollect( colShapes, { name: "", geojson: "{ ""type"": ""Feature"", ""properties"": { ""label"": ""Distance " & gloToSpot.name & " to your guess"" }, ""geometry"": { ""type"": ""LineString"", ""coordinates"": [ [ " & gloToSpot.longitude & ", " & gloToSpot.latitude & " ], [ " & mapSpot.ClickedLocation.Longitude & ", " & mapSpot.ClickedLocation.Latitude & " ] ] } }" } ); // Display results UpdateContext({locShowresult: true})
Now we have set our collections. We need to set the Locations(Items) of the map control. We want to display the sport he has to find and the user guess. So Set this attribute do colSpotAndToSpotPoints.
Let your map know, which key of your json match which value. In the advnaced parameters of the map control, you need to set the following values:
Parameters | Value | Description |
---|---|---|
ItemsColors | “color” | The color of the Pin on the map is going to take the value of the key “color” of the collection set in Locations(Items) |
ItemsLabels | “name” | The name of the Pin on the map is going to take the value of the key “name” of the collection set in Locations(Items) |
ItemsLatitudes | “latitude” | The latitude of the Pin on the map is going to take the value of the key “latitude” of the collection set in Locations(Items) |
ItemsLongitude | “longitude” | The longitude of the Pin on the map is going to take the value of the key “longitude” of the collection set in Locations(Items) |
If you test it you can now see your two points on the map:
To draw the line in between the two points, we need to set the Shape_Items of the map control.
In mapSpot’s advanced parameters, find Shape_Items and set it to colShapes. Then find ShapeGeoJSONObjects and set it to “geojson”. Geojson is the key from the collection colShapes which contains the data to draw the line.
6. Display result and move to next location
The first thing to do is to use locShowResult, which has been set in part 5. Set map control actions, to display ctnShowResult.
Go to the Visible parameter of ctnShowResult and add the reference to the variable.
In the text component txtKmInfo, display the score. Go to the Text parameter and lookup to the score we saved for this spot in colLocationSpotted.
"Your score is "&LookUp(colLocationSpotted, name = gloToSpot.name,score)
In the next button, we want to add the current score to global variable which contains our global score, give a user the next city he hasn’t play with yet. Remove the pins and shape of the last guess.
On the button component, btnNext, in the OnSelect parameters add the following code:
// Add distance to score Set( gloScore, gloScore + LookUp(colLocationSpotted, name = gloToSpot.name,score) ); // Set the actual city to the next one Set( gloToSpot, LookUp(fx_locations,Not(name in ShowColumns(colLocationSpotted,name))) ); // Empty pins to show Clear(colSpotAndToSpotPoints); //Empty Shapes Clear(colShapes); // Hide score panel UpdateContext({locShowresult: false})
Try it out.
7. Display the final score
Let’s finish with displaying the final score. In the Visible of txtYourScore add the following code. Which means display this componenent if we have a global score.
Not(IsBlankOrError(gloScore))
In the Text parameter of txtYourScore, display the final score.
"Your score is " & gloScore
8. Conclusion
Well done. You have finished this tutorial.
The main keys of the tutorial were:
- Insert and set the map control
- Insert Pins and Shapes
- Interactions with the map control
You can always check the post Power Apps Canvas Map control to go further.