Ying XIONG
Ying XIONG

Reputation: 23

openlayers 3: how to draw sth using canvas.getContext('2d') on top of the map

I want to draw some geometry in the map using canvas.getContext('2d'). However, the geometry I've drawn just show for a while. It disappear when I pan/zoom the map. How can I draw a permanent geometry through this way?

Below is my code:

<html>
<head>
    <title></title>
    <!-- styles -->
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol.css"/>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.19.1/ol.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script type="text/javascript">
        var map;
        function init()
        {
            var raster = new ol.layer.Tile({
                            title:'basemap',
                 source: new ol.source.Stamen({
                   layer: 'toner'
                 })
               });

            map = new ol.Map( {layers:[raster],target:'map',  view: new ol.View({
      center: [113,25],
                projection: 'EPSG:4326',
      zoom: 6
    })} );

        };


        function drawSth(){
            var canvas = $("canvas")[0];
            var context = canvas.getContext('2d');
            // begin custom shape
                  context.beginPath();
                  context.moveTo(170, 80);
                  context.bezierCurveTo(130, 100, 130, 150, 230, 150);
                  context.bezierCurveTo(250, 180, 320, 180, 340, 150);
                  context.bezierCurveTo(420, 150, 420, 120, 390, 100);
                  context.bezierCurveTo(430, 40, 370, 30, 340, 50);
                  context.bezierCurveTo(320, 5, 250, 20, 250, 50);
                  context.bezierCurveTo(200, 5, 150, 20, 170, 80);

                  // complete custom shape
                  context.closePath();
                  context.lineWidth = 5;
                  context.fillStyle = '#8ED6FF';
                  context.fill();
                  context.strokeStyle = 'blue';
                  context.stroke();
        }

    </script>

</head>

<body onload="init()">

    <div id="map"></div>

    <div id="controls">         
        <button onclick="drawSth();">just draw sth</button></br></br>
    </div>

</body>

Upvotes: 2

Views: 2677

Answers (1)

Jeff McCloud
Jeff McCloud

Reputation: 5927

You can do that with an ol.source.ImageCanvas and its canvasFunction.

jsFiddle: https://jsfiddle.net/45oxL7rf/

var map = new ol.Map({
  layers: [
    new ol.layer.Tile({
      title: 'basemap',
      source: new ol.source.Stamen({ layer: 'toner' })
    }),
    new ol.layer.Image({
      source: new ol.source.ImageCanvas({
        canvasFunction: function (extent, resolution, pixelRatio, size, projection) {
          var canvas = document.createElement('canvas');
          canvas.width = size[0];
          canvas.height = size[1];

          var context = canvas.getContext('2d');
          // begin custom shape
          context.beginPath();
          context.moveTo(170, 80);
          context.bezierCurveTo(130, 100, 130, 150, 230, 150);
          context.bezierCurveTo(250, 180, 320, 180, 340, 150);
          context.bezierCurveTo(420, 150, 420, 120, 390, 100);
          context.bezierCurveTo(430, 40, 370, 30, 340, 50);
          context.bezierCurveTo(320, 5, 250, 20, 250, 50);
          context.bezierCurveTo(200, 5, 150, 20, 170, 80);

          // complete custom shape
          context.closePath();
          context.lineWidth = 5;
          context.fillStyle = '#8ED6FF';
          context.fill();
          context.strokeStyle = 'blue';
          context.stroke();

          return canvas;
        },
        projection: 'EPSG:3857'
      })
    })
  ],
  target: 'map',
  view: new ol.View({
    center: ol.proj.fromLonLat([-97, 38]),
    zoom: 4
  })
});

Note that I just copy/pasted your canvas drawing and left it as is. As you pan the map, your graphic will not be anchored to the map as you might expect, since you're drawing to static pixel coordinates. In your real app, you'll likely be calculating the proper pixel coordinates based on the arguments passed into your canvasFunction.

Upvotes: 2

Related Questions