update move. scale mapping
This commit is contained in:
parent
2640fb92c1
commit
93097412b0
|
|
@ -1,22 +1,7 @@
|
|||
@inject HttpClient Http
|
||||
|
||||
<style>
|
||||
.selected {
|
||||
background-color: #3399ff !important;
|
||||
}
|
||||
|
||||
.selected > td {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.selected > td .mud-input {
|
||||
color: white !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="d-flex flex-row w-100 h-100 overflow-hidden">
|
||||
<MudTable @ref="Table" Items="@MapsShow" T="MapDto" Dense Hover ReadOnly FixedHeader RowClass="cursor-pointer" Striped Elevation="10"
|
||||
ServerData="ReloadData" Loading=@IsLoading RowClassFunc="@SelectedRowClassFunc" OnRowClick="RowClickEvent" Height="90vh" HorizontalScrollbar>
|
||||
<MudTable Class="h-100 w-100" @ref="Table" Items="@MapsShow" T="MapDto" Dense Hover ReadOnly FixedHeader RowClass="cursor-pointer" Striped Elevation="10"
|
||||
ServerData="ReloadData" Loading=@IsLoading Height="88%" HorizontalScrollbar=true>
|
||||
<ToolBarContent >
|
||||
<MudText Typo="Typo.h6">Maps</MudText>
|
||||
</ToolBarContent>
|
||||
|
|
@ -63,10 +48,8 @@
|
|||
</div>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
private string txtSearch = "";
|
||||
private bool IsLoading = false;
|
||||
|
||||
|
|
@ -137,29 +120,4 @@
|
|||
MapsShow = tasks.Skip(state.Page * state.PageSize).Take(state.PageSize).ToList();
|
||||
return Task.FromResult(new TableData<MapDto>() { TotalItems = tasks.Count, Items = MapsShow });
|
||||
}
|
||||
|
||||
private void RowClickEvent(TableRowClickEventArgs<MapDto> tableRowClickEventArgs) { }
|
||||
|
||||
private string SelectedRowClassFunc(MapDto element, int rowNumber)
|
||||
{
|
||||
if (selectedRowNumber == rowNumber && Table?.SelectedItem != null && !Table.SelectedItem.Equals(element))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
else if (selectedRowNumber == rowNumber && Table?.SelectedItem != null && Table.SelectedItem.Equals(element))
|
||||
{
|
||||
return "selected";
|
||||
}
|
||||
else if (Table?.SelectedItem != null && Table.SelectedItem.Equals(element))
|
||||
{
|
||||
selectedRowNumber = rowNumber;
|
||||
MapSelected = element;
|
||||
// MapPreviewRef?.SetMapPreview(MapSelected);
|
||||
return "selected";
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,317 @@
|
|||
<h3>MapView</h3>
|
||||
@inject IJSRuntime JS
|
||||
@using Excubo.Blazor.Canvas.Contexts
|
||||
|
||||
<div class="view">
|
||||
<div class="toolbar">
|
||||
<MudTooltip Text="Start Localization" role="button" Placement="Placement.Bottom" Color="Color.Info">
|
||||
<button type="button" class="btn btn-secondary action-button" disabled="@(false)">
|
||||
<i class="mdi mdi-play icon-button"></i>
|
||||
</button>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Stop Localization" role="button" Placement="Placement.Bottom" Color="Color.Info">
|
||||
<button type="button" class="btn btn-secondary action-button" disabled="@(true)">
|
||||
<i class="mdi mdi-pause icon-button"></i>
|
||||
</button>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Reset View" role="button" Placement="Placement.Bottom" Color="Color.Info">
|
||||
<button type="button" class="btn btn-secondary action-button" @onclick="ResetView">
|
||||
<i class="mdi mdi-restore icon-button"></i>
|
||||
</button>
|
||||
</MudTooltip>
|
||||
<div class="ms-auto d-flex align-items-center">
|
||||
<div class="zoom-info-container">
|
||||
<small class="zoom-info">
|
||||
<span class="info-item">
|
||||
<i class="mdi mdi-magnify"></i>
|
||||
Zoom: @($"{ZoomScale:F2}x")
|
||||
</span>
|
||||
<span class="info-separator">|</span>
|
||||
<span class="info-item">
|
||||
<i class="mdi mdi-crosshairs-gps"></i>
|
||||
Mouse: (@($"{MouseX:F0}"), @($"{MouseY:F0}"))
|
||||
</span>
|
||||
<span class="info-separator">|</span>
|
||||
<span class="info-item">
|
||||
<i class="mdi mdi-map-marker"></i>
|
||||
World: (@($"{WorldMouseX:F2}m"), @($"{WorldMouseY:F2}m"))
|
||||
</span>
|
||||
<span class="info-separator">|</span>
|
||||
<span class="info-item">
|
||||
<i class="mdi mdi-map-marker"></i>
|
||||
Translate: (@($"{CanvasTranslateX:F2}"), @($"{CanvasTranslateY:F2}"))
|
||||
</span>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div @ref="ViewContainerRef" class="d-flex position-relative w-100 flex-grow-1 overflow-hidden">
|
||||
<canvas @ref="CanvasRef"
|
||||
@onwheel="HandleWheel"
|
||||
@onwheel:preventDefault="true"
|
||||
@onmousemove="HandleMouseMove"
|
||||
@onmouseleave="HandleMouseLeave"
|
||||
style="display: block; cursor: crosshair; transform: scale(1, -1)"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private ElementReference CanvasRef;
|
||||
private ElementReference ViewContainerRef;
|
||||
|
||||
private double ZoomScale = 1.0;
|
||||
private const double MIN_ZOOM = 0.1;
|
||||
private const double MAX_ZOOM = 5.0;
|
||||
|
||||
private const double BASE_PIXELS_PER_METER = 50.0;
|
||||
|
||||
private bool IsMouseInCanvas = false;
|
||||
private double MouseX;
|
||||
private double MouseY;
|
||||
|
||||
private double OriginX = 0;
|
||||
private double OriginY = 0;
|
||||
|
||||
private double WorldMouseX;
|
||||
private double WorldMouseY;
|
||||
|
||||
private double CanvasWidth;
|
||||
private double CanvasHeight;
|
||||
|
||||
private double CanvasTranslateX = 0;
|
||||
private double CanvasTranslateY = 0;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool first_render)
|
||||
{
|
||||
await base.OnAfterRenderAsync(first_render);
|
||||
if (!first_render) return;
|
||||
|
||||
var parentSize = await JS.InvokeAsync<DomRect>("getElementSize", ViewContainerRef);
|
||||
|
||||
CanvasWidth = parentSize.Width;
|
||||
CanvasHeight = parentSize.Height;
|
||||
|
||||
await JS.InvokeVoidAsync("setCanvasSize", CanvasRef, CanvasWidth, CanvasHeight);
|
||||
|
||||
CanvasTranslateX = CanvasWidth / 2;
|
||||
CanvasTranslateY = CanvasHeight / 2;
|
||||
|
||||
await DrawCanvas();
|
||||
}
|
||||
|
||||
private async Task DrawCanvas()
|
||||
{
|
||||
await using var ctx = await JS.GetContext2DAsync(CanvasRef);
|
||||
|
||||
await ctx.ClearRectAsync(0, 0, CanvasWidth, CanvasHeight);
|
||||
await ctx.SaveAsync();
|
||||
|
||||
await ctx.TranslateAsync(CanvasTranslateX, CanvasTranslateY);
|
||||
await ctx.ScaleAsync(ZoomScale, ZoomScale);
|
||||
|
||||
await DrawGrid(ctx);
|
||||
await DrawAxes(ctx);
|
||||
|
||||
await ctx.RestoreAsync();
|
||||
}
|
||||
|
||||
private async Task DrawAxes(Context2D ctx)
|
||||
{
|
||||
double originCanvasX = OriginX * BASE_PIXELS_PER_METER;
|
||||
double originCanvasY = OriginY * BASE_PIXELS_PER_METER;
|
||||
|
||||
await ctx.FillStyleAsync("red");
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.ArcAsync(originCanvasX, originCanvasY, 10 / ZoomScale, 0, Math.PI * 2);
|
||||
await ctx.FillAsync(FillRule.NonZero);
|
||||
|
||||
await ctx.LineWidthAsync(2 / ZoomScale);
|
||||
|
||||
await ctx.StrokeStyleAsync("blue");
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.MoveToAsync(-CanvasWidth / ZoomScale, originCanvasY);
|
||||
await ctx.LineToAsync(CanvasWidth / ZoomScale, originCanvasY);
|
||||
await ctx.StrokeAsync();
|
||||
|
||||
await ctx.StrokeStyleAsync("red");
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.MoveToAsync(originCanvasX, -CanvasHeight / ZoomScale);
|
||||
await ctx.LineToAsync(originCanvasX, CanvasHeight / ZoomScale);
|
||||
await ctx.StrokeAsync();
|
||||
|
||||
double gridSpacingMeters = GetGridSpacingMeters();
|
||||
double arrowLength = gridSpacingMeters * BASE_PIXELS_PER_METER;
|
||||
double arrowHeadSize = 16 / ZoomScale;
|
||||
|
||||
await ctx.FillStyleAsync("blue");
|
||||
await ctx.StrokeStyleAsync("blue");
|
||||
await ctx.LineWidthAsync(4 / ZoomScale);
|
||||
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.MoveToAsync(originCanvasX, originCanvasY);
|
||||
await ctx.LineToAsync(originCanvasX + arrowLength, originCanvasY);
|
||||
await ctx.StrokeAsync();
|
||||
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.MoveToAsync(originCanvasX + arrowLength, originCanvasY);
|
||||
await ctx.LineToAsync(originCanvasX + arrowLength - arrowHeadSize, originCanvasY - arrowHeadSize / 2);
|
||||
await ctx.LineToAsync(originCanvasX + arrowLength - arrowHeadSize, originCanvasY + arrowHeadSize / 2);
|
||||
await ctx.ClosePathAsync();
|
||||
await ctx.FillAsync(FillRule.NonZero);
|
||||
|
||||
await ctx.FillStyleAsync("red");
|
||||
await ctx.StrokeStyleAsync("red");
|
||||
await ctx.LineWidthAsync(4 / ZoomScale);
|
||||
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.MoveToAsync(originCanvasX, originCanvasY);
|
||||
await ctx.LineToAsync(originCanvasX, originCanvasY + arrowLength);
|
||||
await ctx.StrokeAsync();
|
||||
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.MoveToAsync(originCanvasX, originCanvasY + arrowLength);
|
||||
await ctx.LineToAsync(originCanvasX - arrowHeadSize / 2, originCanvasY + arrowLength - arrowHeadSize);
|
||||
await ctx.LineToAsync(originCanvasX + arrowHeadSize / 2, originCanvasY + arrowLength - arrowHeadSize);
|
||||
await ctx.ClosePathAsync();
|
||||
await ctx.FillAsync(FillRule.NonZero);
|
||||
}
|
||||
|
||||
private async Task DrawGrid(Context2D ctx)
|
||||
{
|
||||
await ctx.StrokeStyleAsync("rgba(200, 200, 200, 0.4)");
|
||||
await ctx.LineWidthAsync(1 / ZoomScale);
|
||||
await ctx.SetLineDashAsync(new double[] { 5 / ZoomScale, 5 / ZoomScale });
|
||||
|
||||
double gridSpacingMeters = GetGridSpacingMeters();
|
||||
double gridSpacingPixels = gridSpacingMeters * BASE_PIXELS_PER_METER;
|
||||
|
||||
double visibleLeft = -CanvasTranslateX / ZoomScale;
|
||||
double visibleRight = (CanvasWidth - CanvasTranslateX) / ZoomScale;
|
||||
double visibleTop = -CanvasTranslateY / ZoomScale;
|
||||
double visibleBottom = (CanvasHeight - CanvasTranslateY) / ZoomScale;
|
||||
|
||||
double startX = Math.Floor(visibleLeft / gridSpacingPixels) * gridSpacingPixels;
|
||||
double startY = Math.Floor(visibleTop / gridSpacingPixels) * gridSpacingPixels;
|
||||
|
||||
for (double x = startX; x <= visibleRight; x += gridSpacingPixels)
|
||||
{
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.MoveToAsync(x, visibleTop);
|
||||
await ctx.LineToAsync(x, visibleBottom);
|
||||
await ctx.StrokeAsync();
|
||||
}
|
||||
|
||||
for (double y = startY; y <= visibleBottom; y += gridSpacingPixels)
|
||||
{
|
||||
await ctx.BeginPathAsync();
|
||||
await ctx.MoveToAsync(visibleLeft, y);
|
||||
await ctx.LineToAsync(visibleRight, y);
|
||||
await ctx.StrokeAsync();
|
||||
}
|
||||
|
||||
await ctx.SetLineDashAsync(new double[] { });
|
||||
}
|
||||
|
||||
private double GetGridSpacingMeters()
|
||||
{
|
||||
if (BASE_PIXELS_PER_METER * ZoomScale >= 300) return 0.2;
|
||||
else if (BASE_PIXELS_PER_METER * ZoomScale >= 150) return 0.5;
|
||||
else if (BASE_PIXELS_PER_METER * ZoomScale >= 75) return 1.0;
|
||||
else if (BASE_PIXELS_PER_METER * ZoomScale >= 40) return 2.0;
|
||||
else if (BASE_PIXELS_PER_METER * ZoomScale >= 20) return 5.0;
|
||||
else if (BASE_PIXELS_PER_METER * ZoomScale >= 10) return 10.0;
|
||||
else return 20.0;
|
||||
}
|
||||
|
||||
private double CanvasToWorldX(double canvasX)
|
||||
{
|
||||
return (canvasX - CanvasTranslateX) / ZoomScale / BASE_PIXELS_PER_METER - OriginX;
|
||||
}
|
||||
|
||||
private double CanvasToWorldY(double canvasY)
|
||||
{
|
||||
return (canvasY - CanvasTranslateY) / ZoomScale / BASE_PIXELS_PER_METER - OriginY;
|
||||
}
|
||||
|
||||
private double WorldToCanvasX(double worldX)
|
||||
{
|
||||
return (worldX + OriginX) * BASE_PIXELS_PER_METER * ZoomScale + CanvasTranslateX;
|
||||
}
|
||||
|
||||
private double WorldToCanvasY(double worldY)
|
||||
{
|
||||
return (worldY + OriginY) * BASE_PIXELS_PER_METER * ZoomScale + CanvasTranslateY;
|
||||
}
|
||||
|
||||
private async Task HandleMouseMove(MouseEventArgs e)
|
||||
{
|
||||
MouseX = e.OffsetX;
|
||||
MouseY = e.OffsetY;
|
||||
IsMouseInCanvas = true;
|
||||
|
||||
WorldMouseX = CanvasToWorldX(MouseX);
|
||||
WorldMouseY = CanvasToWorldY(MouseY);
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
if (e.Buttons == 4)
|
||||
{
|
||||
CanvasTranslateX += e.MovementX;
|
||||
CanvasTranslateY -= e.MovementY;
|
||||
await DrawCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleMouseLeave(MouseEventArgs e)
|
||||
{
|
||||
IsMouseInCanvas = false;
|
||||
MouseX = 0;
|
||||
MouseY = 0;
|
||||
StateHasChanged();
|
||||
await DrawCanvas();
|
||||
}
|
||||
|
||||
private async Task HandleWheel(WheelEventArgs e)
|
||||
{
|
||||
if (e.Buttons == 4) return;
|
||||
const double zoomFactor = 0.1;
|
||||
double oldZoom = ZoomScale;
|
||||
|
||||
if (e.DeltaY < 0) ZoomScale = Math.Min(MAX_ZOOM, ZoomScale * (1 + zoomFactor));
|
||||
else ZoomScale = Math.Max(MIN_ZOOM, ZoomScale * (1 - zoomFactor));
|
||||
|
||||
if (Math.Abs(ZoomScale - oldZoom) < 0.001) return;
|
||||
|
||||
MouseX = e.OffsetX;
|
||||
MouseY = e.OffsetY;
|
||||
|
||||
WorldMouseX = CanvasToWorldX(MouseX);
|
||||
WorldMouseY = CanvasToWorldY(MouseY);
|
||||
|
||||
double zoomPointWorldX = (MouseX - CanvasTranslateX) / oldZoom / BASE_PIXELS_PER_METER - OriginX;
|
||||
double zoomPointWorldY = (MouseY - CanvasTranslateY) / oldZoom / BASE_PIXELS_PER_METER - OriginY;
|
||||
|
||||
double newZoomPointCanvasX = (zoomPointWorldX + OriginX) * BASE_PIXELS_PER_METER * ZoomScale;
|
||||
double newZoomPointCanvasY = (zoomPointWorldY + OriginY) * BASE_PIXELS_PER_METER * ZoomScale;
|
||||
|
||||
CanvasTranslateX = MouseX - newZoomPointCanvasX;
|
||||
CanvasTranslateY = MouseY - newZoomPointCanvasY;
|
||||
|
||||
StateHasChanged();
|
||||
await DrawCanvas();
|
||||
}
|
||||
|
||||
private async Task ResetView()
|
||||
{
|
||||
CanvasTranslateX = CanvasWidth / 2;
|
||||
CanvasTranslateY = CanvasHeight / 2;
|
||||
ZoomScale = 1.0;
|
||||
StateHasChanged();
|
||||
await DrawCanvas();
|
||||
}
|
||||
|
||||
public class DomRect
|
||||
{
|
||||
public double Width { get; set; }
|
||||
public double Height { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
173
RobotApp.Client/Pages/Components/Mapping/MapView.razor.css
Normal file
173
RobotApp.Client/Pages/Components/Mapping/MapView.razor.css
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
.view {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background-color: var(--mud-palette-surface);
|
||||
border-radius: var(--mud-default-borderradius);
|
||||
transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
box-shadow: var(--mud-elevation-10);
|
||||
}
|
||||
|
||||
.view .toolbar {
|
||||
width: 100%;
|
||||
height: 3rem;
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
border-bottom: 1px solid var(--mud-palette-divider);
|
||||
background-color: var(--mud-palette-background);
|
||||
}
|
||||
|
||||
.view .toolbar .action-button {
|
||||
padding: 0rem 0.4rem;
|
||||
margin-right: 0.5rem;
|
||||
border-radius: var(--mud-default-borderradius);
|
||||
transition: all 0.3s ease;
|
||||
background-color: var(--bs-gray-200);
|
||||
}
|
||||
|
||||
.view .toolbar .action-button:hover {
|
||||
background-color: var(--mud-palette-action-hover);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.view .toolbar .action-button:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.view .toolbar .action-button:disabled:hover {
|
||||
transform: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.view .toolbar .icon-button {
|
||||
font-size: 1.2rem;
|
||||
color: var(--mud-palette-primary);
|
||||
}
|
||||
|
||||
.view canvas {
|
||||
transition: cursor 0.2s ease;
|
||||
}
|
||||
|
||||
.view canvas:hover {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
/* Enhanced zoom and coordinate info styling */
|
||||
.zoom-info-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--mud-palette-background);
|
||||
border: 1px solid var(--mud-palette-divider);
|
||||
border-radius: 6px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.zoom-info {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
font-size: 0.8rem;
|
||||
color: var(--mud-palette-text-primary);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-item i {
|
||||
font-size: 0.9rem;
|
||||
color: var(--mud-palette-primary);
|
||||
}
|
||||
|
||||
.info-separator {
|
||||
color: var(--mud-palette-divider);
|
||||
font-weight: 300;
|
||||
margin: 0 0.25rem;
|
||||
}
|
||||
|
||||
/* Responsive design for info container */
|
||||
@media (max-width: 768px) {
|
||||
.zoom-info-container {
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
|
||||
.zoom-info {
|
||||
font-size: 0.7rem;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
gap: 0.15rem;
|
||||
}
|
||||
|
||||
.info-item i {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Very small screens - stack vertically */
|
||||
@media (max-width: 480px) {
|
||||
.zoom-info {
|
||||
flex-direction: column;
|
||||
gap: 0.15rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.info-separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.zoom-info-container {
|
||||
padding: 0.35rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hover effects for info container */
|
||||
.zoom-info-container:hover {
|
||||
background-color: var(--mud-palette-action-hover);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
/* Animation for coordinate updates */
|
||||
.info-item {
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.info-item:hover {
|
||||
color: var(--mud-palette-primary);
|
||||
}
|
||||
|
||||
/* High contrast mode support */
|
||||
@media (prefers-contrast: high) {
|
||||
.zoom-info-container {
|
||||
border-width: 2px;
|
||||
background-color: var(--mud-palette-surface);
|
||||
}
|
||||
|
||||
.info-item {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark mode adjustments */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.zoom-info-container {
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.zoom-info-container:hover {
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.4);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<PageTitle>Map Manager</PageTitle>
|
||||
|
||||
<div class="d-flex w-100 h-100 p-2 overflow-hidden flex-row">
|
||||
<div style="height: 100%; width: 40%">
|
||||
<div class="me-4" style="height: 100%; width: 40%">
|
||||
<RobotApp.Client.Pages.Components.Mapping.MapTable />
|
||||
</div>
|
||||
<div class="flex-grow-1 h-100" style="width: 60%">
|
||||
|
|
|
|||
|
|
@ -14,3 +14,5 @@
|
|||
@using MudBlazor
|
||||
@using RobotApp.Common.Shares
|
||||
@using RobotApp.Common.Shares.Dtos
|
||||
@using Excubo.Blazor.Canvas
|
||||
@using Excubo.Blazor.Canvas.Contexts
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Excubo.Blazor.Canvas" Version="3.2.91" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.1" />
|
||||
<PackageReference Include="MudBlazor" Version="8.12.0" />
|
||||
|
|
@ -20,7 +21,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Folder Include="Models\" />
|
||||
<Folder Include="wwwroot\js\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
11
RobotApp.Client/wwwroot/js/canvas.js
Normal file
11
RobotApp.Client/wwwroot/js/canvas.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
window.getElementSize = (element) => {
|
||||
return {
|
||||
width: element.clientWidth,
|
||||
height: element.clientHeight,
|
||||
};
|
||||
}
|
||||
|
||||
window.setCanvasSize = (canvas, width, height) => {
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
}
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
<script src="@Assets["lib/bootstrap/js/bootstrap.bundle.min.js"]"></script>
|
||||
<script src="@Assets["lib/bootstrap/js/bootstrap.min.js"]"></script>
|
||||
<script src="@Assets["_content/MudBlazor/MudBlazor.min.js"]"></script>
|
||||
<script src="@Assets["js/canvas.js"]"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
|||
10
RobotApp/Controllers/ImagesController.cs
Normal file
10
RobotApp/Controllers/ImagesController.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace RobotApp.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ImagesController : ControllerBase
|
||||
{
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user