ドラッグ可能で編集可能なガントチャートの詳細な説明(HighchartsはVueとReactで使用できます)

ドラッグ可能で編集可能なガントチャートの詳細な説明(HighchartsはVueとReactで使用できます)

序文

Excel は強力で、広く使用されています。 Web アプリケーションの登場と改善に伴い、ユーザーの要件はますます高まっています。多くの Excel 関数が Sass に移行されました。彼らのために Excel を作成できればと思います。 。 。プログラマーになるのはとても難しいです。 。 。

昨年、ガントチャートの必要性に気づき、それについて多くの作業を行い、ブログも 2 つ書きました。 1つはGSTCパッケージを使用して作成したガントチャートで、もう1つは自分で作成したシンプルなガントチャートです。どちらの効果も理想的ではなく、特にGSTCには多くの問題があります。多くの道教の友人がブログを読んだ後に問題に遭遇しました。この問題の解決をお手伝いできないことを恥ずかしく思います。以前は忙しすぎて、このガントチャートに再び取り組むことはありませんでしたが、今日、私たちのニーズをほぼ完全に満たす新しいパッケージを見つけました。

まず、私たちは Highcharts を使用しています。次に、大規模なチームの製品であるため、事後メンテナンスが保証されており、ドキュメントも完全です。

Vue3で書いたのですがhighchartsでは区別されません。jsパッケージなのでvue reactでもネイティブマルチページでも動作します。

次に、最も基本的なニーズ、実装する必要がある機能、エフェクト図の GIF、最後にソースコードを見てみましょう。Git に置きました。役に立ったと思ったら、スターを付けてください。

必要

1. 横軸の左側はテーブルデータで、基本的な情報を表示できます。
2. 時間軸は水平軸の右側にあり、異なる精度で時間表示を切り替えることができます。
3. 水平方向のデータ ブロックが複数ある場合は、重ね合わせるのが最適です。
4. データブロックをドラッグしたりクリックしたりして、タスクの時間やその他の情報を変更できます。

レンダリング

このハイチャートは、左側の表と右側のアイコンを実装するだけでなく、データのリンクも実現しています。右側の横軸は時間軸で、フォーマットをカスタマイズできます。データを競合なく重ね合わせることができます。データにはクリックなどのさまざまなイベントがあり、単一のデータブロックを選択して編集できます。データをドラッグできます。たとえば、上下にドラッグして列を変更したり、水平にドラッグしたり、一方的にドラッグしたりできます。イベントにはコールバック関数があります。これらの機能は基本的に私たちのニーズを満たすことができます。たとえば、期間、時間の長さ、データ情報の変更と表示などです。

ソースコードアドレス、コード分析

まずコードの Git アドレスを貼り付け、GitHub ソース コードをクリックしてソース コードをダウンロードします。ソースコードを直接ダウンロードしてプロジェクトを実行することをお勧めします。また、このプロジェクトはvue3用ですが、この種のパッケージの場合、記述方法は、主にパラメータ以外はそれほど変わりません。

コードを投稿して、機能の実装について説明します。もちろん、コメントも非常に詳細です。

まず、highcharts-gantt.js はガントチャートを実装するために特別に使用されるファイルであり、draggable-points.js はポイントイベントバインディングを実装するファイルです。 Vue は変数を直接導入するとエラーを報告したため、 draggable-points の 2 つのモジュールを highcharts-gantt に直接追加し、混乱なく再圧縮しました。そのため、最終的なパッケージは 160K+ のみとなり、はるかに小さくなり、直接使用できます。圧縮されたソースコードは安心して使用できます。2 つのファイルの機能を結合しただけですが、公式のソースファイルではないことに注意してください。興味のある学生は公式のソースコードにアクセスできます。.src ファイルは圧縮されておらず、難読化されており、コメントは非常に詳細です。これは、ファイルをマージしたときのバージョン Highcharts Gantt JS v9.3.1 (2021-11-05) であり、現在の安定バージョンでもあります。

機能はちょっと単純で、コードについてはあまり言うことはないようです。要点を注釈しました。それでも分からない場合は、メッセージやコメントを残してください。

最後に、まだ問題があります。ソースコードを注意深く研究していません。この例にはまだ問題があります。ドラッグイベントが中断されず、チャートのデータ表示が直接変更されます。たとえば、線を垂直にドラッグすると、左側の表のデータが変更されます。まだ満足のいく解決策は見つかっていません。現在は、ドラッグ終了時にコールバックドロップ関数でデータを処理し、必要なデータを書き戻してチャートを更新しています。同様に、ドラッグや時間の競合などのさまざまなチェックを行って、前述の要件を満たすこともできます。しかし、まだ 1 つの欠陥があります。それは、ドラッグ プロセス中にデータが変更することです。ドラッグ プロセス中に左側のテーブルのデータが変更されないようにしたいのですが、まだ解決されていません。良い事例、良いアプリケーション、良い提案があれば、ぜひ提出していただき、一緒に前進していただければ幸いです。

<div class="hightChart-gantt">
    <div id="コンテナ"></div>
    <button @click="getData">現在のデータを印刷</button>
  </div>
</テンプレート>

<スクリプト>
'vue' から {defineComponent、onMounted、ref} をインポートします。
'@jsModule/highcharts/highcharts-gantt.src.js' から Highcharts として * をインポートします。
'dayjs' から dayjs をインポートします
'./constants' から{ WEEKS } をインポートします

// API ドキュメント: https://api.Highcharts.com.cn/gantt/index.html
// コミュニティアドレス: https://forum.jianshukeji.com/tags/c/Highcharts/35/Highcharts-gantt
// 公式例: https://www.highcharts.com.cn/demo/gantt/interactive-gantt

//解決すべき問題// 1. ドラッグ中断: ユーザー操作を検証する必要がありますが、現在のところ、ユーザー操作を中断する方法がわかりません。
// 解決策: 現在のアプローチは、ドロップで判断を行い、ビジネス ロジックに基づいてプロンプトを作成し、データを再レンダリングすることです。実行可能ですが、十分にフレンドリーではありません。


エクスポートデフォルトdefineComponent({
  名前: 'hightCharts-gantt',
  コンポーネント: {},
  設定 () {
    const gantt = ref({});
    // 公式の推奨は UTC 時間を使用することです。ビジネス上のニーズにより、データベース時間との一貫性を保つ必要があります。これはデータベースの保存形式によって異なります。const data = [
      {開始: '2021-6-1 0'、終了: '2021-6-1 18'、工場: 'Huawei'、材料: 'P50'、uid: 1、y: 0、完了: 0.35}、 
      {開始: '2021-6-2 8'、終了: '2021-6-2 16'、工場: 'Huawei'、材質: 'P50'、uid: 2、y: 0}、 
      {開始: '2021-6-3 8'、終了: '2021-6-4 24'、工場: 'Huawei'、材質: 'P50'、uid: 3、y: 0}、 
      {開始: '2021-6-4 12'、終了: '2021-6-5 15'、工場: 'Huawei'、材質: 'P50'、uid: 4、y: 0}、 

      {開始: '2021-6-1 8'、終了: '2021-6-1 12'、工場: 'Xiaomi'、素材: 'Redmi 3'、uid: 5、y: 1}、 
      {開始: '2021-6-3 3'、終了: '2021-6-3 9'、工場: 'Xiaomi'、素材: 'Redmi 3'、uid: 6、y: 1}、 

      {開始: '2021-6-1 6'、終了: '2021-6-1 16'、工場: 'Apple'、素材: 'iPhone13'、uid: 7、y: 2}、 
      {開始: '2021-6-2 3'、終了: '2021-6-2 19'、工場: 'Apple'、素材: 'iPhone13'、uid: 8、y: 2}、 
      {開始: '2021-6-3 8'、終了: '2021-6-3 17'、工場: 'Apple'、素材: 'iPhone13'、uid: 9、y: 2}、 

      {開始: '2021-6-1 12'、終了: '2021-6-1 24'、工場: 'OPPO'、素材: 'Reno7'、uid: 10、y: 3}、
      {開始: '2021-6-2 5'、終了: '2021-6-2 18'、工場: 'OPPO'、素材: 'Reno7'、uid: 11、y: 3}、
      {開始: '2021-6-3 1'、終了: '2021-6-5 12'、工場: 'OPPO'、素材: 'Reno7'、uid: 12、y: 3}、
    ];
    newData = data.map(item => { とする
      アイテムの開始 = dayjs(アイテムの開始).valueOf();
      アイテムの終了 = dayjs(アイテムの終了).valueOf();
      返品商品
    });
    
    // グローバル設定。アイコンを初期化する前に設定する必要があります。Highcharts.setOptions({
      グローバル:
        useUTC: false // UTC 時間を使用しない}, // すべてデフォルトで英語ですが、一部中国語に翻訳されています lang: {
        noData: 「まだデー​​タがありません」
        平日: ['月曜日'、'火曜日'、'水曜日'、'木曜日'、'金曜日'、'土曜日'、'日曜日']、
        月: ['1月'、'1月'、'3月'、'4月'、'5月'、'6月'、'7月'、'8月'、'9月'、'10月'、'11月'、'12月']
      },
    });
    const ドラッグ開始 = (e) => {
    }
    定数ドラッグ = (e) => {
    }
    定数ドロップ = (e) => {
      const { newPoint = {}、ターゲット = {} } = e;
      newPoint.y が 0 の場合
        list = [] とし、 tar = newData.find(item => item.y === newPoint.y && item.uid !== target.uid);
        リスト = newData.map(item => {
          // 現在のドラッグデータ if(item.uid === target.uid) {
            戻る {
              ...アイテム、
              ファクトリー: tar.factory、
              材質: タール、 
              ...新しいポイント
            }
          } それ以外 {
            返品商品
          }
        })
        gantt.value.update({
          シリーズ: [{
            データ: リスト
          }]
        })
      }
    }
    // 選択すると、ビジネスデータを編集するためのウィンドウがポップアップ表示されます。const handleSelect = (e) => {
      console.log('選択済み')
    }
    // 最終データを取得する const getData = () => {
      データを gantt.value.series[0].data.map(item => { とします。
        戻る {
          uid: アイテム.uid、
          工場: アイテム.工場、
          素材: アイテム.素材、
          開始: アイテム.開始、
          終了: 項目.終了
        }
      })
      コンソール.log(データ)
    }


    マウント時(() => {
      試す {
        gantt.value = Highcharts.ganttChart('コンテナ', {
          タイトル:
            テキスト: 'hightCharts ガントチャートの例'
          },
          x軸: [{
            現在の日付インジケーター: true、
            ティックピクセル間隔: 70,
            グリッド: {
              borderWidth: 1, // 右ヘッダーの境界線の幅 cellHeight: 35, // 右日付ヘッダーの高さ },
            ラベル: {
              配置: '中央'、
              フォーマッタ: 関数() {
                `${dayjs(this.value).format('M月D')} ${WEEKS[dayjs(this.value).day()]}` を返します。
              }
            },
          }, {
            ラベル: {
              配置: '中央'、
              フォーマッタ: 関数() {
                `${dayjs(this.value).format('YYYY年M月')}` を返します。
              }
            },
          }],
          y軸: {
            タイプ: 'カテゴリ',
            グリッド: {
              有効: true、
              境界線の色: 'rgba(0,0,0,0.3)',
              境界線の幅: 1,
              列: [
                { タイトル: { テキスト: '工場' }, ラベル: { フォーマット: '{point.factory}' } }, 
                { タイトル: { テキスト: 'モデル' }, ラベル: { フォーマット: '{point.material}' } }, 
              ]
            }
          },
          ツールチップ: {
            フォーマッタ: 関数 () {
              `<div> を返します
               ファクトリー: ${this.point.factory}
              開始時刻: ${dayjs(this.point.start).format('YYYY-MM-DD HH:mm:ss')}}
              終了時間: ${dayjs(this.point.end).format('YYYY-MM-DD HH:mm:ss')'',
              </div>`
            }
          },
          シリーズ: [{ データ: newData }],
          プロットオプション: {
            シリーズ: {
              animation: false, // 依存関係コネクタをアニメーション化しない
              ドラッグドロップ: {
                draggableX: true, // 水平ドラッグ draggableY: true, // 垂直ドラッグ dragMinY: 0, // 垂直ドラッグ下限 dragMaxY: 3, // 垂直ドラッグ上限 dragPrecisionX: 3600000 // 水平ドラッグ精度(ミリ秒単位)},
              データラベル: {
                有効: true、
                フォーマット: '{point.factory}-{point.uid}',
                スタイル: {
                  カーソル: 'デフォルト',
                  ポインタイベント: 'なし'
                }
              },
              allowPointSelect: true、
              ポイント: {
                イベント: {
                  ドラッグ開始: ドラッグ開始、
                  ドラッグ: ドラッグ、
                  ドロップ: ドロップ、
                  選択: ハンドル選択
                }
              }
            }
          },
          エクスポート: {
            ソース幅: 1000
          },
          credits: { // 右下隅の著作権情報を削除します enabled: false
          },
        });
      } キャッチ(エラー){
        コンソール.log(エラー)
      }
    })

    戻る {
      ガント、
      データを取得
    }
  },
})
</スクリプト>

<スタイルスコープ>
.hightChart-gantt {
  オーバーフローx: 自動;
    -webkit-オーバーフロースクロール: タッチ;
}
#容器 {
    最大幅: 1200px;
    最小幅: 800px;
    高さ: 400px;
    マージン: 1em 自動;
}
</スタイル>

ガントチャートをドラッグして編集する方法の詳細説明については、この記事で終わります(highchartsはVueとReactの両方で使用できます)。関連するVueガントチャートガントコンテンツの詳細については、123WORDPRESS.COMの以前の記事を検索するか、次の関連記事を続けて閲覧してください。今後とも123WORDPRESS.COMを応援してください!

以下もご興味があるかもしれません:
  • Vue3 の ref、computed、reactive、toRefs をご存知ですか?
  • setup+ref+reactive は vue3 の応答性を実装します
  • Vue/React シングルページ アプリケーションをリフレッシュなしで復元するソリューション
  • Vue3 のリアクティブ関数 toRef 関数 ref 関数の紹介
  • vue3 の setUp とリアクティブ関数の使用方法の詳細な説明
  • フロントエンドプロジェクトにおける Vue および React のエラー監視

<<:  HTML要素によるFlashブロックの詳細な例

>>:  ウェブインターフェースデザインでウェブサイトのスタイルガイドを作成する方法(画像とテキスト付き)

推薦する

VMware Workstation Pro は Win10 ピュア バージョンのオペレーティング システムをインストールします

この記事では、VMware Workstation Pro で Win10 オペレーティング システ...

HTMLの最適化によりWebページの速度が向上

明らかな HTML、隠された「公開スクリプト」 Web ページのダウンロード時間を短縮する鍵は、フ...

React diffアルゴリズムソースコード分析

目次単一ノード差分単一要素を調整するマルチノード差分調整子配列ノードが移動したかどうかを判断するには...

CSS3はアニメーション効果を実現するためにvar()とcalc()関数を使用する。

ナレッジポイントをプレビューします。アニメーションフレーム背景グラデーションvar() と calc...

jQuery ステップ進行軸プラグインの実装コード

毎日のjQueryプラグイン - ステップ進捗軸 ステップ進捗軸ツール系のサイトでは入門チュートリア...

Linux でユーザーにルート権限を追加する方法の概要

1. ユーザーを追加します。まず、adduser コマンドを使用して共通ユーザーを追加します。コマン...

MySQL SQL文の特殊処理文のまとめ(必読)

1.テーブル全体を更新します。データ行の列の値が空の場合は、別の列フィールドの値と同じにします。 ...

CentOS 7 で MySQL 5.7 をインストールして設定する

この記事では、以下の環境をテストします。 CentOS 7 64 ビット 最小 MySQL 5.7 ...

MySQL 権限制御の詳細分析

目次1. グローバルレベル2. データベースレベル3. 表面レベル4. 列レベルの権限5. サブルー...

Ubuntu で起動時に自動的に起動するシェル スクリプトを作成する (推奨)

スクリプトを書く目的は、さまざまなサービスを手動で起動しなくて済むようにすることです(怠惰のためでも...

MySQL デッドロックのトラブルシューティングの全プロセス記録

【著者】 Liu Bo: Ctrip テクニカル サポート センターのシニア データベース マネージ...

Mysql と Oracle でよく使用される複数テーブルの変更ステートメントの概要

今日、SQLトレーニングの質問バンクでこの質問を見ました。これは、非常に代表的なマルチテーブル変更の...

Youku 動画から 30 秒の広告コードを削除する 2 つの方法

誰もがこんな気持ちになったことがあると思います。30 秒の広告が入った動画を見ると、とても不快に感じ...

HTTPS の有効化に関する経験の共有

国内のネットワーク環境が悪化し続ける中、さまざまな改ざんや乗っ取りが後を絶たず、サイト全体をHTTP...