0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

円グラフや並び替え可能なリストというと、専用のJavaScriptライブラリを導入するイメージがあるかもしれません。しかし、モダンブラウザの標準機能だけで、追加ライブラリなしに実現できる場合があります。本記事では、円グラフを描くCSS conic-gradientと、要素の並び替えに使えるHTML5 Drag and Drop APIの2つを紹介します。

CSS conic-gradient:円グラフを描くグラデーション

conic-gradient()は、通常のグラデーション(linear-gradientが直線状、radial-gradientが中心から放射状)とは異なり、中心点を軸に回転する形で色が変化するグラデーション関数です。この性質を利用すると、色の帯を角度で区切るだけで円グラフのような表現が作れます。

.pie-chart {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: conic-gradient(
    #4CAF50 0deg 120deg,     /* 0%〜33%: 緑 */
    #FFC107 120deg 240deg,   /* 33%〜67%: 黄色 */
    #F44336 240deg 360deg    /* 67%〜100%: 赤 */
  );
}

border-radius: 50%と組み合わせて円形に切り抜くことで、円グラフとして表示されます。色の境界はパーセンテージでも指定できます。

.pie-chart {
  background: conic-gradient(
    #4CAF50 0% 40%,
    #FFC107 40% 75%,
    #F44336 75% 100%
  );
}

用途と注意点

  • 円グラフのほか、市松模様(チェッカーボード)やカラーホイールの表現にも使われる
  • background-colorのような単色を扱うプロパティには使えない(あくまでbackgroundbackground-imageのような画像扱いのプロパティ専用)
  • グラフの値が動的に変わる場合は、JavaScriptからstyle.backgroundのCSS文字列を書き換えることで対応できる(チャート専用ライブラリなしで、シンプルな円グラフ表示だけなら十分実現可能)
  • 繰り返しパターンを作りたい場合はrepeating-conic-gradient()という専用の関数も用意されている

HTML5 Drag and Drop API:ネイティブの並び替えUI

要素をドラッグして並び替える機能も、draggable属性とドラッグ関連イベントの組み合わせだけで、外部ライブラリなしに実装できます。

基本の仕組み

<ul id="list">
  <li draggable="true" data-id="1">項目A</li>
  <li draggable="true" data-id="2">項目B</li>
  <li draggable="true" data-id="3">項目C</li>
</ul>

要素にdraggable="true"を指定するだけで、その要素はドラッグ可能になります(画像・リンク・選択されたテキストはデフォルトでドラッグ可能です)。

let draggedItem = null;

document.querySelectorAll('li').forEach(item => {
  item.addEventListener('dragstart', (e) => {
    draggedItem = item;
    e.dataTransfer.effectAllowed = 'move';
  });

  item.addEventListener('dragover', (e) => {
    e.preventDefault(); // dropを許可するために必須
  });

  item.addEventListener('drop', (e) => {
    e.preventDefault();
    if (draggedItem !== item) {
      // ドラッグ元とドロップ先を入れ替える
      const list = item.parentNode;
      const draggedIndex = [...list.children].indexOf(draggedItem);
      const targetIndex = [...list.children].indexOf(item);
      if (draggedIndex < targetIndex) {
        list.insertBefore(draggedItem, item.nextSibling);
      } else {
        list.insertBefore(draggedItem, item);
      }
    }
  });
});

主なイベントの役割

イベント 発生タイミング
dragstart ドラッグ操作が始まった時(ドラッグ元の要素で発生)
dragover ドラッグ中の要素が、ドロップ先候補の上を通過している間、継続的に発生
drop ドロップ(マウスボタンを離す)が行われた時
dragend ドラッグ操作全体が終了した時(成功・キャンセル問わず)

dragoverイベントでe.preventDefault()を呼ばないと、そもそもdropイベント自体が発火しない点は特に間違えやすいポイントです(ブラウザのデフォルト動作では、多くの要素はドロップ先として扱われないため)。

注意点

  • DataTransferオブジェクトを使うことで、ドラッグ中に任意のデータ(テキスト・URL等)を運ぶこともできる(e.dataTransfer.setData())
  • モバイル(タッチ操作)では、HTML5 Drag and Drop APIは標準では動作しない。タッチ対応が必要な場合は、タッチイベント(touchstart/touchmove/touchend)を別途実装するか、対応済みのライブラリを検討する必要がある
  • 並び替えの永続化(サーバーへの保存)は別途、並び替え後の順序をAPIに送信する実装が必要になる

まとめ

項目 内容
conic-gradient() 中心点を軸に回転する形のグラデーション。円グラフ表現に応用できる
HTML5 Drag and Drop API draggable属性とドラッグ系イベント(dragstart/dragover/drop)の組み合わせでライブラリなしの並び替えUIを実装できる
共通の利点 どちらもモダンブラウザの標準機能のみで完結し、追加ライブラリの導入コストがかからない
主な制約 Drag and Drop APIはモバイルのタッチ操作に非対応(別途実装が必要)

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?