You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为ngx-graph添加水平滚动条?解决宽数据集适配问题

为ngx-graph添加水平滚动条并兼容缩放功能

我正在使用ngx-graph可视化一个跨多年的大型数据集,数据集宽度过大无法在单页完整显示,因此希望为ngx-graph添加水平滚动条,以便用户查看全部数据。

我曾尝试为父容器设置固定宽度,但该方案与缩放功能冲突。请问有人能协助我解决这个问题吗?


现有HTML代码

<div class="space-top-16 vc-form-container">
    <ngx-graph
        class="mss-graph-container"
        [layout]="dagreLayout"
        [curve]="curve"
        [links]="links"
        [nodes]="nodes"
        [autoZoom]="true"
        [autoCenter]="true">
        <ng-template #nodeTemplate let-node>
            <svg
                height="80"
                [attr.width]="node.data.children && node.data.children.length > 0 ? '112' : '72'"
                [attr.max-width]="112">
                <foreignObject
                    height="80"
                    [attr.width]="node.data.children && node.data.children.length > 0 ? '112' : '72'"
                    [attr.max-width]="112">
                    <div class="vc-mss-device-node-wrapper">
                        <div class="vc-mss-device-node" (click)="$event.preventDefault(); showWidget(node)">
                            <span
                                class="vc-mss-device-icon material-icons"
                                [style.border-color]="'#dadbdc'"
                                [style.color]="node.data.icon.color"
                                >{{ node.data.icon.label }}</span
                            >
                            <div
                                xmlns="http://www.w3.org/1999/xhtml"
                                class="vc-mss-device-node-text body-s-1"
                                [matTooltip]="node.label"
                                [matTooltipPosition]="'above'">
                                {{ node.label }} - {{ node.data.type }}
                            </div>
                        </div>

                        @if (node.data.children && node.data.children.length > 0) {
                        <div class="vc-mss-device-node">
                            <button
                                mat-icon-button
                                class="vc-mss-device-expand-icon"
                                (click)="$event.preventDefault();
                                node.data.type !== 'INTERNET' ? (selectedNode = node) : (selectedNode = null)">
                                <mat-icon>{{ node.data.expanded ? 'expand_more' : 'expand_less' }}</mat-icon>
                            </button>
                            <span>({{ node.data.children.length }})</span>
                        </div>
                        }
                    </div>
                </foreignObject>
            </svg>
        </ng-template>
        <ng-template #linkTemplate let-link>
            <svg:g class="edge" xmlns:svg="http://www.w3.org/2000/svg">
                <path class="edge line mss-device-overview-line" [attr.d]="link.line"></path>
            </svg:g>
        </ng-template>
    </ngx-graph>
</div>

现有SCSS代码

:host {
    display: block;
    height: 100%;
    width: 100%;

    .vc-mss-device-node-wrapper {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 8px;

        .vc-mss-device-node {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 8px;

            .vc-mss-device-icon {
                display: flex;
                justify-content: center;
                align-items: center;
                height: 36px;
                width: 36px;
                border: 1px solid;
                border-radius: 50%;
            }

            .vc-mss-device-node-text {
                width: 56px;
                text-align: center;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }
        }

        .vc-mss-device-node {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 4px;
            cursor: pointer;

            button.vc-mss-device-expand-icon {
                height: 24px !important;
                width: 24px !important;
                box-shadow: none !important;

                .mat-icon {
                    height: 24px;
                    width: 24px;
                    line-height: 24px;
                    font-size: 24px;
                }

                &.mat-mdc-icon-button:not([disabled]) {
                    &:hover,
                    &:focus-visible {
                        border-radius: 4px !important;
                        background-color: var(--primary-50);
                    }

                    &:focus-visible {
                        outline: 1px solid var(--primary-600);
                        outline-offset: 1px;
                    }
                }
            }
        }
    }

    .mss-graph-container {
        display: block;
        height: calc(100vh - 345px);
        width: 100%;
    }

    .mss-device-overview-line {
        stroke: var(--outline);
        stroke-width: 1;
    }

    .vc-mss-device-legend {
        display: flex;
        flex-direction: column;
        gap: 8px;
        position: absolute;
        top: 32px;
        left: 16px;
        width: 150px;
        background-color: var(--ghost-white);

        .vc-mss-device-legend-item {
            display: inline-flex;
            align-items: center;
            gap: 8px;
        }
    }
}

解决方案

要实现水平滚动同时兼容ngx-graph的缩放功能,关键是让滚动容器只限制可视区域,而让ngx-graph的SVG自由扩展宽度,同时保留缩放交互逻辑,按以下步骤修改:

1. 修改HTML结构,新增滚动容器

给ngx-graph外层添加一个专用的滚动容器:

<div class="space-top-16 vc-form-container">
  <!-- 新增滚动容器 -->
  <div class="graph-scroll-container">
    <ngx-graph
        class="mss-graph-container"
        [layout]="dagreLayout"
        [curve]="curve"
        [links]="links"
        [nodes]="nodes"
        [autoZoom]="true"
        [autoCenter]="true">
      <!-- 原有模板内容保持不变 -->
    </ngx-graph>
  </div>
</div>

2. 更新SCSS样式

调整容器样式,让滚动容器负责横向滚动,同时允许ngx-graph自适应内容宽度:

:host {
    display: block;
    height: 100%;
    width: 100%;

    /* 新增滚动容器样式 */
    .graph-scroll-container {
        width: 100%;
        height: calc(100vh - 345px);
        overflow-x: auto;
        overflow-y: hidden;
        position: relative;
    }

    .mss-graph-container {
        display: block;
        height: 100%;
        /* 移除固定宽度限制,让SVG随内容扩展 */
        width: auto;
        /* 确保数据集宽度不足时占满容器 */
        min-width: 100%;
    }

    /* 原有其他样式保持不变 */
    .vc-mss-device-node-wrapper {
        /* ... 原有代码 ... */
    }

    .mss-device-overview-line {
        /* ... 原有代码 ... */
    }

    .vc-mss-device-legend {
        /* ... 原有代码 ... */
    }
}

3. 优化初始视图(可选)

如果autoZoom导致初始缩放异常,可在组件初始化后手动适配视图:

import { Component, ViewChild, OnInit } from '@angular/core';
import { NgxGraphComponent } from '@swimlane/ngx-graph';

@Component({
  // 你的组件元数据
})
export class YourGraphComponent implements OnInit {
  @ViewChild(NgxGraphComponent) graphComponent!: NgxGraphComponent;

  ngOnInit() {
    setTimeout(() => {
      this.graphComponent.fitView();
    }, 300);
  }
}

原理说明

  • 滚动容器通过overflow-x: auto提供横向滚动能力,同时固定高度确保纵向布局稳定。
  • ngx-graph容器移除固定宽度,允许内部SVG根据数据集实际宽度自由扩展,避免内容被截断。
  • min-width: 100%保证当数据集宽度小于容器时,图表仍占满可视区域,不会出现留白。

修改后即可通过水平滚动查看完整数据集,同时保留ngx-graph的缩放、拖拽等交互功能。


内容的提问来源于stack exchange,提问作者Harvi Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 10:07:31