在flexbox计算高度后渲染传单地图

时间:2016-04-01 17:57:02

标签: css angularjs leaflet flexbox angularjs-animation

我正在尝试在灵活的孩子中绘制一个占用剩余空间的地图。

我在主要内容的顶部有几个标题,其中一个横幅有时会被隐藏/删除,所以我使用的是flexbox,这样标题就可以消失,而不会影响其他元素的位置。 I.E当我使用绝对位置时,这不起作用。

我的问题是,在Flexbox计算了地图div的高度之前,传单似乎正在计算地图视口。

示例:

这是一张传单的截图,认为地图的高度应该小于应有的值。

enter image description here

如果我检查元素高度是否正确。此外,如果我将计时器放入并强制使用传单使地图大小无效,则地图将重新渲染到正确的高度。

HTML:

<body>
  <div class="header">
      Header
  </div>

  <div class="banner">
      Banner
  </div>

  <main class="main">
    <div class="nav">
      <strong>Navigation</strong>
    </div>

    <div id="map" class="map-content"></div>   
  </main>


    <script src="script.js"></script>
  </body>

CSS:

html, body {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
}

.header {
    height: 50px;
    background-color: grey;
    color: white;
}

.banner { 
    height: 50px;
    background-color: lightgrey;
    color: white;
}

.main {
    display: flex;
    flex: 1 1 auto;
    flex-direction: row;
}

.map-content {
   flex: 1 1 auto;
}

.nav {
    background-color: #2A3D4A;
    color: white;
    width: 200px;
}

修改

我已经把这个问题复制了一下,万岁!但是我仍然不知道究竟发生了什么。只有在我的应用程序中包含ngAnimate时才会出现此问题。如果我使用ngAnimate,无关紧要。

这是被打破的插件。在初始页面加载时,地图很好。单击about链接,然后返回到地图。请注意,返回时,只有大约一半的地图加载。我将高度记录到控制台。当您离开地图并返回时,它总是大约一半大小。

角度动画是做什么来使元素在一瞬间变成一半大小?这是角度的错误吗?

http://plnkr.co/edit/dyBH1Szo3lIEWajKqXWj?p=preview

3 个答案:

答案 0 :(得分:5)

看起来传单地图在创建时获得高度,然后如果高度发生变化则需要调用.invalidateSize()。在传单文档中,它指出Make sure the map container has a defined height, for example by setting it in CSS(参见http://leafletjs.com/examples/quick-start.html)。由于您没有明确设置高度,而是使用css规则position: absolute; top:0; bottom: 0; left: 0; right: 0;,因此它有点狡猾。

我认为问题在于,当你加入ngAnimate时,它会对具有transition属性的元素产生影响,并且不知何时正确的高度不会被传单及时看到。我想你需要使用一种解决方法,例如检测身高变化并致电.invalidateSize()

尝试将此添加到您的指令:

link: function(scope, element) {
  scope.$watch(function() { return element.parent().height(); }, function (val) {
    console.log('height changed to: ' + val);
    scope.map.invalidateSize();
  });
},
scope: true,

使控制器设置为$scope.map = L.map('map',{crs: L.CRS.EPSG4326}).setView([0,0], 4);,以便传单地图对象位于范围内,并删除.map-content上的css规则

答案 1 :(得分:2)

我有类似的问题。发生的事情是,当指令加载时,后链接函数计算div元素的clientHeight。 div用flex填充剩余的空间。但它总是有些偏差。在从Web服务器检索到所有模板部分之前,我将其跟踪到角度调用post链接。另一个指令仍在等待其urlTemplate,一旦它进入,该指令导致另一个div改变高度。

如果我只是暂停了足够的时间,那就解决了这个问题。此外,如果我在晚期div中广播一个事件并在计算高度之前等待它,这也可以解决问题。

我找不到一个简单的方法来判断何时加载了所有模板,并且所有指令都完成了操作DOM的操作。指令优先权绝对没有改变事物的顺序。

查看浏览器中的事件序列,看看它是否不是一个迟到的部分模板,足以甩掉时间,以便在你要求执行计算时不会完全执行计算。

答案 2 :(得分:1)

Edited plunkr:http://plnkr.co/edit/pIg9HKwkl0Bfhk4N3wQX?p=preview

尝试&#34; invalide&#34;像这样的地图:

app.directive('leaflet', ['$document','$timeout', function($document,$timeout) {

  function controller() {
    console.log('in leaflet directive controller');

    var element = $document.find('#map');
    console.log('main container height: ' + element[0].offsetHeight);

    var map = L.map('map',{crs: L.CRS.EPSG4326}).setView([0,0], 4);
    L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

    // the timeout wait the view to render
    $timeout(function () {
       // this rebuild the map
       map.invalidateSize();
    }, 0);
  }

  return {
    template: '<div id="map" class="map-content"></div>',
    controller: controller,
    replace: true
  }

}]);