
Security News
npm Tooling Bug Incorrectly Marks One-Character Packages as Security Holders
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.
leaflet-velocity-csl
Advanced tools
A custom layer for leaflet to visualise arbitrary velocities with ES module and UMD support
一个用于在 Leaflet 地图上可视化风场、洋流等矢量数据的插件。
npm install leaflet-velocity-csl
<!-- Leaflet 依赖 -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<!-- Leaflet Velocity 插件 -->
<link rel="stylesheet" href="https://unpkg.com/leaflet-velocity-csl/dist/leaflet-velocity.css" />
<script src="https://unpkg.com/leaflet-velocity-csl/dist/leaflet-velocity.js"></script>
适用于传统的 HTML 页面开发:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
<link rel="stylesheet" href="./dist/leaflet-velocity.css" />
</head>
<body>
<div id="map" style="height: 500px;"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="./dist/leaflet-velocity.js"></script>
<script>
// 初始化地图
const map = L.map('map').setView([25, 121], 6);
// 添加底图
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// 加载风场数据
fetch('./demo/wind-gbr.json')
.then(response => response.json())
.then(data => {
// 创建风场图层
const velocityLayer = L.velocityLayer({
data: data,
lineWidth: 2,
displayOptions: {
velocityType: 'Wind',
displayPosition: 'bottomleft',
displayEmptyString: '无数据'
}
});
// 添加到地图
velocityLayer.addTo(map);
// 添加控制面板
const control = L.control.velocity().addTo(map);
});
</script>
</body>
</html>
适用于现代前端框架(Vue、React、Angular 等):
// 引入 Leaflet
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
// 引入 Leaflet Velocity
import { velocityLayer, controlVelocity } from 'leaflet-velocity-csl';
import 'leaflet-velocity-csl/dist/leaflet-velocity.css';
// 初始化地图
const map = L.map('map').setView([25, 121], 6);
// 添加底图
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// 加载并添加风场数据
fetch('./wind-data.json')
.then(response => response.json())
.then(data => {
const velocity = velocityLayer({
data: data,
lineWidth: 2,
displayOptions: {
velocityType: 'Wind',
displayPosition: 'bottomleft'
}
});
velocity.addTo(map);
// 添加控制面板
const control = controlVelocity().addTo(map);
});
// 只引入需要的组件
import { VelocityLayer, ControlVelocity } from 'leaflet-velocity-csl';
// 或者使用 API 获取函数
import { getLeafletVelocityAPI } from 'leaflet-velocity-csl';
const api = getLeafletVelocityAPI();
const { velocityLayer, controlVelocity } = api;
<template>
<div id="map" ref="mapContainer" style="height: 500px;"></div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { velocityLayer } from 'leaflet-velocity-csl';
import 'leaflet-velocity-csl/dist/leaflet-velocity.css';
const mapContainer = ref(null);
let map = null;
onMounted(() => {
// 初始化地图
map = L.map(mapContainer.value).setView([25, 121], 6);
// 添加底图
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// 加载风场数据
loadWindData();
});
const loadWindData = async () => {
try {
const response = await fetch('./wind-data.json');
const data = await response.json();
const velocity = velocityLayer({
data: data,
lineWidth: 2,
displayOptions: {
velocityType: '风场',
displayPosition: 'bottomleft',
displayEmptyString: '无风场数据'
}
});
velocity.addTo(map);
} catch (error) {
console.error('加载风场数据失败:', error);
}
};
</script>
import React, { useEffect, useRef } from 'react';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { velocityLayer } from 'leaflet-velocity-csl';
import 'leaflet-velocity-csl/dist/leaflet-velocity.css';
const WindMap = () => {
const mapRef = useRef(null);
const mapInstance = useRef(null);
useEffect(() => {
if (!mapInstance.current) {
// 初始化地图
mapInstance.current = L.map(mapRef.current).setView([25, 121], 6);
// 添加底图
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')
.addTo(mapInstance.current);
// 加载风场数据
loadWindData();
}
return () => {
if (mapInstance.current) {
mapInstance.current.remove();
}
};
}, []);
const loadWindData = async () => {
try {
const response = await fetch('./wind-data.json');
const data = await response.json();
const velocity = velocityLayer({
data: data,
lineWidth: 2,
displayOptions: {
velocityType: 'Wind',
displayPosition: 'bottomleft'
}
});
velocity.addTo(mapInstance.current);
} catch (error) {
console.error('Failed to load wind data:', error);
}
};
return <div ref={mapRef} style={{ height: '500px', width: '100%' }} />;
};
export default WindMap;
const options = {
// 数据源
data: windData, // 风场数据(必需)
// 显示选项
displayOptions: {
velocityType: 'Wind', // 显示类型:'Wind'、'Ocean'、'Custom'
displayPosition: 'bottomleft', // 控制面板位置
displayEmptyString: '无数据', // 无数据时显示的文本
speedUnit: 'm/s', // 速度单位
directionString: '风向', // 方向标签
speedString: '风速' // 速度标签
},
// 粒子效果
lineWidth: 2, // 粒子轨迹宽度
colorScale: [
'rgb(36,104, 180)',
'rgb(60,157, 194)',
'rgb(128,205,193)',
'rgb(151,218,168)',
'rgb(198,231,181)',
'rgb(238,247,217)',
'rgb(255,238,159)',
'rgb(252,217,125)',
'rgb(255,182,119)',
'rgb(252,150,75)',
'rgb(250,112,52)',
'rgb(245,64,32)',
'rgb(237,45,28)',
'rgb(220,24,32)',
'rgb(180,0,35)'
], // 颜色映射
// 性能选项
maxVelocity: 10, // 最大速度值
velocityScale: 0.005, // 速度缩放因子
particleAge: 90, // 粒子生命周期
particleMultiplier: 1/300 // 粒子密度
};
const controlOptions = {
position: 'bottomleft', // 控制面板位置
emptyString: '无数据', // 无数据显示文本
angleConvention: 'bearingCCW', // 角度约定
showCardinal: true, // 显示基数方向
velocityUnit: 'm/s', // 速度单位
directionString: '方向:', // 方向标签
speedString: '速度:' // 速度标签
};
风场数据需要符合以下 JSON 格式:
[
{
"header": {
"parameterCategory": 2,
"parameterNumber": 2,
"dx": 0.5,
"dy": 0.5,
"la1": 90.0,
"la2": -90.0,
"lo1": 0.0,
"lo2": 359.5,
"nx": 720,
"ny": 361
},
"data": [/* U 分量数据数组 */]
},
{
"header": {
"parameterCategory": 2,
"parameterNumber": 3,
"dx": 0.5,
"dy": 0.5,
"la1": 90.0,
"la2": -90.0,
"lo1": 0.0,
"lo2": 359.5,
"nx": 720,
"ny": 361
},
"data": [/* V 分量数据数组 */]
}
]
parameterNumber: 2 - U 分量(东西方向)parameterNumber: 3 - V 分量(南北方向)dx, dy - 网格间距(度)la1, la2 - 纬度范围lo1, lo2 - 经度范围nx, ny - 网格数量data - 对应的数值数组创建一个新的风场图层。
参数:
options (Object) - 配置选项返回:
创建一个风场控制面板。
参数:
options (Object) - 控制面板选项返回:
更新风场数据。
参数:
data (Array) - 新的风场数据更新配置选项。
参数:
options (Object) - 新的配置选项A: 可以通过以下方式优化性能:
const options = {
data: windData,
particleMultiplier: 1/500, // 减少粒子密度
particleAge: 60, // 缩短粒子生命周期
lineWidth: 1 // 减小线宽
};
A: 修改 colorScale 选项:
const customColors = [
'#0000FF', // 蓝色 - 低速
'#00FF00', // 绿色 - 中速
'#FFFF00', // 黄色 - 高速
'#FF0000' // 红色 - 极高速
];
const velocityLayer = L.velocityLayer({
data: windData,
colorScale: customColors
});
A: 针对移动端可以使用以下配置:
const mobileOptions = {
data: windData,
particleMultiplier: 1/800, // 更少的粒子
lineWidth: 1, // 更细的线条
particleAge: 45, // 更短的生命周期
velocityScale: 0.01 // 调整速度缩放
};
详见 LICENSE.md 文件。
欢迎提交 Issue 和 Pull Request!
FAQs
A custom layer for leaflet to visualise arbitrary velocities with ES module and UMD support
The npm package leaflet-velocity-csl receives a total of 11 weekly downloads. As such, leaflet-velocity-csl popularity was classified as not popular.
We found that leaflet-velocity-csl demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
npm confirmed a tooling bug incorrectly marked several one-character packages as security holders and said it was working on a rollback.

Research
/Security News
Newer packages in this compromise use native extensions and .pth loaders to execute JavaScript stealers in developer environments.

Research
Socket found 37 malicious PyPI wheels that abuse Python startup hooks to launch a Bun-powered credential stealer tied to Mini Shai-Hulud/Miasma.