npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uoa-css-lab/duckscatter

v1.3.0

Published

A TypeScript library for plotting scatter charts using WebGPU

Downloads

110

Readme

duckscatter

GitHub license npm version CI Ask DeepWiki

duckscatterは大規模な散布図を描画するための、TypeScriptライブラリです。

従来の散布図描画ライブラリでは、全文検索などの複雑なフィルタリングに時間がかかりました。duckscatterは、DuckDB-WASMによるSQL内での高速なデータ処理と、WebGPUによる大規模並列レンダリングを組み合わせることで、数十万点規模のデータでもスムーズな操作を実現します。

  • WebGPUによるレンダリング: GPUの能力を活用し、ブラウザ上で大規模な散布図を高速に描画します。CanvasやSVGでは扱えきれないような大量のデータポイントであっても、スムーズな操作を実現します。

  • DuckDB-WASMによる高速なデータ分析: DuckDB-WASMを内蔵しており、標準的なSQLを実行できます。SQLを使って動的に描画データをフィルタリングしたり、点の色やサイズを計算したりすることが可能です。

  • ラベル表示: データポイントにテキストラベルを表示できます。クラスタリングの結果を可視化する際に、各クラスタの中心や代表点にラベルを表示したり、特定のデータポイントに注釈を付けたりするのに最適です。

画面イメージ

データについて

Parquetファイル

duckscatterは、Parquet形式のデータファイルを読み込みます。以下のカラムが必要です:

| カラム | 型 | 説明 | |--------|------|------| | x | double | X座標 | | y | double | Y座標 | | IDカラム | 任意 | ポイントを識別するための一意キー(カラム名はidColumnオプションで指定) |

その他のカラムはSQLで参照でき、色やサイズの計算に利用できます。

GeoJSONファイル(ラベル用)

ラベルを表示するには、GeoJSON形式のファイルを指定します:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [x, y]
      },
      "properties": {
        "cluster_label": "ラベルテキスト"
      }
    }
  ]
}

API

const plot = new ScatterPlot({
  canvas: HTMLCanvasElement,  // 描画先のcanvas要素
  dataUrl: string,            // ParquetファイルのURL
  data: {
    idColumn: string,                         // IDカラム名(必須)
    visiblePointLimit?: number,               // 描画最大ポイント数(デフォルト: 100,000)
    sizeSql?: string,                         // サイズ計算SQL式(デフォルト: "3")
    colorSql?: string,                        // 色計算SQL式(ARGB 32bit整数、デフォルト: "0x4D4D4DCC")
    whereConditions?: WhereCondition[],       // フィルタ条件(CPU側)
    gpuFilterColumns?: string[],              // GPUフィルタリング用カラム名(最大4つ)
    gpuWhereConditions?: GpuWhereCondition[], // GPUフィルター条件
  },
  gpu?: {
    backgroundColor?: ColorRGBA,  // 背景色
    pointAlpha?: number,          // グローバル透明度(0.0-1.0、デフォルト: 1.0)
    pointSizeScale?: number,      // グローバルサイズスケール(デフォルト: 1.0)
  },
  labels?: {
    url?: string,                             // GeoJSONファイルのURL
    fontSize?: number,                        // フォントサイズ(デフォルト: 12)
    filterLambda?: LabelFilterLambda,         // ラベル表示フィルタ
    onClick?: (label: Label) => void,         // クリックコールバック
    hoverOutlineOptions?: HoverOutlineOptions, // ホバーアウトライン設定
  },
  interaction?: {
    onPointHover?: PointHoverCallback,   // ポイントホバーコールバック
    onLabelHover?: LabelHoverCallback,   // ラベルホバーコールバック
  },
});

await plot.initialize();

主要メソッド:

  • render(): 描画
  • resize(width, height): キャンバスリサイズ
  • setZoom(zoom) / getZoom() / zoomIn() / zoomOut(): ズーム操作
  • zoomToPoint(newZoom, screenX, screenY): 指定座標を中心にズーム
  • setPan(x, y) / getPan() / pan(dx, dy): パン操作
  • resetView(): ビューリセット
  • update(options): オプション更新
  • runQuery(sql): カスタムSQLクエリ実行
  • getLabels(): ラベル全件取得
  • destroy(): リソース解放

ポイント表示属性制御:

  • setPointAlpha(alpha): グローバル透明度を設定(0.0-1.0)
  • getPointAlpha(): 現在のグローバル透明度を取得
  • setPointSizeScale(scale): グローバルサイズスケールを設定
  • getPointSizeScale(): 現在のグローバルサイズスケールを取得

ホバー制御API:

外部コンポーネントからプログラム的にホバー状態を制御できます。

  • setPointHover(pointId): ポイントをホバー状態に(Promise<boolean>
  • clearPointHover(): ポイントホバー解除
  • getHoveredPoint(): ホバー中のポイント取得
  • setLabelHover(identifier): ラベルをホバー状態に(booleanを返す)
  • clearLabelHover(): ラベルホバー解除
  • getHoveredLabel(): ホバー中のラベル取得
  • clearAllHover(): 全ホバー解除
// 使用例
await plot.setPointHover(12345);           // IDでポイントをホバー
plot.setLabelHover({ text: 'Cluster A' }); // テキストでラベルをホバー
plot.setLabelHover({ cluster: 5 });        // クラスタ番号でラベルをホバー
plot.clearAllHover();                      // 全ホバー解除

GPUフィルタリング

GPUフィルタリングを使用すると、数値カラムの範囲フィルタをGPU側で高速に実行できます。データの再フェッチなしにリアルタイムでフィルタリングが可能です。

const plot = new ScatterPlot({
  // ...
  data: {
    idColumn: 'word',
    // GPUフィルタリング用のカラムを指定(最大4つ)
    gpuFilterColumns: ['frequency', 'length'],
    // フィルター条件を指定
    gpuWhereConditions: [
      { column: 'frequency', min: 100, max: 10000 },
      { column: 'length', min: 3 },
    ],
  },
});

// 実行時にフィルター条件を更新
await plot.update({
  data: {
    gpuWhereConditions: [
      { column: 'frequency', min: 500 },
    ],
  },
});

CPUフィルタ(whereConditions)との違い:

| | CPUフィルタ | GPUフィルタ | |---|---|---| | 対応演算子 | 数値比較、文字列検索、生SQL | 範囲のみ(min/max) | | 更新速度 | SQLクエリ再実行が必要 | 即座に反映 | | 用途 | 複雑な条件、全文検索 | スライダーなどリアルタイム操作 |

型定義

主な型定義:

// GPUフィルター条件
interface GpuWhereCondition {
  column: string;  // gpuFilterColumnsで指定したカラム名
  min?: number;    // 最小値(省略時: -Infinity)
  max?: number;    // 最大値(省略時: +Infinity)
}

// ホバーアウトラインオプション
interface HoverOutlineOptions {
  enabled?: boolean;           // 有効化(デフォルト: true)
  color?: string;              // 線色(デフォルト: 白)
  width?: number;              // 線幅(ピクセル、デフォルト: 2)
  minimumHoverSize?: number;   // 最小ホバーサイズ
  outlinedPointAddition?: number;
}

// WHERE条件フィルター
type WhereCondition = NumericFilter | StringFilter | RawSqlFilter;

interface NumericFilter {
  type: 'numeric';
  column: string;
  operator: '>=' | '>' | '<=' | '<';
  value: number;
}

interface StringFilter {
  type: 'string';
  column: string;
  operator: 'contains' | 'equals' | 'startsWith' | 'endsWith';
  value: string;
}

interface RawSqlFilter {
  type: 'raw';
  sql: string;
}

Examples

実行方法

# ライブラリのビルド(ルートディレクトリで)
npm install
npm run build

# サンプルアプリの実行
cd examples/next
npm install
npm run dev

ブラウザで http://localhost:3000 を開きます。

サンプルデータ

サンプルでは、GloVe 6B単語ベクトルをUMAPで2次元に投影したデータを使用しています(約40万単語)。

  • データセット: https://huggingface.co/datasets/mt0rm0/glove.6B.50d.umap.2d

ラベル生成

ラベルはDBSCANクラスタリングとOpenAI APIを使って生成できます:

cd examples/next
export OPENAI_API_KEY="your-api-key"
python scripts/generate_labels.py

ライセンス

このライブラリは MIT License の下でライセンスされています。