Commit e5cee3e3 authored by Ryan Nowak's avatar Ryan Nowak
Browse files

Add animated map

Adds a library, delivery map component, and the ability to animate a
marker on the map.

This is very hardcoded for now, I'll loop back around to this once we
have support for ordering.
parent 873d72cc
......@@ -13,6 +13,7 @@
<ItemGroup>
<ProjectReference Include="..\BlazingPizza.Shared\BlazingPizza.Shared.csproj" />
<ProjectReference Include="..\BlazingPizza.OpenStreetMap\BlazingPizza.OpenStreetMap.csproj" />
</ItemGroup>
</Project>
@page "/myorders"
@implements IDisposable
<div class="main px-4 py-3">
<p>My orders go here.</p>
<DeliveryMap
Id="deliveryMap"
Height="300"
Width="300"
Center="@center"
Zoom="13"
Start="@start"
End="@end"
Driver="@driver" />
</div>
@functions {
Point center = new Point() { X = 51.5001, Y = -0.1239, };
Marker start = new Marker() { Description = "Blazing Pizza HQ", X = 51.5098, Y = -0.124, };
Marker driver = new Marker() { Description = "Your friendly Blazing Pizza driver", X = 51.5098, Y = -0.124, };
Marker end = new Marker() { Description = "Queen Elizabeth II Center", X = 51.49811, Y = -0.12863, };
bool animating;
int step;
int totalSteps = 20;
protected override void OnInit()
{
animating = true;
_ = UpdatePosition();
}
void IDisposable.Dispose()
{
animating = false;
}
async Task UpdatePosition()
{
await Task.Delay(TimeSpan.FromSeconds(1));
if (!animating)
{
return;
}
step++;
driver.X = start.X + (end.X - start.X) * ((double)step / (double)totalSteps);
driver.Y = start.Y + (end.Y - start.Y) * ((double)step / (double)totalSteps);
if (step == totalSteps)
{
animating = false;
return;
}
StateHasChanged();
_ = UpdatePosition();
}
}
......@@ -4,3 +4,5 @@
@using Microsoft.JSInterop
@using BlazingPizza.Client
@using BlazingPizza.Client.Shared
@using BlazingPizza.OpenStreetMap
@addTagHelper "*, BlazingPizza.OpenStreetMap"
\ No newline at end of file
......@@ -6,11 +6,13 @@
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/site.css" rel="stylesheet" />
<link href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css" rel="stylesheet" />
<title>Blazing Pizza</title>
</head>
<body>
<app>Loading...</app>
<script src="_framework/blazor.webassembly.js"></script>
<script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js"></script>
</body>
</html>
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.3</LangVersion>
<IsPackable>true</IsPackable>
</PropertyGroup>
<ItemGroup>
<!-- .js/.css files will be referenced via <script>/<link> tags; other content files will just be included in the app's 'dist' directory without any tags referencing them -->
<EmbeddedResource Include="content\**\*.js" LogicalName="blazor:js:%(RecursiveDir)%(Filename)%(Extension)" />
<EmbeddedResource Include="content\**\*.css" LogicalName="blazor:css:%(RecursiveDir)%(Filename)%(Extension)" />
<EmbeddedResource Include="content\**" Exclude="**\*.js;**\*.css" LogicalName="blazor:file:%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Blazor.Browser" Version="0.7.0" />
<PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.7.0" PrivateAssets="all" />
</ItemGroup>
</Project>
@inject IJSRuntime JSRuntime
<div id="@Id" style="height: @(Height)px; width: @(Width)px;">
</div>
@functions {
// leaflet.js requires a div with an id.
[Parameter] string Id { get; set; }
// leaflet.js requires an explicit size for the map
[Parameter] int Height { get; set; }
[Parameter] int Width { get; set; }
[Parameter] Point Center { get; set; }
[Parameter] double Zoom { get; set; }
[Parameter] Marker Start { get; set; }
[Parameter] Marker End { get; set; }
[Parameter] Marker Driver { get; set; }
bool initializedMap;
protected async override Task OnAfterRenderAsync()
{
// After we render, make sure the map is initialized for this element
if (!initializedMap)
{
await JSRuntime.InvokeAsync<object>("deliveryMap.initialize", Id);
await JSRuntime.InvokeAsync<object>("deliveryMap.setView", Id, Center, Zoom);
await JSRuntime.InvokeAsync<object>("deliveryMap.setMarkers", Id, new Marker[] { Start, End, });
initializedMap = true;
}
// If we already intialized the map, then all we need to do update the position of the driver.
await JSRuntime.InvokeAsync<object>("deliveryMap.setDriverMarker", Id, Driver);
}
}
\ No newline at end of file
namespace BlazingPizza.OpenStreetMap
{
public class Marker
{
public string Description { get; set; }
public double X { get; set; }
public double Y { get; set; }
}
}
namespace BlazingPizza.OpenStreetMap
{
public class Point
{
public double X { get; set; }
public double Y { get; set; }
}
}
@using System.Net.Http
@using Microsoft.JSInterop
@using BlazingPizza.OpenStreetMap
var tileUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var tileAttribution ='Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>';
// Global export
deliveryMap = {
maps: { },
initializeCore: function (id) {
var map = deliveryMap.maps[id];
if (map === undefined) {
map = L.map(id);
deliveryMap.maps[id] = map;
L.tileLayer(tileUrl, {attribution: tileAttribution}).addTo(map);
}
return map;
},
initialize: function(id) {
deliveryMap.initializeCore(id);
},
setView: function(id, center, zoom) {
var map = deliveryMap.initializeCore(id);
map.setView([center.x, center.y], zoom);
},
setMarkers: function(id, markers) {
var map = deliveryMap.initializeCore(id);
markers.forEach(function(m) {
var marker = L.marker([m.x, m.y]).addTo(map);
marker.bindPopup(m.description).openPopup();
});
},
setDriverMarker: function(id, driver) {
var map = deliveryMap.initializeCore(id);
if (deliveryMap.driver === undefined) {
var marker = L.marker([driver.x, driver.y]).addTo(map);
marker.bindPopup(driver.description).openPopup();
deliveryMap.driver = marker;
} else {
deliveryMap.driver.setLatLng([driver.x, driver.y]);
}
}
}
\ No newline at end of file
......@@ -8,6 +8,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazingPizza.Client", "Blaz
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazingPizza.Shared", "BlazingPizza.Shared\BlazingPizza.Shared.csproj", "{42410116-06C1-4D19-B5FC-BD1F85F918B3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazingPizza.OpenStreetMap", "BlazingPizza.OpenStreetMap\BlazingPizza.OpenStreetMap.csproj", "{77601C05-0A91-4895-A1A1-B5F90422DAB8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -54,6 +56,18 @@ Global
{42410116-06C1-4D19-B5FC-BD1F85F918B3}.Release|x64.Build.0 = Release|Any CPU
{42410116-06C1-4D19-B5FC-BD1F85F918B3}.Release|x86.ActiveCfg = Release|Any CPU
{42410116-06C1-4D19-B5FC-BD1F85F918B3}.Release|x86.Build.0 = Release|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Debug|x64.ActiveCfg = Debug|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Debug|x64.Build.0 = Debug|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Debug|x86.ActiveCfg = Debug|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Debug|x86.Build.0 = Debug|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Release|Any CPU.Build.0 = Release|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Release|x64.ActiveCfg = Release|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Release|x64.Build.0 = Release|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Release|x86.ActiveCfg = Release|Any CPU
{77601C05-0A91-4895-A1A1-B5F90422DAB8}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment