mcpField
A
arcgis-time-animation

arcgis-time-animation

github.com/saschabrunnerchデータ・データベース2358 回インストール29 週間前に更新
リポジトリ

arcgis-time-animation について

arcgis-time-animationは、ArcGISで時間対応マップを開発する人向けのスキルです。ArcGIS API for JavaScriptを使った時間範囲、レイヤーのフィルター、TimeSlider操作、再生、アニメーションの方法を解説します。

主な機能

  1. 01時間範囲と間隔の設定
  2. 02TimeSliderのモードと再生操作
  3. 03時間対応レイヤーとクエリのフィルター
  4. 04時間変化を監視して表示を更新
  5. 05時系列データのアニメーション

活用シーン

  1. 01ArcGISマップに時間スライダーを追加
  2. 02日付範囲でマップレイヤーを絞り込み
  3. 03時系列データの変化をアニメーション表示
  4. 04指定期間のレイヤー地物をクエリ

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/saschabrunnerch/arcgis-maps-sdk-js-ai-context --skill arcgis-time-animation

インストール後、Claude Code で/arcgis-time-animationを入力して読み込まれたか確認します。

詳細

ArcGIS Time Animation

時間データ、時間対応レイヤー、時間フィルタリング、アニメーションコントロールを使用する場合に、このスキルを使用します。

インポートパターン

ESM(npm)
import TimeExtent from "@arcgis/core/TimeExtent.js";
import TimeInterval from "@arcgis/core/TimeInterval.js";
import TimeSlider from "@arcgis/core/widgets/TimeSlider.js";
CDN(動的インポート)
const TimeExtent = await $arcgis.import("@arcgis/core/TimeExtent.js");
const TimeInterval = await $arcgis.import("@arcgis/core/TimeInterval.js");
const TimeSlider = await $arcgis.import("@arcgis/core/widgets/TimeSlider.js");

TimeExtent

開始日と終了日で構成される時間範囲を表します。

const timeExtent = new TimeExtent({
  start: new Date("2024-01-01"),
  end: new Date("2024-12-31"),
});

// Apply to view (filters all time-aware layers)
view.timeExtent = timeExtent;

// Instant in time (start === end)
const instant = new TimeExtent({
  start: new Date("2024-06-15"),
  end: new Date("2024-06-15"),
});

// No time filter (show all data)
view.timeExtent = null;

TimeInterval

時間の長さを表します。

const interval = new TimeInterval({
  value: 1,
  unit: "months",
});

サポートされる単位: milliseconds、seconds、minutes、hours、days、weeks、months、years、decades、centuries

TimeSlider コンポーネント

arcgis-time-slider(マップコンポーネント)
<arcgis-map item-id="YOUR_WEBMAP_ID">
  <arcgis-time-slider slot="bottom-left" mode="time-window" loop time-visible>
  </arcgis-time-slider>
</arcgis-map>

<script type="module">
  const map = document.querySelector("arcgis-map");
  const timeSlider = document.querySelector("arcgis-time-slider");

  await map.viewOnReady();

  // Configure from layer
  const layer = map.view.map.layers.find((l) => l.timeInfo);
  if (layer) {
    await layer.load();
    timeSlider.fullTimeExtent = layer.timeInfo.fullTimeExtent;
    timeSlider.stops = { interval: layer.timeInfo.interval };
  }
</script>
TimeSlider ウィジェット(コア API)
const timeSlider = new TimeSlider({
  container: "timeSliderDiv",
  view: view,
  fullTimeExtent: {
    start: new Date("2020-01-01"),
    end: new Date("2024-12-31"),
  },
  timeExtent: {
    start: new Date("2024-01-01"),
    end: new Date("2024-03-31"),
  },
  mode: "time-window",
  playRate: 1000,
  loop: true,
  stops: {
    interval: {
      value: 1,
      unit: "months",
    },
  },
});
TimeSlider のプロパティ
プロパティ型デフォルト説明
fullTimeExtentTimeExtent—ウィジェットで表示できる完全な時間範囲
timeExtentTimeExtent—現在選択されている時間範囲
modestring"instant"アニメーションモード
stopsobject—スライダーのスナップ位置
playRatenumber1000ステップ間のミリ秒数
loopbooleanfalse最後に達したときに最初から再生する
layoutstring"auto""auto"、"compact"、"wide"
disabledbooleanfalse操作を無効にする
TimeSlider のモード
// Instant - single point in time
mode: "instant";

// Time Window - range with start and end
mode: "time-window";

// Cumulative from Start - everything from start to current
mode: "cumulative-from-start";

// Cumulative from End - everything from current to end
mode: "cumulative-from-end";
カスタムストップ
// Interval-based stops
stops: {
  interval: { value: 1, unit: "weeks" }
}

// Specific dates
stops: {
  dates: [
    new Date("2024-01-01"),
    new Date("2024-04-01"),
    new Date("2024-07-01"),
    new Date("2024-10-01")
  ]
}

// Number of evenly distributed stops
stops: {
  count: 12
}
再生コントロール
timeSlider.play();
timeSlider.stop();
時間の変更を監視する
timeSlider.watch("timeExtent", (timeExtent) => {
  console.log("New time range:", timeExtent.start, "to", timeExtent.end);
});

timeSlider.watch("viewModel.state", (state) => {
  console.log("State:", state); // "ready", "playing", "disabled"
});
カスタムラベル
const timeSlider = new TimeSlider({
  container: "timeSliderDiv",
  view: view,
  fullTimeExtent: { start, end },

  tickConfigs: [
    {
      mode: "position",
      values: [
        new Date("2021-01-01"),
        new Date("2022-01-01"),
        new Date("2023-01-01"),
      ],
      labelsVisible: true,
      labelFormatFunction: (value) => value.getFullYear().toString(),
    },
  ],

  labelFormatFunction: (value, type, element, layout) => {
    const date = new Date(value);
    if (type === "min" || type === "max") {
      return date.toLocaleDateString();
    }
    return date.toLocaleDateString("en-US", {
      month: "short",
      year: "numeric",
    });
  },
});

時間対応レイヤー

時間情報を持つ FeatureLayer
const featureLayer = new FeatureLayer({
  url: "https://services.arcgis.com/.../FeatureServer/0",
  timeInfo: {
    startField: "event_date",
    endField: "end_date",
    interval: {
      value: 1,
      unit: "days",
    },
  },
});

// Check if layer supports time
await featureLayer.load();
if (featureLayer.timeInfo) {
  console.log("Time field:", featureLayer.timeInfo.startField);
  console.log("Full extent:", featureLayer.timeInfo.fullTimeExtent);
}
TimeInfo のプロパティ
プロパティ型説明
startFieldstring開始日フィールド名(必須)
endFieldstring終了日フィールド名(任意)
fullTimeExtentTimeExtentデータの完全な時間範囲
intervalTimeInterval推奨されるアニメーション間隔
trackIdFieldstringトラック識別フィールド(StreamLayer 用)
その他の時間対応レイヤー
// ImageryLayer
const imageryLayer = new ImageryLayer({
  url: "...",
  timeInfo: { startField: "acquisition_date" },
});

// MapImageLayer
const mapImageLayer = new MapImageLayer({
  url: "...",
  timeInfo: { startField: "date_field" },
});

// StreamLayer
const streamLayer = new StreamLayer({
  url: "wss://services.arcgis.com/.../StreamServer",
  timeInfo: {
    trackIdField: "vehicle_id",
    startField: "timestamp",
  },
  purgeOptions: {
    displayCount: 1000,
    age: 5,
  },
});

レイヤーからの TimeSlider の初期化

async function setupTimeSlider(view, layer) {
  await layer.load();

  if (!layer.timeInfo) {
    console.warn("Layer is not time-aware");
    return null;
  }

  const timeSlider = new TimeSlider({
    container: "timeSliderDiv",
    view: view,
    fullTimeExtent: layer.timeInfo.fullTimeExtent,
    mode: "time-window",
    playRate: 1000,
    loop: true,
    stops: {
      interval: layer.timeInfo.interval || { value: 1, unit: "months" },
    },
  });

  timeSlider.watch("timeExtent", (extent) => {
    document.getElementById("currentTime").textContent =
      `${extent.start.toLocaleDateString()} - ${extent.end.toLocaleDateString()}`;
  });

  return timeSlider;
}

時間によるフィルタリング

クライアント側のフィルター
// Filter all time-aware layers via view
view.timeExtent = new TimeExtent({
  start: new Date("2024-01-01"),
  end: new Date("2024-06-30"),
});

// Filter specific layer via layerView
const layerView = await view.whenLayerView(featureLayer);
layerView.filter = {
  timeExtent: new TimeExtent({
    start: new Date("2024-03-01"),
    end: new Date("2024-03-31"),
  }),
};
時間を指定したクエリ
const query = featureLayer.createQuery();
query.timeExtent = new TimeExtent({
  start: new Date("2024-01-01"),
  end: new Date("2024-12-31"),
});
query.where = "status = 'active'";
query.returnGeometry = true;

const results = await featureLayer.queryFeatures(query);

アニメーションパターン

統計情報を使用する TimeSlider
timeSlider.watch("timeExtent", async (timeExtent) => {
  const query = featureLayer.createQuery();
  query.timeExtent = timeExtent;
  query.outStatistics = [
    {
      statisticType: "count",
      onStatisticField: "OBJECTID",
      outStatisticFieldName: "count",
    },
    {
      statisticType: "sum",
      onStatisticField: "value",
      outStatisticFieldName: "total",
    },
  ];

  const result = await featureLayer.queryFeatures(query);
  const stats = result.features[0].attributes;
  document.getElementById("count").textContent = stats.count;
  document.getElementById("total").textContent = stats.total;
});
時間に基づくハイライト表示
let highlightHandle;

timeSlider.watch("timeExtent", async (timeExtent) => {
  if (highlightHandle) highlightHandle.remove();

  const query = featureLayer.createQuery();
  query.timeExtent = timeExtent;

  const layerView = await view.whenLayerView(featureLayer);
  const results = await featureLayer.queryFeatures(query);
  highlightHandle = layerView.highlight(results.features);
});
手動アニメーションループ
async function animateOverTime(layer, startDate, endDate, intervalDays) {
  const current = new Date(startDate);

  while (current <= endDate) {
    const nextDate = new Date(current);
    nextDate.setDate(nextDate.getDate() + intervalDays);

    view.timeExtent = new TimeExtent({
      start: current,
      end: nextDate,
    });

    await new Promise((resolve) => setTimeout(resolve, 500));
    current.setDate(current.getDate() + intervalDays);
  }
}

TimeZoneLabel コンポーネント

<arcgis-map>
  <arcgis-time-zone-label slot="bottom-left"></arcgis-time-zone-label>
</arcgis-map>

時間に基づくグラフィックスの表示設定

// Set time visibility on individual graphics
graphic.visibilityTimeExtent = new TimeExtent({
  start: new Date("2024-01-01"),
  end: new Date("2024-06-30"),
});

よくある問題

  1. タイムゾーンの問題:日付は JavaScript のローカルタイムゾーンの影響を受けます。一貫性を保つには UTC の日付を使用してください。

    const date = new Date("2024-06-15T00:00:00Z");
    
  2. レイヤーの読み込みが必要:timeInfo は await layer.load() の後にのみ使用できます。

  3. TimeExtent が適用されない:すべての時間対応レイヤーをフィルタリングするには、ビューの timeExtent を設定する必要があります。

  4. Null でフィルターを解除:すべてのデータを表示する(時間フィルターなし)には、view.timeExtent = null を使用します。

  5. パフォーマンス:時間範囲が広いと多数のフィーチャが返される場合があります。可能な場合はサーバー側クエリを使用してください。

  6. Stops の設定が必要:TimeSlider では、スライダーの位置を定義するために stops を設定する必要があります。

参考サンプル

  • timeslider — TimeSlider ウィジェットの基本
  • timeslider-filter — TimeSlider によるデータのフィルタリング
  • timeslider-component-filter — フィルタリング機能を備えた TimeSlider コンポーネント
  • time-layer — 時間対応レイヤーの操作
  • widgets-timeslider — TimeSlider ウィジェットの例
  • widgets-timeslider-offset — タイムゾーンオフセットを指定した TimeSlider
  • layers-scenelayer-time — 時間対応の SceneLayer
  • layers-voxel-time — 時間対応の VoxelLayer
  • layers-graphics-visibilitytimeextent — 時間に基づくグラフィックスの表示設定

関連スキル

  • arcgis-imagery — 時間を含む多次元画像
  • arcgis-layers — レイヤーの設定
  • arcgis-widgets-ui — ウィジェットの配置とスロット

コメント