Как передать URL-адрес base64 в одноуровневый компонент - PullRequest
0 голосов
/ 22 февраля 2020

У меня есть компонент, который прекрасно отображает карту листовки, и я могу нарисовать на ней несколько полигонов. Я добавил библиотеку htmlToImage , чтобы сделать скриншот того, что я нарисовал, и если я добавлю его в качестве дочернего элемента к тому же компоненту, он будет отображаться нормально. Но мне нравится передавать этот источник изображения следующему компоненту (одноуровневому компоненту) и делать с ним другие вещи. Я попытался реализовать службу, в которой мой первый компонент записывает dataURL как строковую переменную, а второй компонент получает эту переменную и использует ее для отображения изображения из этого сохраненного пути. Первый компонент направляется к следующему с методом router-link в качестве родственного компонента (переход от home / map к home / image), но он не будет отображать изображение, а просто console.log (path) - пустая строка, которая то, что я инициализировал в своем сервисе, изначально. Что я делаю не так?

Я использую Angular 9 и работаю на локальном хосте. Вот что я пытался сделать до сих пор:

map.component.ts

// Map related methods ....
// ....

getScreenshot() {
   htmlToImage.toPng(document.getElementById('map'))
      .then((dataUrl) => {
        this.projectService.setProject('image', dataUrl);
      })
      .catch((error) => {
        console.error('oops, something went wrong!', error);
      });
}

screenshot.component.ts

const path = this.projectService.getProject().image;

constructr(private projectService: ProjectService) {}

screenshot.component. html

<div class="row content">
    <img [src]="path" alt="map" >
</div>

project.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

export class ProjectService {

  private project = {
    title: '',
    image: '',

  };

  getProject() {
    return this.project;
  }

  setProject(option: any, value: any) {
    this.project[option] = value;
  }

}

app-routing.module.ts

export const appRoutes: Routes = [
  {
    path: 'home', component: AppComponent,
    children: [
      { path: 'map', component: MapComponent },
      { path: 'image', component: ScreenshotComponent },
    ]
  },
];

Я разместил свой код на StackBlitz .

1 Ответ

0 голосов
/ 25 февраля 2020

Я создал пример карты в MapComponent и следовал документации ngx-leaflet-draw и ngx-leaflet , чтобы нарисовать многоугольник внутри карты. После создания многоугольника в маршруте /home/map я сохранил изображение с многоугольником в ProjectService для получения его в ScreenshotComponent после перехода по маршруту /home/image через кнопку с директивой routerLink.

Я попытался описать названия методов, чтобы легко увидеть, что происходит.

map.component.html

<div style="height: 300px; width: 600px;"
     id="map"
     leaflet 
     leafletDraw
     (leafletMapReady)="onMapReady($event)"
     (leafletDrawCreated)="onLeafletDrawCreated($event)"
     [leafletOptions]="leafletOptions"
     [leafletDrawOptions]="drawOptions"
     >
</div>
<div>Draw a polygon and go to image route</div>
<button routerLink="/home/image">Go Image Page</button>

map.component.ts

import { Component } from "@angular/core";
import htmlToImage from "html-to-image";
import { ProjectService } from "../project.service";
import * as L from 'leaflet';

@Component({
  selector: "app-map",
  templateUrl: "./map.component.html",
  styleUrls: ["./map.component.css"]
})
export class MapComponent {

  map: L.Map;
  editableLayers = new L.FeatureGroup();
  leafletOptions = {
    layers: [
      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18 })
    ],
    zoom: 5,
    center: L.latLng(46.879966, -121.726909)
  };
  drawOptions = {
    position: 'topright',
    draw: {
        marker: {
          icon: L.icon({
              iconSize: [ 25, 41 ],
              iconAnchor: [ 13, 41 ],
              iconUrl: 'assets/marker-icon.png',
              shadowUrl: 'assets/marker-shadow.png'
          })
        },
        polyline: false,
        circle: {
            shapeOptions: {
                color: '#aaaaaa'
            }
        }
    }
  };

  constructor(private projectService: ProjectService) {}

  onMapReady(map: L.Map) {
    // map loaded, store in map var
    this.map = map;
  }

  onLeafletDrawCreated(event: any) {
    // after drawing a polygon take a screenshot
    this.getScreenshot();
  }

  getScreenshot() {
    // I recommend you use Renderer2 provided by Angular Core Package instead of document.getElementById directly
    // https://angular.io/api/core/Renderer2
    htmlToImage
      .toPng(document.getElementById("map")) 
      .then(dataUrl => {
        this.projectService.setProject("image", dataUrl);
      })
      .catch(error => {
        console.error("oops, something went wrong!", error);
      });
  }
}

screenshot.component.html

<div *ngIf="path; else noImageTemplate;" 
    style="height: 300px; width: 600px;" class="row content">
    <img style="height: 100%; width: 100%; object-fit: contain;" [src]="path" alt="map" >
</div>
<ng-template #noImageTemplate>
  <div style="height: 300px; width: 600px; border: 1px solid lightgray;">
    No image yet, try select some polygon on map page
  </div>
</ng-template>
<button routerLink="/home/map">Go Map Route</button>

screenshot.component.ts

import { Component, OnInit } from '@angular/core';
import { ProjectService } from "../project.service";

@Component({
  selector: 'app-screenshot',
  templateUrl: './screenshot.component.html',
  styleUrls: ['./screenshot.component.css']
})
export class ScreenshotComponent implements OnInit {

  path: string = this.projectService.getProject().image;

  constructor(private projectService: ProjectService) {}

  ngOnInit() {
    console.info('path from project service!', this.path);
  }
}

project.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class ProjectService {
  private project = {
    title: '',
    image: '',
  };
  getProject() {
    return this.project;
  }
  setProject(option: any, value: any) {
    this.project[option] = value;
  }
}

Решение доступно здесь: Stackblitz

...