自然灾害数据是理解地球动态系统中风险分布的基础信息载体。不同的灾害类型、不同的时空尺度、不同的严重程度,构成了一个多维的信息网络。将这些分散的、异构的灾害事件数据汇聚为一个统一的可比较、可筛选、可追溯的整体,是人类在面对自然灾害时从被动响应走向主动认知的关键一步。

真正的价值不在于数据的简单罗列,而在于通过结构化的分类与可视化的表达,揭示灾害发生的时空规律、类型分布与严重程度格局。当数据从孤立的事件描述转化为可交互的知识图谱时,决策者才能在对的时间、对的地点、以前瞻性的视角做出判断——这正是灾害数据聚合分析所承载的深层使命。

灾害事件数据的聚合分析,遵循"获取—解析—筛选—统计—可视化—导出"的六步方法论。

步骤一:数据获取

从权威灾害监测机构的数据接口获取原始数据。请求需携带必要的筛选参数,包括灾害类型(地震、热带气旋、洪水、火山、干旱、野火)、警报级别(绿/橙/红)、时间范围以及分页信息。参数通过查询字符串编码,以标准 HTTP 协议发送请求并接收响应。

步骤二:数据解析与标准化

原始响应数据采用地理信息领域标准的空间数据交换格式(GeoJSON)。解析时需遍历特征集合中的每个要素,提取其属性字段(事件编号、标题、类型、国家、时间、警报级别、严重程度、受灾人口)和几何字段(经纬度坐标)。同时还需兼容数组格式的备选响应结构,确保对不同版本接口的适配能力。

除了 JSON 格式外,部分数据源也以 XML 格式的订阅源方式提供。对于 XML 数据,需要构建文档对象模型树并遍历其中的条目节点,通过命名空间区分自定义字段与标准字段,从中提取相同的事件属性。两种格式的数据经过解析后应统一映射为相同的内部数据结构,保证后续处理的一致性。

步骤三:多维筛选与分页

用户根据需求选择灾害类型、警报等级和时间区间进行过滤。时间区间校验是关键环节:起始日期不得晚于截止日期,区间跨度需控制在一年的合理范围内。筛选结果按页分割,每页固定数量,通过页码索引实现数据的分批浏览。

步骤四:统计分析与可视化

对筛选后的事件集合进行三类统计:

  • 类型分布统计:按灾害类别聚合计数,以环形比例图呈现各类事件的占比关系。
  • 警报级别统计:按红/橙/绿三个等级分别计数,以柱状图展示各级别的数量对比,颜色与实际警报色对应。
  • 时间分布统计:将事件按发生时间排序,以散点图在时间轴上排列,点色反映警报级别,悬停可查看事件详情。

图表需支持动态主题适配,特别是色彩空间从感知均匀空间到显示设备空间的实时转换,确保在不同配色环境下图表的可读性。

步骤五:数据导出

将内存中的结构化事件数据序列化为 JSON 文本,打包为二进制大对象,生成临时下载链接并触发浏览器下载。导出前确保数据已通过筛选与解析流程,内容是最终面向用户的有效数据。

设计原则

  1. 数据溯源原则:每条事件保留原始来源链接,用户可追溯查看详细报告。
  2. 容错优先原则:接口响应格式可能存在差异,解析逻辑应兼容多种数据结构并妥善处理缺失字段。
  3. 时间一致原则:所有事件时间统一采用协调世界时(UTC),避免时区混淆导致的时间比对偏差。

本项目在 TypeScript 中使用了以下技术栈和算法实现。

数据获取

Web Fetch API

使用浏览器内置的 fetch 函数发起 HTTP GET 请求,通过 URLSearchParams 构建查询字符串。

const params = new URLSearchParams()
params.set('fromdate', startDate!)
params.set('todate', endDate!)
params.set('pagenumber', formData.pageNumber.toString())
params.set('pagesize', formData.pageSize.toString())

const url = `https://www.gdacs.org/gdacsapi/api/events/geteventlist/SEARCH?${params.toString()}`
const response = await fetch(url)
  • 说明:Fetch API 是浏览器原生支持的 HTTP 客户端,无需额外安装。
  • 参考:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

数据解析

GeoJSON 格式处理

GDACS 接口返回的数据为 GeoJSON FeatureCollection 结构,核心数据结构定义如下:

export interface GdacsFeature {
  type: string
  properties: {
    eventid: string
    eventtype: string
    name: string
    title: string
    alertlevel: string
    severity: string
    fromdate: string
    todate: string
    country: string
    population: number
    url: string
    geometry: { type: string; coordinates: number[] }
  }
  geometry: { type: string; coordinates: number[] }
}

export interface GdacsApiResponse {
  type: string
  features: GdacsFeature[]
}

解析时将 FeatureCollection 中的每个 feature 映射为内部使用的 GdacsEvent 结构,同时兼容数组格式的直接响应:

if (jsonData.type === 'FeatureCollection' && jsonData.features) {
  events = jsonData.features.map((feature: any) => {
    const props = feature.properties || {}
    const coords = feature.geometry?.coordinates || []
    return {
      id: props.eventid || '',
      title: props.title || '',
      latitude: parseFloat(props.latitude) || parseFloat(coords[1]) || 0,
      longitude: parseFloat(props.longitude) || parseFloat(coords[0]) || 0,
      // ... 其他字段映射
    }
  })
}
  • 参考:https://geojson.org/

DOMParser XML 解析

对于 XML 格式的 RSS 订阅源数据,使用浏览器内置 DOMParser 解析,并通过命名空间提取自定义字段:

function parseGdacsXml(xmlText: string): GdacsEvent[] {
  const parser = new DOMParser()
  const xmlDoc = parser.parseFromString(xmlText, 'text/xml')
  const items = xmlDoc.querySelectorAll('item')
  const gdacsNamespace = 'http://www.gdacs.org'

  items.forEach((item) => {
    const gdacsAlertLevel = getGdacsElementContent(item, gdacsNamespace, 'alertlevel')
    const gdacsLat = parseFloat(getGdacsElementContent(item, gdacsNamespace, 'lat') || '0')
    // ...
  })
}

function getGdacsElementContent(
  parent: Element, namespace: string, tagName: string
): string | null {
  const elements = parent.getElementsByTagNameNS(namespace, tagName)
  return elements.length > 0 ? elements[0]!.textContent : null
}
  • 说明:DOMParser 是浏览器原生 API,用于将 XML 字符串解析为 DOM 树。
  • 参考:https://developer.mozilla.org/en-US/docs/Web/API/DOMParser

数据可视化

Apache ECharts (echarts)

用于绘制交互式图表,支持环形图、柱状图、散点图三种类型。

  • 包名:echarts
  • npm:https://www.npmjs.com/package/echarts
  • 官网:https://echarts.apache.org/
  • 在本项目中:生成事件类型分布(pie)、警报级别统计(bar)、时间分布(scatter)三张图表,每张图表支持动态主题色注入。

图表的 ECharts Option 通过工厂函数生成,以警报级别柱状图为例:

import * as echarts from 'echarts'

export function generateAlertLevelChart(
  data: GdacsEvent[], theme: ChartThemeColors
): EChartsOption {
  return {
    backgroundColor: 'transparent',
    tooltip: { trigger: 'axis' },
    xAxis: {
      type: 'category',
      data: Object.keys(levelCounts),
    },
    yAxis: { type: 'value', name: '数量' },
    series: [{
      type: 'bar',
      data: Object.entries(levelCounts).map(([level, count]) => ({
        value: count,
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: getAlertLevelColor(level) },
            { offset: 1, color: getAlertLevelColor(level) + '80' },
          ]),
        },
      })),
    }],
  }
}

色彩空间转换算法

OKLCH 到 sRGB 十六进制转换

本项目的核心算法之一:将 DaisyUI 主题使用的 OKLCH 色彩空间转换为 ECharts 渲染所需的 sRGB 十六进制颜色值。

  • 算法来源:自实现,遵循 CSS Color Module Level 4 规范中的 OKLCH 到 sRGB 转换数学公式。
export function oklchToHex(color: string): string {
  const match = color.match(/oklch\(([\d.]+)(%?)\s+([\d.]+)\s+([\d.]+)\)/)
  if (!match) return null
  let L = parseFloat(match[1]!)
  if (match[2] === '%' || L > 1) L = L / 100
  const { L, C, H } = parts

  // OKLCH → OKLab
  const hRad = (H * Math.PI) / 180
  const a = C * Math.cos(hRad)
  const b = C * Math.sin(hRad)

  // OKLab → Linear sRGB
  const l_ = L + 0.3963377774 * a + 0.2158037573 * b
  const m_ = L - 0.1055613458 * a - 0.0638541728 * b
  const s_ = L - 0.0894841775 * a - 1.291485548 * b

  const l3 = l_ * l_ * l_
  const m3 = m_ * m_ * m_
  const s3 = s_ * s_ * s_

  let r = +4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3
  let g = -1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3
  let bl = -0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3

  // Gamma 校正 (sRGB transfer function)
  const gamma = (c: number) =>
    c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055

  r = gamma(r); g = gamma(g); bl = gamma(bl)

  // 输出十六进制
  const hex = (c: number) => {
    const v = Math.round(Math.max(0, Math.min(1, c)) * 255)
    return v.toString(16).padStart(2, '0')
  }
  return `#${hex(r)}${hex(g)}${hex(bl)}`
}

转换路径:OKLCH → OKLab → Linear sRGB → Gamma校正 → sRGB HEX。

日期处理

date-fns

  • 包名:date-fns
  • npm:https://www.npmjs.com/package/date-fns
  • 在本项目中:提供中文日期本地化配置(zhCN locale),用于日期选择器的界面显示。

文件导出

Blob + URL.createObjectURL

使用浏览器原生 API 实现客户端文件下载,无需服务端参与:

export function downloadJson(data: GdacsEvent[], filename: string = 'gdacs_events.json'): void {
  const jsonStr = JSON.stringify(data, null, 2)
  const blob = new Blob([jsonStr], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}
  • 参考:https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL

技术架构数据流

用户输入参数 → URLSearchParams 编码 → fetch() 请求 GDACS API
                                        ↓
                              GeoJSON / Array 响应
                                        ↓
                           数据标准化 (GdacsEvent[])
                                        ↓
                      ┌─────────────────┼─────────────────┐
                      ↓                 ↓                  ↓
                 环形图(Pie)       柱状图(Bar)      散点图(Scatter)
                事件类型分布      警报级别统计        时间分布
                      ↑                 ↑                  ↑
                      └─────────────────┼──────────────────┘
                                        ↓
                              ECharts Instance 渲染
                              (OKLCH→sRGB 主题色注入)
                                        ↓
                              JSON.stringify → Blob → 下载

GDACS 灾害数据

从 GDACS 获取全球灾害事件数据

查询参数

工具简介

本工具从全球灾害预警与协调系统(GDACS)获取实时的全球自然灾害事件数据,支持按事件类型、警报级别和时间范围进行筛选查询。查询结果以统计概览、可视化图表和事件列表三种形式呈现,并支持将数据导出为 JSON 文件。

支持的输入类型

筛选项 可选值
事件类型 全部类型 / 地震 / 热带气旋 / 洪水 / 火山 / 干旱 / 野火
警报级别 全部级别 / 绿色 / 橙色 / 红色
开始日期 1900-01-01 至 当日,默认 30 天前
结束日期 不早于开始日期,不晚于当日,默认当日

操作步骤

  1. 设置查询条件:在页面上方的查询参数区域,分别选择事件类型、警报级别、开始日期和结束日期。事件类型和警报级别选择"全部"可获取全量数据。日期通过日期选择器点选。

  2. 发起查询:点击"查询数据"按钮。系统将向 GDACS 服务器发送请求,按钮显示加载动画,请耐心等待。

  3. 查看结果

    • 数据概览:展示事件总数及各警报级别的数量(红/橙/绿三色卡片)。
    • 可视化图表:切换"事件类型分布""警报级别统计""时间分布"三个标签页,以不同图表形式观察数据特征。环形图展示灾害类型占比,柱状图对比各级别数量,散点图在时间轴上排列事件。
    • 事件列表:表格列出每条事件的警报级别(以对应颜色标签标识)、类型、标题、国家、经纬度坐标和时间。点击"查看详情"可跳转至 GDACS 官网的完整报告页面。
  4. 翻页浏览:若事件数量超过每页 20 条,列表底部将出现分页控件。点击页码或"上一页/下一页"按钮切换页面。

  5. 导出数据:点击"下载 JSON"按钮,将当前查询的所有事件数据以 JSON 格式保存到本地文件。

  6. 清除结果:点击"清除结果"按钮可清空当前展示的所有数据,重新开始查询。

输入约束

  • 开始日期不能大于结束日期,否则查询按钮不可用。
  • 日期范围不能超过 365 天(约一年),否则将显示错误提示。
  • 日期范围不能少于 1 天。
  • 日期选择器限定可选用期不晚于当天、不早于 1900 年 1 月 1 日。
  • 每页固定显示 20 条事件记录,不可调整。

注意事项

  1. 网络依赖:本工具直接请求 GDACS 官方网站的公开 API。如果 GDACS 服务器不可达或响应超时,查询将失败并显示错误提示。请确保网络畅通。GDACS 服务位于境外,国内用户可能出现访问延迟或失败,建议在网络状况良好时使用。

  2. 数据时效性:查询结果反映的是 GDACS 在当前时刻已收录的事件数据。不同时间段查询同一日期范围,结果可能会因 GDACS 数据更新而有所差异。事件列表和图表不会自动刷新,如需最新数据请重新点击"查询数据"。

  3. 时区说明:所有事件时间均为 UTC(协调世界时)。北京时间比 UTC 快 8 小时。例如列表中出现 10:00 的时间,对应的北京时间为当天 18:00。进行时间比对时请注意时区转换。

  4. 坐标精度:经纬度坐标保留四位小数。该精度足以标识灾害发生的大致区域,但不适用于需要精确定位的场景(如现场救援导航)。坐标来源于 GDACS 官方数据,本工具不做坐标变换或投影转换。

  5. 事件数据可能缺失部分字段:GDACS 对不同类型事件所提供的信息详细程度可能不一致。部分事件的描述、受灾人口或国别信息可能为空,这是数据源本身的限制,不属于工具异常。页面会对空值字段进行缺省显示处理。

  6. 图表与列表的数据一致性:图表和列表的数据来源于同一次查询结果,但图表会根据事件的特征字段(如类型、级别)进行聚合展示。在时间分布散点图中,由于同一时间可能重叠多个事件,图表展示的是趋势概览而非逐条明细。详细的事件级信息应以列表为准。

  7. 导出文件内容:下载的 JSON 文件包含当前查询返回的所有事件(不受分页限制),字段与页面展示的 GdacsEvent 结构一致。文件名默认为 gdacs_events.json,文件编码为 UTF-8。

中国各省访问量分布图

鼠标悬停查看各省份的访问数据统计

用户评论

所有评论均为匿名发布

1 浏览0 条评论
nfCf
暂无评论,来说两句吧