【问题标题】:How to pass an image base64 url to a sibling component如何将图像 base64 url​​ 传递给兄弟组件
【发布时间】:2020-02-22 01:07:12
【问题描述】:

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

【问题讨论】:

  • 您的 ProjectService 是单例吗?您可以发布您的 ProjectService 的完整代码吗?
  • 我想是的,我更新了我的服务的代码部分。
  • 是的,我可以看到你的ProjectServiceprovidedIn: 'root'。您是否将此服务包含在提供者的模块数组中?你能把代码上传到 Stackblitz 上吗?这样我就可以检查发生了什么。
  • 我试图复制它here 但stackblitz 无法加载地图。

标签: angular typescript service base64url


【解决方案1】:

我在MapComponent 中创建了一个示例地图,并按照ngx-leaflet-drawngx-leaflet 的文档在地图内绘制了一个多边形。在/home/map 路由中创建多边形后,我将带有多边形的图像存储到ProjectService,以便在通过带有routerLink 指令的按钮转到/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

【讨论】:

  • 感谢您的解释。我现在对提供者的概念有了更好的理解。但不幸的是,在尝试了您的建议后,它没有奏效。我认为处理地图数据有问题,因为我的项目中有输入字段,我在该服务上编写了诸如标题之类的内容,它确实将更改传递给下一个组件,但它无法传递与地图相关的任何数据。我试图获取地图或绘制的多边形的纬度和经度,将其传递给服务中的变量并在下一个组件中接收它,我得到了我最初在服务中初始化的值。
  • 我没有父子组件。它们是兄弟组件。所以,我想在地图上做一些事情,然后获取这些信息和屏幕截图,然后转到下一个组件(第一个组件的兄弟),显示图像并使用从前一个组件中的地图获取的信息做其他事情。
  • 我需要订阅 Observable 而不是使用服务吗?
  • 是的,你知道。我用一个带有 observable 的例子编辑了我的答案,但你也需要一个单例服务。如果你能解决你的问题,请告诉我。
  • 您的回答仍然显示 screenshot.component.html 的内容。只有当sibling.component.html 有一个带有来自屏幕截图组件的路径但不再显示地图的图像元素时,我才能获取图像。基本上我想在截屏后替换 map 元素,并会看到 src 是从截屏组件中截取的同级图像。
猜你喜欢
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
  • 2021-06-10
  • 1970-01-01
  • 2017-12-01
  • 2021-12-02
相关资源
最近更新 更多