none
Bing Maps AJAX v7 - Setting Opacity on Tile Layer frequently causes flicker RRS feed

  • Question

  • Hi.

    I am using Bing Maps AJAX v7, and have bound the opacity of a tile layer to a jQuery slider control. However, when I slide the slider control I get quite a serious flicker. This flicker was no where near as pronounced with similar code using the v6.3 Map Control.

    Here is some example code:

    Bing Maps AJAX v7 (Very Flickery!):

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <title></title>
      <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
      <script type="text/javascript" charset="UTF-8" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&mkt=en-gb"></script>  
      <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.2.min.js" type="text/javascript"></script>
      <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/jquery-ui.min.js" type="text/javascript"></script>
      <script type="text/javascript">
        var map, tileSource, tilelayer;
    
        $(function ()
        {
          // Initialize the map
          map = new Microsoft.Maps.Map($('#map')[0], { credentials: "Your Bing Maps Key", center: new Microsoft.Maps.Location(48.03, -122.4), zoom: 12, mapTypeId: "r" });
    
          // Create the tile layer source
          tileSource = new Microsoft.Maps.TileSource({ uriConstructor: 'http://www.microsoft.com/maps/isdk/ajax/layers/lidar/{quadkey}.png' });
    
          // Construct the layer using the tile source
          tilelayer = new Microsoft.Maps.TileLayer({ mercator: tileSource, opacity: 1 });
    
          // Push the tile layer to the map
          map.entities.push(tilelayer);
    
          //set up slider
          $('#opacitySlider').slider({
            value: 100,
            slide: function (e, ui)
            {
              tilelayer.setOptions({
                opacity: (ui.value / 100)
              });
            }
          });
    
        });
      </script>
    </head>
    <body>
      <div id="map" style="position:relative; width:400px; height:400px;"></div>
      <div id="opacitySlider" style="position:relative; width:400px;"></div>
    </body>
    </html>
    
    

    Bing Maps AJAX v6.3 (Not so Flickery):

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <title></title>
      <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
      <script type="text/javascript" charset="UTF-8" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.3&mkt=en-gb"></script>  
      <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.2.min.js" type="text/javascript"></script>
      <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/jquery-ui.min.js" type="text/javascript"></script>
      <script type="text/javascript">
        var map, tileSourceSpec;
    
        $(function ()
        {
          // Initialize the map
          map = new VEMap('map');
          map.LoadMap(new VELatLong(48.03, -122.4), 12, 'r', false);
    
          //add the tile layer
          tileSourceSpec = new VETileSourceSpecification("lidar", "http://www.microsoft.com/maps/isdk/ajax/layers/lidar/%4.png");
          tileSourceSpec.NumServers = 1;
          tileSourceSpec.Opacity = 1;
          tileSourceSpec.ZIndex = 100;
    
          map.AddTileLayer(tileSourceSpec, true);
    
          //set up slider
          $('#opacitySlider').slider({
            value: 100,
            slide: function (e, ui)
            {
              map.DeleteTileLayer(tileSourceSpec.ID);
              tileSourceSpec.Opacity = (ui.value / 100);
              map.AddTileLayer(tileSourceSpec, true);
            }
          });
    
        });
      </script>
    </head>
    <body>
      <div id="map" style="position:relative; width:400px; height:400px;"></div>
      <div id="opacitySlider" style="position:relative; width:400px;"></div>
    </body>
    </html>
    
    

    Does anyone have any ideas as to how I can improve the smoothness of the opacity slider using the v7 map control?

    Thanks in advance,

    Neil.

     

    • Moved by Ricky_Brundritt Friday, March 9, 2012 5:02 PM (From:Bing Maps: Map Control and Web services Development)
    Tuesday, April 12, 2011 1:53 PM

Answers

  • Here is the last approach that might help you, in fact the logic around this:

    1. On slide you change the HTML opacity element and set opacity option to 100
    2. On change (which occurs after the slide) : you change the HTML opacity back to 100 and set options on Tilelayer
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     <title></title>
     <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
     <script type="text/javascript" charset="UTF-8" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&mkt=en-gb"></script> 
     <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.2.min.js" type="text/javascript"></script>
     <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/jquery-ui.min.js" type="text/javascript"></script>
     <script type="text/javascript">
      var map, tileSource, tilelayer;
      var isOpacityChanged = false;
      $(function () {
        // Initialize the map
        map = new Microsoft.Maps.Map($('#map')[0], { credentials: "Your Bing Maps Key", center: new Microsoft.Maps.Location(48.03, -122.4), zoom: 12, mapTypeId: "r" });
    
        // Create the tile layer source
        tileSource = new Microsoft.Maps.TileSource({ uriConstructor: 'http://www.microsoft.com/maps/isdk/ajax/layers/lidar/{quadkey}.png' });
    
        // Construct the layer using the tile source
        tilelayer = new Microsoft.Maps.TileLayer({ mercator: tileSource, opacity: 1 });
    
        // Push the tile layer to the map
        map.entities.push(tilelayer);
    
    
        //set up slider
        $('#opacitySlider').slider({
          value: 100,
          slide: function (event, ui) {
            if (!isOpacityChanged) {
              tilelayer.setOptions({ opacity: 100 });
              isOpacityChanged = true;
            }
    
            $('.MicrosoftMap div div:eq(0) div:eq(1)').css({ opacity: (ui.value / 100) });        
          },
          change: function (event, ui) {
            tilelayer.setOptions({ opacity: (ui.value / 100) });
            $('.MicrosoftMap div div:eq(0) div:eq(1)').css({ opacity: 100 });
            isOpacityChanged = false;
          }
        });
    
      });
     </script>
    </head>
    <body>
     <div id="map" style="position:relative; width:400px; height:400px;"></div>
     <div id="opacitySlider" style="position:relative; width:400px;"></div>
    </body>
    </html>
    

    MVP - Bing Maps - My blog (FR): http://blogs.developpeur.org/nicoboo/ Twitter: http://twitter.com/nicolasboonaert/
    Tuesday, April 12, 2011 3:32 PM
    Moderator

All replies

  • It's a common problem, you should work directly with the corresponding HTML element even if it is not a supported way:

    //set up slider
       $('#opacitySlider').slider({
        value: 100,
         slide: function( event, ui ) {
    			$('.MicrosoftMap div div:eq(0) div:eq(1)').css({ opacity: (ui.value / 100) });
    		}
       });
    

    You can have a more delicate approach using something like: getRootElement()

     


    MVP - Bing Maps - My blog (FR): http://blogs.developpeur.org/nicoboo/ Twitter: http://twitter.com/nicolasboonaert/
    Tuesday, April 12, 2011 2:13 PM
    Moderator
  • Hi Nicolas.

    The problem with this approach is that the Map control's own internal state regarding opacity of the layer becomes out-of-sync with the actual opacity of the images. When you zoom in for instance, the opacity becomes reset to the Map controls value rather than the value we have set from the slider.

    Thanks for the suggestion though,

    Neil.

    Tuesday, April 12, 2011 2:18 PM
  • Yes, but the thing is you get bind event from the map control and set the opacity option correctly.

    This simple code helps you avoiding the flickering effect.
    Of course you will need to change the opacity again.

    The simplest way to do this would be to always change the HTML element for this case:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     <title></title>
     <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
     <script type="text/javascript" charset="UTF-8" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&mkt=en-gb"></script> 
     <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.2.min.js" type="text/javascript"></script>
     <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/jquery-ui.min.js" type="text/javascript"></script>
     <script type="text/javascript">
      var map, tileSource, tilelayer;
    
      $(function ()
      {
       // Initialize the map
       map = new Microsoft.Maps.Map($('#map')[0], { credentials: "Your Bing Maps Key", center: new Microsoft.Maps.Location(48.03, -122.4), zoom: 12, mapTypeId: "r" });
       Microsoft.Maps.Events.addHandler(map, 'viewchange', changeOpacity);
       Microsoft.Maps.Events.addHandler(map, 'mousemove', changeOpacity);
    
    
       // Create the tile layer source
       tileSource = new Microsoft.Maps.TileSource({ uriConstructor: 'http://www.microsoft.com/maps/isdk/ajax/layers/lidar/{quadkey}.png' });
    
       // Construct the layer using the tile source
       tilelayer = new Microsoft.Maps.TileLayer({ mercator: tileSource, opacity: 1 });
    
       // Push the tile layer to the map
       map.entities.push(tilelayer);
    
       //set up slider
       $('#opacitySlider').slider({
        value: 100,
         slide: function( event, ui ) {
    					$('.MicrosoftMap div div:eq(0) div:eq(1)').css({ opacity: (ui.value / 100) });
    				}
       });
    
    });
    
      function changeOpacity() {
        var opacityCompute = $('#opacitySlider').slider("value") / 100;
        $('.MicrosoftMap div div:eq(0) div:eq(1)').css({ opacity: opacityCompute });
      }
     </script>
    </head>
    <body>
     <div id="map" style="position:relative; width:400px; height:400px;"></div>
     <div id="opacitySlider" style="position:relative; width:400px;"></div>
    </body>
    </html>
    

    MVP - Bing Maps - My blog (FR): http://blogs.developpeur.org/nicoboo/ Twitter: http://twitter.com/nicolasboonaert/
    Tuesday, April 12, 2011 2:38 PM
    Moderator
  • Hi Nicolas.

    Thanks again for your suggestion. However the problem with this approach is that occasionally we still get the issue of the opacity values going out-of-sync. I think this is due to some internal event occuring inside the map control after all the publicly exposed events have fired. For instance I tried binding to the viewchange and viewchangeend events and setting the opacity then, only to have the control set it back to it's own internal value (although this behaviour was not consistent).

    Regards,

    Neil.

    Tuesday, April 12, 2011 2:51 PM
  • Here is the last approach that might help you, in fact the logic around this:

    1. On slide you change the HTML opacity element and set opacity option to 100
    2. On change (which occurs after the slide) : you change the HTML opacity back to 100 and set options on Tilelayer
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     <title></title>
     <link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
     <script type="text/javascript" charset="UTF-8" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&mkt=en-gb"></script> 
     <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.2.min.js" type="text/javascript"></script>
     <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.11/jquery-ui.min.js" type="text/javascript"></script>
     <script type="text/javascript">
      var map, tileSource, tilelayer;
      var isOpacityChanged = false;
      $(function () {
        // Initialize the map
        map = new Microsoft.Maps.Map($('#map')[0], { credentials: "Your Bing Maps Key", center: new Microsoft.Maps.Location(48.03, -122.4), zoom: 12, mapTypeId: "r" });
    
        // Create the tile layer source
        tileSource = new Microsoft.Maps.TileSource({ uriConstructor: 'http://www.microsoft.com/maps/isdk/ajax/layers/lidar/{quadkey}.png' });
    
        // Construct the layer using the tile source
        tilelayer = new Microsoft.Maps.TileLayer({ mercator: tileSource, opacity: 1 });
    
        // Push the tile layer to the map
        map.entities.push(tilelayer);
    
    
        //set up slider
        $('#opacitySlider').slider({
          value: 100,
          slide: function (event, ui) {
            if (!isOpacityChanged) {
              tilelayer.setOptions({ opacity: 100 });
              isOpacityChanged = true;
            }
    
            $('.MicrosoftMap div div:eq(0) div:eq(1)').css({ opacity: (ui.value / 100) });        
          },
          change: function (event, ui) {
            tilelayer.setOptions({ opacity: (ui.value / 100) });
            $('.MicrosoftMap div div:eq(0) div:eq(1)').css({ opacity: 100 });
            isOpacityChanged = false;
          }
        });
    
      });
     </script>
    </head>
    <body>
     <div id="map" style="position:relative; width:400px; height:400px;"></div>
     <div id="opacitySlider" style="position:relative; width:400px;"></div>
    </body>
    </html>
    

    MVP - Bing Maps - My blog (FR): http://blogs.developpeur.org/nicoboo/ Twitter: http://twitter.com/nicolasboonaert/
    Tuesday, April 12, 2011 3:32 PM
    Moderator