How would I use this with angular?
Closed this issue · 11 comments
Hi there, I was wondering if you would be able to provide some help on how to use this with angular?
i've tried adding some custom defininitions to the typings however this is my first time doing this sort of thing and I'm having some issues
here's what I have for my typings:
/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
id: string;
}
import * as L from 'leaflet';
declare module 'leaflet' {
namespace control {
function browserPrint(options?: any): Control.BrowserPrint;
function takeScreen(format:any, overridedPluginOptions:any) : simpleMapScreenshoter;
interface simpleMapScreenshoter {
addTo(map:L.Map) :any;
}
}
namespace Control {
interface BrowserPrint {
addTo(map: L.Map): any;
}
}
}
Thanks in advance
I haven't tested this in Angular, but it work correct in Vue Typescript:
Short way:
declare module "leaflet" {
export function simpleMapScreenshoter(options?: any): any;
}
Long way:
import {Control} from 'leaflet'
interface SimpleMapScreenshoter extends Control{
takeScreen(): Promise<File>;
}
interface SimpleMapScreenshoterOptions {
screenName(): string;
// other options from https://github.com/grinat/leaflet-simple-map-screenshoter/blob/master/src/SimpleMapScreenshoter.js#L9
}
declare module "leaflet" {
export function simpleMapScreenshoter(options?: SimpleMapScreenshoterOptions): SimpleMapScreenshoter;
}
Hi thanks for your quick response, I've tried your short way and I get this error at runtime
leaflet__WEBPACK_IMPORTED_MODULE_4__.simpleMapScreenshoter is not a function
Here's some code snippets for what I have
typings.d.ts
/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
id: string;
}
import * as L from 'leaflet';
declare module 'leaflet' {
export function simpleMapScreenshoter(options?: any): any;
}
Component.ts
import * as L from 'leaflet';
export class AddPostComponent implements OnInit, AfterViewChecked {
simpleMapScreenshoter:any;
map:any;
onMapReady(map: L.Map, detail: any)
{
this.simpleMapScreenshoter = L.simpleMapScreenshoter().addTo(this.map);
this.map = map;
this.takeScreenshot();
}
takeScreenshot()
{
let format = 'image' // 'image' - return base64, 'canvas' - return canvas
let overridedPluginOptions =
{
mimeType: 'image/jpeg'
}
this.simpleMapScreenshoter.takeScreen(format, overridedPluginOptions).then(blob =>
{
alert('done')
console.log(blob);
}).catch(e =>
{
console.error(e)
})
}
}
Webpack cant find plugin because you dont import it
In Component.ts
import * as L from 'leaflet'
// import plugin after leaflet
import 'leaflet-simple-map-screenshoter'
Edit: This issue was because I was passing the wrong variable
It all seems to run through and the alert is called, however the base64 output does not display the entire map (Please see attatched image)
Base64:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAEoAC8DASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAj/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AL4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//Z
Thanks again for such a quick response, That error has gone away and is now replaced with this one:
Cannot read property '_controlCorners' of undefined at NewClass.addTo (leaflet-src.js:4786) at Component.push../src/app/Components/component.component.ts.Component.onMapReady (component.component.ts:2467) at Object.eval [as handleEvent] (Component.html:757) at handleEvent (core.js:23107) at callWithDebugContext (core.js:24177) at Object.debugHandleEvent [as handleEvent] (core.js:23904) at dispatchEvent (core.js:20556) at core.js:22046 at SafeSubscriber.schedulerFn [as _next] (core.js:13527) at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:192)
Then you call L.simpleMapScreenshoter().addTo(this.map)
map is undefined
In leafltet sources:
addTo: function (map) {
...
corner = map._controlCorners[pos];
In leafltet sources:
addTo: function (map) { ... corner = map._controlCorners[pos];
Is this response in regards to the new commented I added above (About only parts of the image being rendered?)
No.
Hmm... only parts of the image bacuse wrong width/height size of html node with map. Check your css code(maybe you forget import leaflet map css styles, maybe you create before map node calc with/height, call https://leafletjs.com/reference-1.6.0.html#map-invalidatesize). Try to set options cropImageByInnerWH to false
L.simpleMapScreenshoter({
cropImageByInnerWH: false
})
I was able to get it all working (It was an issue with my custom css that used translateX), the only issue I'm having now is that if I call screenshot inside of onMapReady the image I get is blank.
However If I wait 0.5 seconds before doing this then the image is fine, any suggestions on what I could do so I don't have to wait a predefined amount of time?
Tiles not loaded, need:
- wait for all tiles donwload (https://leafletjs.com/reference-1.6.0.html#gridlayer-load)
- wait fo tile render and wait a bit more than 0.2 secs (the duration of the tile animation fade-in)
- take screen
Example:
const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
tiles.on('load', () => {
setTimeout(() => {
simpleMapScreenshoter.takeScreen('image').then(image => {
var img = document.createElement('img')
img.src = image
document.body.appendChild(img)
})
}, 201)
})
Thanks soo much for your continued support, I seem to have everything I need to accomplish what I was trying to do