如何将图像 base64 url 传递给兄弟组件

How to pass an image base64 url to a sibling component

我有一个可以完美呈现传单地图的组件,我可以在上面绘制一些多边形。我添加了 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 上发布了我的代码。

我在 MapComponent 中创建了一个示例地图,并按照 ngx-leaflet-draw and ngx-leaflet 的文档在地图中绘制多边形。在 /home/map 路线中创建多边形后,我将带有多边形的图像存储到 ProjectService 中,以便在通过 [=20] 按钮进入 /home/image 路线后将其放入 ScreenshotComponent =]指令。

我试图用方法名称进行描述,以便轻松查看正在发生的事情。

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