VueはGraphVisを使用して無限に拡張された関係グラフを開発します

VueはGraphVisを使用して無限に拡張された関係グラフを開発します

1. GraphVis 公式サイトにアクセスして、対応する js をダウンロードします。js の新しいバージョンと古いバージョンは異なります。古いバージョンを導入するか、新しいバージョンを導入するかは、ニーズによって異なります (GraphVis 公式サイト: http://www.graphvis.cn/)

  • visgraph.min.js (基本設定js)
  • visgraph-layout.min.js (レイアウト js を構成する)

2. 必要なvueファイルにjsファイルを導入する

import VisGraph from '@/assets/js/GraphVis/old/visgraph.min.js' // 対応する js ファイルの場所import LayoutFactory from '@/assets/js/GraphVis/old/visgraph-layout.min.js' // 対応する js ファイルの場所export default { components: { VisGraph, LayoutFactory } }

3. キャンバスと設定を読み込む

構成(必要に応じて構成を変更します):

設定: {
  // ノード構成ノード: {
            label: { // ラベル設定 show: true, // 表示するかどうか color: '250,250,250', // フォント色 font: 'normal 14px Microsoft YaHei', // フォントサイズと種類 textPosition: 'Middle_Center', // フォント位置 wrapText: true // ノード折り返しテキスト(このプロパティは、フォント位置がMiddle_Centerでtrueの場合にのみ有効です)
            },
            shape: 'circle', // ノードの形状 円、長方形、正方形、楕円、三角形、星、多角形、テキスト
            // 幅: 60、// ノード幅 (形状が rect の場合にのみ有効)
            // 高さ: 60, // ノードの高さ (形状が rect の場合にのみ有効)
            color: '62,160,250', // ノード colorborderColor: '62,160,250', // ノードの境界線 colorborderWidth: 0, // ノードの境界線の幅borderRadius: 0, // ノードの角丸lineDash: [0], // ノードの境界線の線の種類[0] は実線を示します[5,8] は点線を示しますborderWidth > 0Validalpha: 1, // ノードの透明度size: 60, // ノードのサイズselected: { // ノードが選択されています styleborderColor: '136,198,255', // 選択時の境界線の色borderAlpha: 1, // 選択時の境界線の透明度borderWidth: 3, // 選択時の境界線の幅showShadow: true, // 影を表示するかどうかshadowColor: '136,198,255' // 選択時の影の色}
          },
          // ライン構成リンク: {
            label: { // ラベル設定 show: true, // 表示するかどうか color: '100,100,200', // ラベルの色 font: 'normal 10px Arial' // ラベルのテキストのサイズとタイプ},
            lineType: 'direct', // 線の種類 direct、curver、vlink、hlink、bezier、vbezier、hbezier
            colorType: 'defined', // 線の色のタイプsource: ソースの色を継承、target: ターゲットの色を継承both: 双方向の色を使用、defined: カスタム color: '200,200,200', // 線の色alpha: 1, // 線の透明度lineWidth: 1, // 線の幅lineDash: [0], // 破線の間隔スタイル (例: [5,8])
            showArrow: true, // 矢印を表示 selected: { // 選択時のスタイル設定 color: '20,250,50', // 選択時の色 alpha: 1, // 選択時の透明度 lineWidth: 4, // 選択された線の幅 showShadow: true, // 影を表示 shadowColor: '50,250,50' // 影の色 }
          },
          highLightNeiber: true, // 隣接ノードの高さマーク wheelZoom: 0.8 // ホイールズームスイッチ、使用していない場合は [0,1] に設定しないでください  
}

キャンバスをロードします:

this.visgraph = 新しいVisGraph(
        document.getElementById(this.canvasId)、
        この.canvasConfig
      )
this.visgraph.clearAll()
this.visgraph.drawData(this.graphData)

4. 拡張機能:

サブノードの無制限の拡張、トリガーするにはノードをダブルクリックします (ondblClick):

this.visgraph.restoreHightLight() // ハイライトをキャンセル const allNodes = this.visgraph.getVisibleData()
this.currentNode.push(ノードID)
allNodes.nodes.forEach(item => {
    if (this.currentNode.indexOf(item.id) === (-1)) {
         this.visgraph.deleteNode(アイテム)
    }
})
const findNodeNum = Math.round(Math.random() * 50)
const increamData = this.buildIncreamData(ノード、findNodeNum)
this.visgraph.activeAddNodeLinks(increamData.nodes、increamData.links) は、
this.visgraph.translateToCenter()

完全なコード (relation.vue):

<!--
 * @著者: CarlYang
 * @日付: 2021-07-23 15:31:51
 * @最終編集時間: 2021-07-30 09:46:05
 * @LastEditors: LastEditorsを設定してください
 * @説明: リレーションシップグラフ* @ファイルパス: \vue-g6\src\views\GraphVis\company.vue
-->
<テンプレート>
  <div id="コンテナ">
    <!-- ================================================== キャンバス ビュー================================================ -->
    <div
      id="グラフパネル"
      ref="グラフパネル"
      @contextmenu="グローバルクリックディスパッチ"
    </div>

    <!-- ==================================================== 左ツールバー================================================== -->
    <div class="left-toolbar">
      <ul>
        <li @click="setZoomOut" title="ズームアウト">
          <i class="iconfont icon-zoomin"></i>
        </li>
        <li @click="setZoomIn" title="ズームアウト">
          <i class="iconfont icon-zoomout"></i>
        </li>
        <li @click="saveImage" title="画像を保存">
          <i class="iconfont icon-baocun-"></i>
        </li>
        <li @click="exportJson" title="JSON をエクスポート">
          <i class="iconfont icon-json"></i>
        </li>
        <li @click="showOverView" title="サムネイル">
          <i class="iconfont icon-suolvetu" style="font-size: 14px"></i>
        </li>
        <li @click="clockwiseRotate" title="時計回りに回転">
          <i class="iconfont icon-shunshizhenfangxiangclockwise4" style="font-size: 14px"></i>
        </li>
        <li @click="反時計回りに回転" title="反時計回りに回転">
          <i class="iconfont icon-nishizhencounterclockwise3" style="font-size: 14px"></i>
        </li>
        <li @click="setMouseModel('normal')" title="通常モード">
          <i class="iconfont icon-pointer-up"></i>
        </li>
        <li @click="setMouseModel('drag')" title="ドラッグモード">
          <i class="iconfont icon-line-dragmovetuozhuai-01"></i>
        </li>
        <li @click="setMouseModel('select')" title="選択モード">
          <i class="iconfont icon-kuangxuan1"></i>
        </li>
        <li @click="fullScreen" title="全画面表示">
          <i class="iconfont icon-quanping" style="font-size: 20px"></i>
        </li>
      </ul>
    </div>

    <!-- ===================================================== 右クリックメニュー================================================= -->
    <div id="nodeMenuDialog" class="nodeMenuDialog">
      <ul>
        <li @click="clickNodeInfo">ノード情報</li>
        <li @click="settingNode">ノードを構成する</li>
        <li @click="selectRelation">関係を選択</li>
        <li @click="deleteNode">ノードを削除</li>
        <li @click="contractNode">ノードを折りたたむ</li>
        <li @click="expandedNode">展開されたノード</li>
      </ul>
    </div>

    <!-- ======================================================= ノード情報ポップアップボックス================================================== -->
    <el-引き出し
      title="ノード情報"
      :visible.sync="ノード情報ドロワー"
      方向="rtl"
      :modal="false"
      サイズ= "20%"
    >
      <div class="nodeInfo">
        <el-form class="nodeInfoForm" ref="nodeInfoForm" :model="nodeInfoForm" label-width="80px">
          <el-form-item label="ノード名">
            <el-input v-model="nodeInfoForm.label"></el-input>
          </el-form-item>
          <el-form-item label="ノードID">
            <el-input v-model="nodeInfoForm.id"></el-input>
          </el-form-item>
        </el-form>
        <el-tabs v-model="nodeInfoActiveName" :stretch="true" class="nodeInfoTabs">
          <el-tab-pane label="関係" name="first">
            <div class="nodeInfoRelation">
              <el-collapse v-model="nodeInfoRelationActive">
                <el-collapse-item title="ターゲットノード" name="1">
                  <テンプレートスロット="タイトル">
                    <el-badge :value="nodeInfoSourceList.length">ターゲットノード</el-badge>
                  </テンプレート>
                  <表
                    境界線="0"
                    セル間隔="0"
                    セルパディング="0"
                    クラス="nodeInfo-table"
                    v-if="nodeInfoSourceList.length > 0"
                  >
                    <頭>
                      <tr>
                        <th>エンティティ オブジェクト</th>
                        <th>関係タイプ</th>
                      </tr>
                    </thead>
                    <t本文>
                      <tr v-for="(item, index) in nodeInfoSourceList" :key="index">
                        <td
                          :style="{ color: アイテムの色 }"
                          スタイル="カーソル: ポインタ;"
                          @click="moveCenterThisNode(item.id)"
                        >{{ アイテム.ラベル }}</td>
                        <td>{{ item.relationType }}</td>
                      </tr>
                    </tbody>
                  </テーブル>
                  <p v-else>データがありません</p>
                </el-collapse-item>
                <el-collapse-item title="ソースノード" name="2">
                  <テンプレートスロット="タイトル">
                    <el-badge :value="nodeInfoTargetList.length">ソースノード</el-badge>
                  </テンプレート>
                  <表
                    境界線="0"
                    セル間隔="0"
                    セルパディング="0"
                    クラス="nodeInfo-table"
                    v-if="nodeInfoTargetList.length > 0"
                  >
                    <頭>
                      <tr>
                        <th>エンティティ オブジェクト</th>
                        <th>関係タイプ</th>
                      </tr>
                    </thead>
                    <t本文>
                      <tr v-for="(item, index) in nodeInfoTargetList" :key="index">
                        <td
                          :style="{ color: アイテムの色 }"
                          スタイル="カーソル: ポインタ;"
                          @click="moveCenterThisNode(item.id)"
                        >{{ アイテム.ラベル }}</td>
                        <td>{{ item.relationType }}</td>
                      </tr>
                    </tbody>
                  </テーブル>
                  <p v-else>データがありません</p>
                </el-collapse-item>
              </el-collapse>
            </div>
          </el-tab-pane>
          <el-tab-pane label="属性" name="2番目">
            <div class="nodeInfoAttribute">
              <el-table :data="nodeInfoAttributeList" ボーダースタイル="幅: 100%">
                <el-table-column prop="name" label="プロパティ名"></el-table-column>
                <el-table-column prop="値" label="プロパティ値"></el-table-column>
              </el-table>
            </div>
          </el-tab-pane>
        </el-tabs>
      </div>
    </el-drawer>

    <!-- ====================================================== ノード構成=============================================== -->
    <el-引き出し
      title="ノード構成"
      :visible.sync="nodeConfigDrawer"
      方向="rtl"
      :modal="false"
      サイズ= "20%"
    >
      <div class="nodeConfig">
        <el-form ref="form" :model="nodeConfigForm" label-width="80px" label-position="left">
          <el-form-item label="名前">
            <el-input v-model="nodeConfigForm.label" placeholder="ノード名を入力してください"></el-input>
          </el-form-item>
          <el-form-item label="タイプ">
            <el-select v-model="nodeConfigForm.shape" placeholder="ノードタイプを選択してください">
              <el-オプション
                v-for="(item, index) in nodeTypeList"
                :key="'ノード' + インデックス"
                :label="アイテム.ラベル"
                :value="アイテムの値"
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item ラベル="色">
            <div class="form-color">
              <el-入力
                v-model="nodeConfigForm.fillColor"
                クラス="フォーム入力"
                placeholder="色を選択してください"
                読み取り専用
              </el-input> ...
              <el-カラーピッカー
                v-model="nodeConfigForm.hexColor"
                クラス="フォームカラー選択"
                @change="colorChange(nodeConfigForm.hexColor, 'fillColor')"
              </el-カラーピッカー>
            </div>
          </el-form-item>
          <el-form-item label="サイズ">
            <el-input v-model="nodeConfigForm.size" placeholder="ノードのサイズを入力してください" type="number"></el-input>
          </el-form-item>
          <el-form-item label="境界線の幅">
            <el-input v-model="nodeConfigForm.borderWidth" placeholder="境界線の幅を入力してください" type="number"></el-input>
          </el-form-item>
          <el-form-item label="破線境界線">
            <el-select v-model="nodeConfigForm.borderDash" placeholder="破線の境界線を選択してください">
              <el-option label="いいえ" :value="false"></el-option>
              <el-option ラベル="はい" :値="true"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="境界線の色">
            <div class="form-color">
              <el-入力
                v-model="nodeConfigForm.borderColor"
                クラス="フォーム入力"
                placeholder="境界線の色を選択してください"
                読み取り専用
              </el-input> ...
              <el-カラーピッカー
                v-model="nodeConfigForm.borderHexColor"
                クラス="フォームカラー選択"
                @change="colorChange(nodeConfigForm.borderHexColor, 'borderColor')"
              </el-カラーピッカー>
            </div>
          </el-form-item>
          <el-form-item label="フォント位置">
            <el-select v-model="nodeConfigForm.textPosition" placeholder="フォントの位置を選択してください">
              <el-オプション
                v-for="(item, index) in textPositionList"
                :key="インデックス"
                :label="アイテム.ラベル"
                :value="アイテムの値"
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="フォントスタイル">
            <el-input v-model="nodeConfigForm.font" placeholder="フォントスタイルを入力してください"></el-input>
          </el-form-item>
          <el-form-item label="フォント色">
            <div class="form-color">
              <el-入力
                v-model="nodeConfigForm.fontColor"
                クラス="フォーム入力"
                placeholder="フォントの色を選択してください"
                読み取り専用
              </el-input> ...
              <el-カラーピッカー
                v-model="nodeConfigForm.fontHexColor"
                クラス="フォームカラー選択"
                @change="colorChange(nodeConfigForm.fontHexColor, 'fontColor')"
              </el-カラーピッカー>
            </div>
          </el-form-item>
          <el-form-item label="フォントの背景">
            <div class="form-color">
              <el-入力
                v-model="nodeConfigForm.fontBgColor"
                クラス="フォーム入力"
                placeholder="フォントの背景を選択してください"
                読み取り専用
              </el-input> ...
              <el-カラーピッカー
                v-model="nodeConfigForm.fontBgHexColor"
                クラス="フォームカラー選択"
                @change="colorChange(nodeConfigForm.fontBgHexColor, 'fontBgColor')"
              </el-カラーピッカー>
            </div>
          </el-form-item>
          <el-form-item label="フォントオフセット">
            <el-入力
              v-model="nodeConfigForm.textOffset"
              placeholder="フォントオフセットを入力してください"
              タイプ="数値"
              最大 = "100"
              最小値= "-100"
            </el-input> ...
          </el-form-item>
        </el-form>
        <div class="save-setting">
          <el-button type="primary" @click="saveSetting">設定を保存</el-button>
        </div>
      </div>
    </el-drawer>
  </div>
</テンプレート>
<スクリプト>
'@/assets/js/GraphVis/old/visgraph.min.js' から VisGraph をインポートします。
'@/assets/js/GraphVis/old/visgraph-layout.min.js' から LayoutFactory をインポートします。
'screenfull' から screenfull をインポートします
輸入 {
  会社
} '@/assets/js/company.js' から
エクスポートデフォルト{
  名前: 'デザイングラフ',
  コンポーネント:
    VisGraph、
    レイアウトファクトリー
  },
  データ() {
    戻る {
      //キャンバスインスタンス visgraph: null,
      // 中心ノード centerNode: null,
      //選択されたノード currentNode: [],
      // 選択されたノード情報checkedNodeInfo: {},
      // グラフ構成 config: {
        ノード: {
          ラベル: {
            表示: true、
            色: '250,250,250',
            フォント: 'normal 14px Microsoft YaHei'、
            テキスト位置: 'Middle_Center'、
            境界線の幅: 0,
            wrapText: true
          },
          形状: '円'、
          幅: 60,
          高さ: 60,
          色: '62,160,250',
          境界線の色: '62,160,250',
          境界線の幅: 0,
          境界半径: 0,
          ラインダッシュ: [0],
          アルファ: 1,
          選択: {
            境界線の色: '136,198,255',
            ボーダーアルファ: 1,
            境界線の幅: 3,
            表示シャドウ: true、
            影色: '136,198,255'
          },
          onClick: (イベント、ノード) => {
            // this.visgraph.highLightNeiberNodes(node, 1) // ハイライト},
          ondblClick: (イベント、ノード) => {
            this.visgraph.restoreHightLight() // ハイライトをキャンセル const allNodes = this.visgraph.getVisibleData()
            this.currentNode.push(ノードID)
            allNodes.nodes.forEach(item => {
              if (this.currentNode.indexOf(item.id) === (-1)) {
                this.visgraph.deleteNode(アイテム)
              }
            })
            const findNodeNum = Math.round(Math.random() * 50)
            const increamData = this.buildIncreamData(ノード、findNodeNum)
            this.visgraph.activeAddNodeLinks(increamData.nodes、increamData.links) は、
            this.visgraph.translateToCenter()
          },
          onMouseOver: (イベント、ノード) => { },
          onMouseOut: (イベント、ノード) => { }
        },
        リンク:
          ラベル: {
            表示: true、
            色: '100,100,200',
            フォント: '通常 10px Arial'
          },
          ラインタイプ: 'direct'、
          colorType: '定義済み'、
          色: '200,200,200',
          アルファ: 1,
          線幅: 1,
          ラインダッシュ: [0],
          表示矢印: true、
          選択: {
            色: '20,250,50',
            アルファ: 1,
            線幅: 4,
            表示シャドウ: true、
            影の色: '50,250,50'
          }
        },
        highLightNeiber: true、
        ホイールズーム: 0.8、
        要素クリックなし: (イベント、_graphvis) => {
          // キャンバス上の他の場所をクリックするとポップアップが非表示になります this.nodeMenuDialogClose()
        }
      },
      // ノード情報ポップアップボックス nodeInfoDrawer: false,
      // ノード情報フォーム nodeInfoForm: {
        ラベル: ''、
        id: ''
      },
      // ノード情報ポップアップボックスタブオプション名 nodeInfoActiveName: 'first',
      // リレーションシップ nodeInfoRelationActive: ['1', '2'],
      // ターゲットノードリスト nodeInfoTargetList: [],
      // ソースノードリスト nodeInfoSourceList: [],
      // ノード属性リスト nodeInfoAttributeList: [],
      // ノード設定ポップアップボックス nodeConfigDrawer: false,
      // ノード構成フォーム nodeConfigForm: {
        ラベル: ''、
        形: ''、
        塗りつぶし色: ''、
        16進数カラー: ''、
        サイズ: ''、
        境界線の幅: ''、
        ボーダーダッシュ: ''、
        境界線の色: ''、
        境界線の16進数カラー: ''、
        テキスト位置: '',
        フォント: ''、
        フォントカラー: ''、
        フォントHexColor: ''、
        フォント背景色: ''、
        フォントBgHexColor: ''、
        テキストオフセット: ''
      },
      // ノードタイプリスト nodeTypeList: [
        { 値: '円'、ラベル: '円' },
        { 値: 'rect', ラベル: 'Rectangle' },
        { 値: '楕円'、ラベル: '楕円' },
        { 値: '星'、ラベル: '五角形' },
        { 値: '三角形'、ラベル: '三角形' },
        { 値: '多角形'、ラベル: '六角形' }
      ]、
      // フォント位置リスト textPositionList: [
        { 値: 'Middle_Center'、ラベル: 'Center' },
        { 値: 'Bottom_Center'、ラベル: 'Bottom' },
        { 値: 'top_Center'、ラベル: 'Top' },
        { 値: 'Middle_Left'、ラベル: 'Left' },
        { 値: 'Middle_right'、ラベル: '右' },
      ]
    }
  },
  マウント() {
    this.handleData(会社)
    ウィンドウのサイズ変更 = () => {
      if (this.visgraph) {
        this.visgraph.moveCenter()
      }
    }
  },
  メソッド: {
    /**
     * 処理データ * @日付 2021-07-23
     * @param {オブジェクト} データ
     */
    ハンドルデータ(データ) {
      定数オブジェクト = {
        ノード: [],
        リンク: []
      }
      定数ノード = data.nodes
      ノード.forEach(アイテム => {
        if (item.label === '本社') {
          定数ノードオブジェクト = {
            id: アイテム.id、
            ラベル: アイテム.ラベル、
            プロパティ: アイテム、
            色: '38,186,191',
            選択された境界線の色: '131,218,228',
            影色: '131,218,228'
          }
          ノードオブジェクトサイズ = 80
          ノードオブジェクトx = 250
          ノードオブジェクトy = 250
          this.centerNode = ノードObj
          this.currentNode.push(アイテムID)
        } それ以外 {
          定数ノードオブジェクト = {
            id: アイテム.id、
            ラベル: アイテム.ラベル、
            プロパティ: アイテム、
            サイズ: 60
          }
          スイッチ (アイテム.タイプ) {
            ケース1:
              ノードオブジェクト.color = '242,105,97'
              nodeObj.selectedBorderColor = '249,179,157'
              ノードオブジェクト.shadowColor = '249,179,157'
              壊す
          }
          obj.nodes.push(nodeObj)
        }
      })
      const リンク = data.edges
      links.forEach(item => {
        定数linkObj = {
          id: アイテム.id、
          ターゲット: item.to,
          出典: item.from,
          ラベル: アイテム.ラベル、
          プロパティ: アイテム
          // ストロークカラー: this.getRandomColor()
        }
        スイッチ (アイテム.タイプ) {
          ケース11:
            リンクオブジェクト.color = '40,194,199'
            linkObj.selectedColor = '40,194,199'
            linkObj.shadowColor = '40,194,199'
            壊す
          ケース12:
            linkObj.color = '250,108,100'
            linkObj.selectedColor = '250,108,100'
            linkObj.shadowColor = '250,108,100'
            壊す
          ケース13:
            リンクオブジェクト.color = '0,132,255'
            linkObj.selectedColor = '0,132,255'
            linkObj.shadowColor = '0,132,255'
            壊す
          ケース15:
            linkObj.color = '250,108,100'
            linkObj.selectedColor = '250,108,100'
            linkObj.shadowColor = '250,108,100'
            壊す
        }
        obj.links.push(linkObj)
      })
      この.buildData(obj)
    },
    /**
     * 例を作成する * @date 2021-07-23
     * @param {オブジェクト} gxData
     */
    ビルドデータ(gxData) {
      this.visgraph = 新しい VisGraph(document.getElementById('graph-panel'), this.config)
      定数ノード数 = gxData.nodes.length
      const xyArr = this.getXY(this.centerNode、ノード数、ノード数 * 20)
      gxData.nodes.forEach((n, i) => {
        nx = xyArr[i].x
        ny = xyArr[i].y
        サイズ = 60
      })
      gxData.nodes.push(このセンターノード)
      gxData を描画します。
      this.visgraph.setZoom()
    },
    /**
     * 選択したノードの周囲のポイント座標 * @date 2021-07-23
     * @param {中心ノード} centerNode
     * @param {ノード数} nodeCount
     * @param {中心点からの距離} 半​​径
     * @returns {配列}
     */
    getXY(centerNode, nodeCount, radius) {
      定数 aop = 360.0 / ノード数
      定数arr = []
      (i = 0 とします; i < nodeCount; i++) {
        r1 = 半径とする
        ノード数 > 10 の場合
          r1 = (i % 2 === 0 ? 半径 + 35 : 半径 - 35)
        }
        定数ao = i * aop
        定数o1 = {}
        o1.x = centerNode.x + r1 * Math.cos(ao * Math.PI / 180)
        o1.y = centerNode.y + r1 * Math.sin(ao * Math.PI / 180)
        arr[i] = o1
      }
      リターン
    },
    /**
     * ランダムにノードを生成 * @date 2021-07-23
     * @param {現在選択されているノード} centerNode
     * @param {ノード数} nodeNum
     * @returns {オブジェクト}
     */
    ビルドIncreamData(centerNode、nodeNum) {
      定数gxData = {
        ノード: [],
        リンク: []
      }
      定数カウント = ノード数
      定数 nodeIdPrefix = 'node_' + Math.round(Math.random() * 1000) + '_'
      (i = 0 とします; i < count; i++) {
        gxData.nodes.push({
          id: ノードIDプレフィックス + i、
          ラベル: '子ノード+' + i,
          サイズ: 60
          // 色: this.getRandomColor()
        })
        gxData.links.push({
          出典: centerNode.id、
          ターゲット: nodeIdPrefix + i、
          ラベル: '関係' + i
        })
      }
      gxDataを返す
    },
    /**
     * キャンバス右クリックイベント * @date 2021-07-26
     * @param {Object} イベント
     */
    グローバルクリックディスパッチ(イベント) {
      イベントボタンが 2 の場合
        if (this.visgraph.currentNode) {
          this.nodeMenuDialogOpen(イベント、this.visgraph.currentNode)
        }
      }
    },
    /**
     * ノードを右クリックするとメニューが表示されます * @date 2021-07-26
     * @param {Object} イベント
     * @param {Object} ノード
     */
    nodeMenuDialogOpen(イベント、ノード) {
      nodeMenuDialog を document.getElementById("nodeMenuDialog"); に設定します。
      nodeMenuDialog.style.left = event.clientX + "px";
      nodeMenuDialog.style.top = (event.clientY - 76) + "px";
      nodeMenuDialog.style.display = "ブロック";
      this.checkedNodeInfo = ノード;
      イベントの伝播を停止します。
    },
    /**
     * ノードメニューを閉じる * @date 2021-07-26
     */
    ノードメニューダイアログを閉じる() {
      nodeMenuDialog を document.getElementById("nodeMenuDialog"); に設定します。
      nodeMenuDialog.style.display = "なし";
    },
    /**
     * ノード情報をクリック * @date 2021-07-26
     */
    クリックノード情報() {
      this.nodeInfoDrawer = true
      // 割り当てフォーム this.nodeInfoForm = this.checkedNodeInfo
      // 関連ノード // 送信ノード const k = this.checkedNodeInfo
      const g = (k.outLinks || []).map((link) => {
        戻る {
          id: link.target.id,
          ラベル: link.target.label,
          タイプ: link.target.type、
          色: 'rgb(' + link.target.fillColor + ')',
          リレーションタイプ: link.type || link.label || '--'
        }
      })
      // 入力ノード const h = (k.inLinks || []).map((link) => {
        戻る {
          id: リンク.ソース.id、
          ラベル: link.source.label,
          タイプ: リンク.ソース.タイプ、
          色: 'rgb(' + link.source.fillColor + ')',
          リレーションタイプ: link.type || link.label || '--'
        }
      })
      this.nodeInfoTargetList = h
      this.nodeInfoSourceList = g
      // 属性の割り当て const list = []
      const nameList = ['id', 'label', 'type', 'cluster', 'fillColor', 'shape', 'size', 'font', 'fontColor', 'x', 'y']
      nameList.forEach(item => {
        定数オブジェクト = {
          名前: アイテム、
          値: this.checkedNodeInfo[item]
        }
        リストをプッシュする
      })
      this.nodeInfoAttributeList = リスト
      this.nodeMenuDialogClose()
    },
    /**
     * 関連する操作を選択 * @date 2021-07-26
     */
    選択関係() {
      this.visgraph.rightMenuOprate('selRelate')
    },
    /**
     * 指定されたノードを削除します* @date 2021-07-26
     * @returns {any}
     */
    ノードを削除します。
      this.visgraph.deleteNode(this.visgraph.currentNode)
      this.nodeMenuDialogClose()
    },
    /**
     * 指定されたノードを折りたたむ * @date 2021-07-26
     * @returns {any}
     */
    コントラクトノード() {
      (this.visgraph.currentNode.outLinks.length > 0)の場合{
        this.visgraph.contract(this.visgraph.currentNode)
        this.nodeMenuDialogClose()
      } それ以外 {
        this.$message.warning('現在のノードには子ノードがないため、折りたたむことはできません')
      }
    },
    /**
     * 指定されたノードを展開します * @date 2021-07-26
     * @returns {any}
     */
    展開されたノード() {
      (this.visgraph.currentNode.outLinks.length > 0)の場合{
        this.visgraph.expanded(this.visgraph.currentNode)
        this.nodeMenuDialogClose()
      } それ以外 {
        this.$message.warning('現在のノードには子ノードがないため、展開できません')
      }
    },
    /**
     * 指定されたノードを移動する* @date 2021-07-26
     * @param {文字列} ID
     */
    このノードを中央に移動します(id) {
      定数ノード = this.visgraph.findNodeById(id)
      this.visgraph.moveNodeToCenter(ノード)
    },
    /**
     * ノード構成 * @日付 2021-07-30
     * @returns {any}
     */
    設定ノード(){
      this.nodeMenuDialogClose()
      定数{
        id、
        ラベル、
        形、
        塗りつぶし色、
        サイズ、
        境界線の幅、
        ラインダッシュ、
        境界線の色、
        テキスト位置、
        フォント、
        フォントカラー、
        ラベル背景、
        テキストオフセットX
      } = this.visgraph.currentNode
      this.nodeConfigForm.id = id
      this.nodeConfigForm.label = ラベル
      this.nodeConfigForm.shape = シェイプ
      this.nodeConfigForm.fillColor = 'rgb(' + fillColor + ')'
      this.nodeConfigForm.hexColor = this.rgbToHex('rgb(' + fillColor + ')')
      this.nodeConfigForm.size = サイズ
      this.nodeConfigForm.borderWidth = 境界幅
      this.nodeConfigForm.borderDash = lineDash.length === 2
      this.nodeConfigForm.borderColor = 'rgb(' + borderColor + ')'
      this.nodeConfigForm.borderHexColor = this.rgbToHex('rgb(' + borderColor + ')')
      this.nodeConfigForm.textPosition = テキスト位置
      this.nodeConfigForm.font = フォント
      this.nodeConfigForm.fontColor = 'rgb(' + fontColor + ')'
      this.nodeConfigForm.fontHexColor = this.rgbToHex('rgb(' + fontColor + ')')
      this.nodeConfigForm.fontBgColor = labelBackGround ? 'rgb(' + labelBackGround + ')' : ''
      this.nodeConfigForm.fontBgHexColor = labelBackGround ? this.rgbToHex('rgb(' + labelBackGround + ')') : ''
      this.nodeConfigForm.textOffset = テキストオフセットX
      this.nodeConfigDrawer = true
    },
    /**
     * ノード構成を保存 * @date 2021-07-30
     * @returns {any}
     */
    保存設定(){
      定数{
        id、
        ラベル、
        形、
        塗りつぶし色、
        16進数カラー、
        サイズ、
        境界線の幅、
        ボーダーダッシュ、
        境界線の色、
        境界16進数カラー、
        テキスト位置、
        フォント、
        フォントカラー、
        フォントHexColor、
        フォント背景色、
        フォントBgHexColor、
        テキストオフセット
      } = this.nodeConfigForm
      定数 b = this.visgraph.findNodeByAttr('id', id)
      (b) の場合 {
        b.label = ラベル
        b.size = サイズ
        b.shape = 形状
        b.fillColor = this.getColorRgb(fillColor)
        b.textPosition = テキスト位置
        b.fontColor = this.getColorRgb(fontColor)
        b.labelBackGround = this.getColorRgb(fontBgColor)
        b.font = フォント;
        b.textOffsetY = 数値(textOffset) || 2
        b.borderWidth = 数値(borderWidth) || 2
        b.borderColor = this.getColorRgb(borderColor)
        b.lineDash = (borderDash ? [8, 5] : [0])
        this.visgraph.refresh()
        this.$メッセージ({
          メッセージ: '設定が正常に変更されました!',
          タイプ: '成功'、
          期間: 2000
        })
        this.nodeConfigDrawer = false
      } それ以外 {
        this.$メッセージ({
          メッセージ: '選択したノードが見つかりません!',
          タイプ: 'エラー'、
          期間: 2000
        })
      }
    },
    /**
     * ランダムな色を取得 * @date 2021-07-20
     * @returns {String} スタイル */
    ランダムカラーを取得する() {
      定数 r = Math.floor(Math.random() * 256)
      定数 g = Math.floor(Math.random() * 256)
      定数 b = Math.floor(Math.random() * 256)
      'rgb(' + r + ',' + g + ',' + b + ')' を返します
    },
    /**
     * 色選択ボックスの変更割り当て * @date 2021-07-26
     * @param {文字列} 値
     * @param {String} ケイ
     */
    色の変更(値、キー) {
      this.nodeConfigForm[キー] = this.hexToRgba(値)
    },
    /**
     * 16進数のカラー値をRGBに変換する
     * @日付 2021-07-26
     * @param {文字列} 16進数
     * @returns {文字列}
     */
    hexToRgba(16進数) {
      "rgb(" + parseInt("0x" + hex.slice(1, 3)) + "," + parseInt("0x" + hex.slice(3, 5)) + "," + parseInt("0x" + hex.slice(5, 7)) + ")" を返します
    },
    /**
     * RGBカラー値を16進数に変換 * @date 2021-07-26
     * @param {文字列} 色
     * @returns {文字列}
     */
    rgbToHex(色) {
      定数 rgb = color.split(',');
      rgb[0]を分割します。('(')[1]);
      定数 g = parseInt(rgb[1]);
      定数 b = parseInt(rgb[2].split(')')[0]);
      const hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
      16進数を返します。
    },
    /**
     * RGBを削除
     * @日付 2021-07-30
     * @param {文字列} a
     * @returns {文字列}
     */
    getColorRgb(a) {
      (a && a.length > 0) の場合 {
        a = a.replace('rgb(', '').replace(')', '')
      } それ以外 {
        a = ヌル
      }
      返す
    },
    /**
     * 画像を保存 * @日付 2021-07-23
     */
    画像を保存(){
      this.visgraph.saveImage()
    },
    /**
     * jsonをエクスポート
     * @日付 2021-07-30
     */
    エクスポートJSON() {
      この.visgraph.exportJsonFile()
    },
    /**
     * サムネイルを開く * @日付 2021-07-23
     */
    オーバービューを表示する() {
      console.log(this.showOverViewFlag)
      this.showOverViewFlag = !this.showOverViewFlag
      this.visgraph.showOverView(this.showOverView)
    },
    /**
     * ズームアウト * @date 2021-07-23
     */
    setZoomIn() {
      this.visgraph.setZoom('zoomIn')
    },
    /**
     * 拡大 * @日付 2021-07-23
     */
    setZoomOut() {
      this.visgraph.setZoom('zoomOut')
    },
    /**
     * 時計回り回転 * @date 2021-07-23
     */
    時計回りに回転する(){
      this.visgraph.rotateGraph(-10)
    },
    /**
     *反時計回り* @日付 2021-07-23
     */
    反時計回りに回転する(){
      this.visgraph.rotateGraph(10)
    },
    /**
     * マウスモードを設定 * @date 2021-07-23
     * @param {String} type drag: ドラッグモード select: ボックス選択モード normal: 通常モード */
    setMouseModel(タイプ) {
      this.visgraph.setMouseModel(タイプ)
    },
    /**
     * 全画面表示 * @日付 2021-07-23
     */
    全画面表示() {
      screenfull.request(this.$refs.graphpanel)
    }
  }
}
</スクリプト>

<style lang="scss" スコープ>
#容器 {
  幅: 100%;
  位置: 相対的;
  #グラフパネル{
    幅:100%;
    高さ:100%;
    背景:#9dadc1;
    位置: 絶対;
    zインデックス: 1;
  }
  /* メニューバーをテストする */
  .左ツールバー{
    位置: 絶対;
    上: 0;
    左: 0;
    zインデックス: 1000;
    幅: 45px;
    高さ: 100%;
    背景色: #fafafa;
    右境界線: 1px 実線 #e5e2e2;
    ul {
      li {
        テキスト配置: 中央;
        高さ: 35px;
        色: #066fba;
        行の高さ: 35px;
        カーソル: ポインタ;
        パディング: 0;
        私 {
          フォントサイズ: 18px;
        }
        &:ホバー{
          背景色: #6ea36d;
          色: #fff;
        }
      }
    }
  }

  /* 右クリックポップアップスタイル*/
  .nodeメニューダイアログ{
    表示: なし;
    位置: 絶対;
    最小幅: 100px;
    パディング: 2px 3px;
    マージン: 0;
    境界線: 1px 実線 #e3e6eb;
    背景: #f9f9f9;
    色: #333;
    zインデックス: 100;
    境界線の半径: 5px;
    ボックスの影: 1px 1px 4px rgba(0, 0, 0, 0.2);
    変換: translate(0, 15px) スケール(0.95);
    遷移: transform 0.1s イーズアウト、不透明度 0.1s イーズアウト;
    オーバーフロー: 非表示;
    カーソル: ポインタ;
    li {
      表示: ブロック;
      位置: 相対的;
      マージン: 0;
      パディング: 0 10px;
      境界線の半径: 5px;
      空白: ラップなし;
      行の高さ: 30px;
      テキスト配置: 中央;
      &:ホバー{
        背景色: #c3e5fd;
      }
    }
  }

  /* ノード情報ポップアップボックス*/
  .nodeInfo {
    .nodeInfoForm {
      パディング: 20px 20px 0 20px;
      境界線: 実線 1px #dcdfe6;
      左境界線: なし;
      右境界線: なし;
      マージン: 20px 0;
    }
    .nodeInfo関係{
      パディング: 0 20px;
      .nodeInfoテーブル{
        幅: 100%;
        overflow-y: スクロール;
        番目 {
          幅: 50%;
          境界線: 1px 実線 #ebeef5;
          パディング: 9px 0 9px 9px;
          テキスト配置: 左;
          &:最初の子 {
            右境界線: なし;
          }
        }
        td {
          幅: 50%;
          境界線: 1px 実線 #ebeef5;
          上境界線: なし;
          パディング: 9px 0 9px 9px;
          &:最初の子 {
            右境界線: なし;
          }
        }
      }
      /deep/ .el-badge__content.is-fixed {
        上: 24px;
        右: -7px;
      }
      p {
        テキスト配置: 中央;
        パディング: 20px 0;
      }
    }

    .nodeInfo属性{
      パディング: 0 20px;
    }
  }

  /* ノード構成ポップアップウィンドウ*/
  .nodeConfig{
    パディング: 20px 20px 0 20px;
    境界線: 実線 1px #dcdfe6;
    左境界線: なし;
    右境界線: なし;
    マージン: 20px 0;
    .form-color {
      ディスプレイ: フレックス;
      コンテンツの両端揃え: スペースの間;
      .フォーム入力{
        幅: calc(100% - 50px);
      }
    }
    .保存設定{
      幅: 100%;
      下マージン: 20px;
      .el-ボタン{
        幅: 100%;
      }
    }
  }
}
</スタイル>

注意: 2 つの JS ファイルが導入されると、ESLint はエラーを報告します。このファイルは無視できます。ESLint を使用しない場合は無視できます。同時に、プロジェクトはelement-uiに基づいて開発され、screenfullフルスクリーンプラグインとAliアイコンライブラリアイコンが導入されており、必要に応じて導入できます。

デモ:

これで、Vue で GraphVis を使用して無限に拡張可能な関係グラフを作成する方法についての記事は終了です。Vue GraphVis 関係グラフの関連コンテンツの詳細については、123WORDPRESS.COM で以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vueを使用して写真をアップロードする3つの方法
  • Vue に Echarts チャートを追加するための基本的なチュートリアル
  • Vue に基づいて画像 src を動的に読み込むソリューション
  • Vueは画像をクリックして拡大する効果を実現します
  • Vueプロジェクトで背景画像を設定する方法
  • vue+elementUIは画像アップロード機能を実現します
  • Vueを使用して画像カルーセルコンポーネントを作成するアイデアの詳細な説明
  • vue.js をベースに画像カルーセル効果を実現する
  • Vueでカスタムアイコンを使用する方法

<<:  Linuxシステムでノードプロセスを実行しているが、プロセスを強制終了できない問題を解決します

>>:  CentOS 7.4 に MySQL 5.7 を手動でインストールする方法

推薦する

ReactとReduxの配列処理の説明

この記事では、reduce()、filter()、map()、every()、some()、spre...

Vue の自動書式設定の改行保存の詳細な説明

ネットで変更方法をいろいろ調べたのですが、うまくいきませんでした。後で大物から見て削除しました。フォ...

シンプルなビデオ連射機能を実装する JavaScript CSS3

この記事では、最も単純なビデオ連射機能をシミュレートするデモを作成します。アイデア:再生する動画と同...

MySQLの大規模テーブル最適化ソリューションについての簡単な説明

背景Alibaba Cloud RDS for MySQL(MySQL バージョン 5.7)データベ...

Win10 システムに MySQL8.0.13 をインストールする際の問題と解決策

オペレーティングシステム: Windows10 MySQL バージョン: 8.0.13-winx64...

スケーラブルな列の完全な例を実現するための Ant 設計 Vue テーブル

ant-design-vue テーブルのスケーラブルな列の問題に対する完璧なソリューション。固定列と...

MySQL COUNT関数の使用と最適化

目次COUNT 関数は何をするのですか? MyISAMの「魔法」シンプルなCOUNT最適化近似値を使...

MySQL ツリー構造テーブルの設計と最適化に関する簡単な説明

序文多くの管理・オフィスシステムでは、ツリー構造がいたるところで見られます。たとえば、「部門」や「機...

CSS で overflow-y: visible; が機能しない理由の分析と解決

シナリオ最近の要件は、モバイル デバイス用の h5 ページです。これには、選択可能なカードの行が必要...

Javascript のスコープとクロージャの詳細

目次1. 範囲2. スコープチェーン3. 語彙の範囲5. 閉鎖の適用6. クロージャの欠陥7. 閉会...

ルート変更を監視するJavaScriptの詳細な説明

目次歴史pushState() メソッドpushState() の使用シナリオreplaceStat...

速度、読み込み、Web アプリケーションなどにおける div と table の違い。

1: 速度と読み込み方法の違いdivとtableの違いは速度ではなく、読み込み方法です。速度はネット...

空のパスがページのパフォーマンスに与える影響に対する解決策

数日前、Google Reader で Yu Bo さんが共有した投稿「空のパスがページのパフォーマ...

フローティングをクリアするいくつかの方法(推奨)

1. 同じタイプの空の要素を追加し、要素の CSS 属性 clear:both; を設定します。 ...

MySQL テーブルと列のコメントの概要

コードと同様に、テーブルや列にコメントを追加して、他のユーザーがその機能を理解できるようにすることが...