Drawing a circle Google Static Maps

后端 未结 7 681
刺人心
刺人心 2020-12-07 23:39

I have a Google Maps Circle drawn on v3 api. When the user has plotted there circle (or polygon if they choose), they can save the data to the server. If the user has picked

相关标签:
7条回答
  • 2020-12-08 00:12

    This solution uses the significantly more versatile Canvas API to draw over the map image . All code is in Typescript, so simply remove type declarations if you're using Javascript.

    ADVANGES OF USING CANVAS:

    • Its easier to draw shapes on.
    • Those shapes can also be revised without re-requesting the map image from Google.
    • The drawing 'layer' can be serialized independently of the underlying map image.

    USAGE:

    // DEFINE BASIC VARIABLES
    const latitude: -34.3566871,
    const longitude: 18.4967666
    const mapZoom = 12;
    const imageWidth: 100;
    const imageHeight: 100;
    
    // INVOKE UTILITY FUNCTION
    savePlaceImage({
    
      // SET BASIC PROPS
      latitude,
      longitude,
      mapZoom,
      imageWidth,
      imageHeight,
      fileName: 'Cape Point',
    
      // DRAW IMAGE USING CANVAS API
      draw: ctx => {
    
        // draw location as dot
        ctx.fillStyle = '#FF3366';
        ctx.beginPath();
        ctx.arc(imageWidth / 2, imageHeight / 2, 10, 0, 2 * Math.PI);
        ctx.fill();
    
        // draw circle around location with 1 kilometer radius
        ctx.strokeStyle = '#0000FF';
        ctx.beginPath();
        ctx.arc(imageWidth / 2, imageHeight / 2, pixelsPerMeter(latitude) * 1000, 0, 2 * Math.PI);
        ctx.stroke();
      }
    })
    

    UTILITIES:

    function savePlaceImage(
      config: {
        latitude: number,
        longitude: number,
        mapZoom: number,
        imageWidth: number,
        imageHeight: number,
        fileName: string,
        draw: (ctx: CanvasRenderingContext2D) => void,
      },
    ) {
    
      // DOWNLOAD MAP IMAGE FROM GOOGLE'S STATIC MAPS API AS A BLOB
      return from(axios.get<Blob>(`https://maps.googleapis.com/maps/api/staticmap`, {
        params: {
          key: GOOGLE_MAPS_API_KEY,
          size: `${config.imageWidth}x${config.imageHeight}`,
          zoom: `${config.mapZoom}`,
          center: `${config.latitude},${config.longitude}`,
          style: 'feature:all|element:labels|visibility:off',
        },
        responseType: 'blob',
    
      // CONVERT BLOB TO BASE64 ENCODED STRING
      }).then(response => {
        const reader = new FileReader();
        reader.readAsDataURL(response.data);
        return new Promise<string>(resolve => reader.onloadend = () => resolve(reader.result as string));
    
      // CREATE HTML IMG ELEMENT, SET IT'S SRC TO MAP IMAGE, AND WAIT FOR IT TO LOAD
      }).then(response => {
        const image = document.createElement('img');
        image.src = response;
        return new Promise<HTMLImageElement>(resolve => image.onload = () => resolve(image));
    
      // CREATE HTML CANVAS ELEMENT, THEN DRAW ON TOP OF CANVAS USING CANVAS API, THEN CONVERT TO BLOB
      }).then(image => {
        const canvas = document.createElement('canvas');
        canvas.width = config.imageWidth;
        canvas.height = config.imageHeight;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);
        config.draw(ctx);
        return new Promise<Blob>(resolve => canvas.toBlob(blob => resolve(blob)));
    
      // ATTACH BLOB TO HTML FORM WHICH CONVERTS IT TO A FILE TO BE POSTED, THEN SEND FILE TO SERVER
      }).then(blob => {
        const form = new FormData();
        form.append('blob', blob, `${config.fileName}.png`);
        const file = form.get('blob') as File;
        return axios.post<{ file }>('https://www.my-api.com/save-image', form);
      }));
    }
    
    function pixelsPerMeter(latitude: number) {
      const radiusOfEarthInKilometers = 6371;
      return Math.cos(latitude * Math.PI / 180) * 2 * Math.PI * radiusOfEarthInKilometers / (256 * Math.pow(2, 12));
    }
    
    0 讨论(0)
提交回复
热议问题