leaflet 降雨等值面的动画效果

leaflet 降雨等值面的动画展示效果

参考1:https://www.msn.cn/zh-cn/weather/maps msn天气

参考2:https://github.com/lwsu/leaflet-polygon-fillPattern

看见msn上的天气地图, 降雨等值面 动画效果很漂亮。于是看了下代码。 复制了一份。

代码:


(function (window, document, undefined) {
if (L.Browser.svg) {
    L.SVG.include({
        _updateStyle: function (layer) {
            var path = layer._path,
                options = layer.options

            if (!path) { return }

            if (options.stroke) {
                path.setAttribute('stroke', options.color)
                path.setAttribute('stroke-opacity', options.opacity)
                path.setAttribute('stroke-width', options.weight)
                path.setAttribute('stroke-linecap', options.lineCap)
                path.setAttribute('stroke-linejoin', options.lineJoin)

                if (options.dashArray) {
                    path.setAttribute('stroke-dasharray', options.dashArray)
                } else {
                    path.removeAttribute('stroke-dasharray')
                }

                if (options.dashOffset) {
                    path.setAttribute('stroke-dashoffset', options.dashOffset)
                } else {
                    path.removeAttribute('stroke-dashoffset')
                }
            } else {
                path.setAttribute('stroke', 'none')
            }

            if (options.fill) {
                if (typeof (options.fill) === 'string' &&
                        options.fill.match(/^url\(/)) {
                    // here what we add
                    this.__fillPattern(layer)
                } else {
                    path.setAttribute('fill', options.fillColor || options.color)
                }
                path.setAttribute('fill-opacity', options.fillOpacity)
                path.setAttribute('fill-rule', options.fillRule || 'evenodd')
            } else {
                path.setAttribute('fill', 'none')
            }
        },

        __fillPattern: function(layer) {
            var values = '0;-200;-400;-600;-800;-1000;-1200;-1400;-1600;-1800;-2000;-2200;-2400;-2600;-2800'
            var height = '200'
            var width = '200'

            var path = layer._path,
                options = layer.options

            if (!this._defs) {
                this._defs = L.SVG.create('defs')
                this._container.appendChild(this._defs)
            }
            var _img_url = options.fill.substring(4, options.fill.length - 1)
            var _ref_id = _img_url + (Math.random() * Math.pow(10, 17) + Math.random() * Math.pow(10, 17))
            _ref_id += new Date().getUTCMilliseconds()
            var _p = document.getElementById(_ref_id)
            if (!_p) {
                var _im = new Image()
                _im.src = _img_url

                _p = L.SVG.create('pattern')
                _p.setAttribute('id', _ref_id)
                _p.setAttribute('x', '0')
                _p.setAttribute('y', '0')
                _p.setAttribute('patternUnits', 'userSpaceOnUse')
                _p.setAttribute('width', width)
                _p.setAttribute('height', height)
                var _rect = L.SVG.create('rect')
                _rect.setAttribute('width', width)
                _rect.setAttribute('height', height)
                _rect.setAttribute('x', 0)
                _rect.setAttribute('y', 0)
                _rect.setAttribute('fill', options.fillColor || options.color)

                _p.appendChild(_rect)
                this._defs.appendChild(_p)

                var _img = L.SVG.create('image')
                _img.setAttribute('x', '0')
                _img.setAttribute('y', '0')
                _img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', _img_url)
                _img.setAttribute('width', width)
                _img.setAttribute('height', height)

                var_animate = L.SVG.create('animate')
                var_animate.setAttribute('attributeType', 'XML')
                var_animate.setAttribute('attributeName', 'x')
                var_animate.setAttribute('calcMode', 'discrete')
                var_animate.setAttribute('values', values)
                var_animate.setAttribute('dur', '1s')
                var_animate.setAttribute('repeatCount', 'indefinite')
                _img.appendChild(var_animate)
                _p.appendChild(_img)

                _im.onload = function() {
                    _p.setAttribute('width', width)
                    _p.setAttribute('height', height)
                    _img.setAttribute('width', '3000')
                    _img.setAttribute('height', height)
                }
            }
            path.setAttribute('fill', 'url(#' + _ref_id + ')')
        }
    })
}
}(this, document))

如何使用:


 let json = L.geoJSON(feature, {
      style: function (feature) {
        let val = feature.properties.val
        let fill = 'url(/static/img/rain-low.png)'
        let fillOpacity = 0.5
        let color = '#fff'
        let itm = surfaceOption.level
        if (val === itm[0].value) {
          color = itm[0].color
          fillOpacity = 0.1
          fill = null
        } else if (val === itm[1].value) {
          color = itm[1].color
          fillOpacity = 0.3
          fill = 'url(/static/img/rain-low.png)'
        } else if (val === itm[2].value) {
          color = itm[2].color
          fillOpacity = 0.7
          fill = 'url(/static/img/rain-low.png)'
        } else if (val === itm[3].value) {
          color = itm[3].color
          fillOpacity = 0.9
          fill = 'url(/static/img/rain-avg.png)'
        } else if (val === itm[4].value) {
          color = itm[4].color
          fillOpacity = 0.9
          fill = 'url(/static/img/rain-avg.png)'
        } else if (val === itm[5].value) {
          color = itm[5].color
          fillOpacity = 0.7
          fill = 'url(/static/img/rain-hvy.png)'
        } else if (val === itm[6].value) {
          color = itm[6].color
          fillOpacity = 0.7
          fill = 'url(/static/img/rain-hvy.png)'
        } else {
          fillOpacity = 0
        }
        return {
          stroke: false,
          fillColor: color,
          color: color,
          // weight: 0.5,
          fillOpacity: fillOpacity,
          fill: fill
        }
      },
      onEachFeature: function (feature, layer) {
        layer.addTo(layerGroup)
 
      }
    })

引用的PNG:可以直接在msn 天气网站上下载

1、rain-low.png(图片半透明效果看不见, 直接在下面鼠标右键将图片另存为)

请添加图片描述

2、rain-avg.png(图片半透明效果看不见, 直接在下面鼠标右键将图片另存为)请添加图片描述
3、rain-hvy.png(图片半透明效果看不见, 直接在下面鼠标右键将图片另存为)

请添加图片描述

展示效果:

直接在msn上截图
在这里插入图片描述

Leaflet中,可以通过Leaflet.Contour插件来实现等值计算和绘制。 具体实现步骤如下: 1. 准备数据。等值需要的是二维网格数据,可以使用WebGL或者其他地图库(如Mapbox、OpenLayers等)来获取高程数据,也可以使用自己的数据源。 2. 加载数据并转换为合适的格式。Leaflet.Contour插件需要的数据格式为: ```javascript var data = { x: [], // 横坐标数组 y: [], // 纵坐标数组 z: [], // 高程值数组 nx: 100, // x方向网格数量 ny: 100, // y方向网格数量 dx: 1, // x方向网格间距 dy: 1 // y方向网格间距 } ``` 3. 进行等值计算。可以使用turf.js等插件来进行计算。 ```javascript var contours = turf.contour(data, [10, 20, 30, 40, 50]); // 进行等值计算,计算5个等值,高度分别为10, 20, 30, 40, 50 ``` 4. 将等值添加到Leaflet地图中。可以使用Leaflet.Contour插件提供的L.contourLayer()方法来实现。 ```javascript var contourLayer = L.contourLayer(contours, { style: function (feature) { return { color: 'black', weight: 1, fillColor: getColor(feature.properties.index), fillOpacity: 0.8 }; } }).addTo(map); // 将等值添加到Leaflet地图中 function getColor(d) { return d === 0 ? '#FFEDA0' : d === 1 ? '#FEB24C' : d === 2 ? '#FD8D3C' : d === 3 ? '#FC4E2A' : d === 4 ? '#E31A1C' : d === 5 ? '#BD0026' : d === 6 ? '#800026' : '#FFFFFF'; } // 定义等值填充颜色函数 ``` 需要注意的是,等值计算和绘制需要较高的计算资源和较大的数据存储空间,同时在展示过程中也需要进行优化,以保证地图的流畅性和渲染效果
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值