Leaflet 自定义Popup弹窗

news/2024/7/19 14:13:39 标签: js, javascript

首先感谢 Leaflet - 自定义弹出框(popup)提供的扩展

但是实际结合组件化的使用过程中,对于弹窗内元素的高宽存在不确定性(即初始化时不传入容器的宽高),所以需要进一步对Popup组件进行拓展,以便适应更自由的窗体组件

稍微解读了下Leaflet对于popup组件的源代码,其实popup对于整体的地图容器来说,也只是地图上根据像素位置定位的元素之一,因此对其的控制也和其它图层一样,对初始化、更新、层级变化做监听,修改位置和样式即可,以下是代码(ES5)

javascript">// 重写setTransform,由于不再固定宽度,所以增加translateX(-50%)水平居中
function setTransform(el, offset, scale) {
  var pos = offset || new L.Point(0, 0);
  el.style[L.DomUtil.TRANSFORM] =
    (L.Browser.ie3d
      ? "translate(" + pos.x + "px," + pos.y + "px,0) translateX(-50%)"
      : "translate3d(" + pos.x + "px," + pos.y + "px,0) translateX(-50%)") +
    (scale ? " scale(" + scale + ")" : "");
}
// 因为重写了setTransform,所以setPosition也要重新指向方法
function setPosition(el, point) {
  el._leaflet_pos = point;
  if (L.Browser.any3d) {
    setTransform(el, point);
  } else {
    el.style.left = point.x + "px";
    el.style.top = point.y + "px";
  }
}

自定义集成popup模块

javascript">L.CustomPopup = L.Popup.extend({
  _initLayout: function() {
    // 此处生成的容器,Leaflet会根据其类名自动适配Transform,匹配样式,所以如果要自定义的话,该部分样式要自己重写,我这里只解决了自适应容器的问题,以下采用原生容器,所以后面我会加上样式覆盖。
    var prefix = "leaflet-popup",
      container = (this._container = L.DomUtil.create(
        "div",
        prefix + " " + (this.options.className || "") + " leaflet-zoom-animated"
      ));
    var wrapper = container;
    this._contentNode = L.DomUtil.create("div", prefix + "-content", wrapper);
    L.DomEvent.disableClickPropagation(wrapper)
      .disableScrollPropagation(this._contentNode)
      .on(wrapper, "contextmenu", L.DomEvent.stopPropagation);
    this._tipContainer = L.DomUtil.create(
      "div",
      prefix + "-tip-container",
      container
    );
    this._tip = L.DomUtil.create("div", prefix + "-tip", this._tipContainer);
  },
  // 位置更新
  _updatePosition: function() {
    if (!this._map) {
      return;
    }
    var pos = this._map.latLngToLayerPoint(this._latlng),
      offset = L.point(this.options.offset),
      anchor = [0, 0];
    if (this._zoomAnimated) {
      setPosition(this._container, pos.add(anchor));
    } else {
      offset = offset.add(pos).add(anchor);
    }
    var bottom = (this._containerBottom = -offset.y),
      left = (this._containerLeft =
        -Math.round(this._containerWidth / 2) + offset.x);
    // bottom position the popup in case the height of the popup changes (images loading etc)
    this._container.style.bottom = bottom + "px";
    this._container.style.left = left + "px";
  },
  // 重写层级变化触发更新
  _animateZoom: function(e) {
    var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center),
      anchor = [0, 0];
    setPosition(this._container, pos.add(anchor));
  }
});

因为使用的是原生生成的容器,所以这里要强制覆盖原生CSS

.leaflet-popup-content{
   width: fit-content !important;
   margin: 0 !important;
}

以上就完成了自定义弹窗了

然后就是正常使用

javascript">let testPopup = new L.CustomPopup({
   className: "layerPopup",
   // minWidth: 300, // 这里不再传入固定宽度啦
   offset: L.point(0, -10)
}).setLatLng(latlng).setContent("<div id='popupContainer'></div>");
testPopup.openOn(this.map);

这里注册一下用于弹窗的组件

javascript">import popupAlarmContainer from "./layerPopup/alarm.vue";
let PopupAlarm = Vue.extend(popupAlarmContainer);
let popupContent = new PopupAlarm({
   propsData: {
      popupInfo: {} // 需要传入的props参数
   }
});
popupContent.$mount("#popupContainer");

到这里为止alarm.vue组件就注册到这个自定义弹窗了,后续我们只要针对alarm.vue进行弹窗组件的样式控制和逻辑业务开发就好了,完美解脱Leaflet原生Popup的控制。

后续有时间我会进一步优化,并将该组件扩展上传至npm库及Leaflet Plugins


http://www.niftyadmin.cn/n/841097.html

相关文章

1:20,1:100,1:400杠杆有什么不同

从事外汇杠杆交易&#xff0c;或者说外汇保证金交易&#xff08;同一个产品不同说法&#xff09;&#xff0c;从实质上说&#xff0c;就是从事合约的买卖。 第一、 外汇的国际报价都是五位数&#xff0c;就以欧元为例&#xff0c;欧元/美圆1.1820&#xff0c;这代表1欧元…

Jquery中AJAX参数详细(1)-转

http://www.cnblogs.com/qiufuwu618/archive/2012/12/20/2826190.html Jquery中AJAX参数详细列表&#xff1a; 参数名类型描述urlString(默认: 当前页地址) 发送请求的地址。typeString(默认: "GET") 请求方式 ("POST" 或 "GET")&#xff0c; 默…

Android Studio 换主题 + 背景图片 + 去掉白色竖线

1.去掉AS编辑区域右边的白色竖线&#xff1a; 把right margin 设置的大一点就可以了&#xff0c;默认是120 &#xff0c;设置成 1200就ok了 2.AS主题下载换装 可以去如下网站下载&#xff0c;然后导入jar&#xff0c; 具体用法百度&#xff1a; Color Themeshttp://color-theme…

Eclipse远程调试Java应用程序:实用技巧

软件开发中&#xff0c;调试是不可或缺的一个环节&#xff0c;它可以帮助开发人员提高效率&#xff0c;节省开发时间。在我认为&#xff0c;本地调试是最优选择&#xff0c;通常情况下&#xff0c;当无法实现本地调试时&#xff0c;我们才会考虑远程调试。 有些项目是运行在Lin…

ES6 对象数组的深拷贝

对于数组的深拷贝&#xff0c;习惯性的使用 […arr] 建立新地址&#xff0c;偶然间对某份对象数组数据进行同样的深拷贝时&#xff0c;发现修改新数组内部对象的元素依旧会影响到原数组对象 例如 let a [{ name: "小李" } ]; let b [...a]; b[0].name "小张…

7正则表达式

在前面我们已经搞定了怎样获取页面的内容&#xff0c;不过还差一步&#xff0c;这么多杂乱的代码夹杂文字我们怎样把它提取出来整理呢&#xff1f;下面就开始介绍一个十分强大的工具&#xff0c;正则表达式&#xff01;1.了解正则表达式正则表达式是对字符串操作的一种逻辑公式…

hehe

记主几条&#xff1a;1&#xff0c;股票是先1线股涨的&#xff0c;到快结束的时候是3线股涨的&#xff0c;外汇也一样&#xff0c;当欧元不涨了&#xff0c;英棒大涨的时候往往是最高点&#xff0c; 2&#xff0c;做主力品种&#xff0c;就象做股票要做1线股的&#xff0c;做外…

Leaflet提升加载性能(一)

实际应用中&#xff0c;经常会出现海量图层数据导致的页面性能下降的问题&#xff0c;这里我提供几个思路&#xff0c;今天先从Layer层来解决好了。 我们知道&#xff0c;Leaflet支持svg和canvas两种渲染器。正常来说&#xff0c;svg渲染适合少量的&#xff0c;实时配置的动态活…