You need to enable JavaScript to run this app. 如何使用ngx-datatable创建带分页的行列分隔式摄像头马赛克墙
优惠活动
大模型
产品
解决方案
定价
更多

如何使用ngx-datatable创建带分页的行列分隔式摄像头马赛克墙

ngx-datatable 摄像头马赛克网格实现方案

核心逻辑

你需要实现的效果本质是打破ngx-datatable“一行对应一个业务对象、一列对应一个数据字段”的默认渲染规则,转为每行固定排列N个摄像头卡片、列与列之间明确分隔、自带分页能力的网格效果,核心实现路径:

  • 先把一维存储的摄像头原始数据,按预设的每行列数做切片分组,生成对齐的网格行数据(不足列数的位置补空占位)
  • 用ngx-datatable的自定义单元格模板,逐列渲染对应位置的摄像头卡片
  • 复用ngx-datatable原生的分页能力,基于分组后的网格行数做分页计算

现有方案的问题定位

  • 方案1缺陷:将每个摄像头单独作为一行数据,导致单元格位置错位,无法实现每行固定列数的马赛克排列。比如你给出的示例中第一个摄像头绑定column1、第二个绑定column2,会渲染为第一行仅第一列有内容、第二行仅第二列有内容,行列完全错乱
  • 方案2缺陷:硬编码合并摄像头到固定行结构,没有通用的分组适配逻辑,无法应对摄像头数量动态变化的场景,且未处理不足列数的空占位,也没有和ngx-datatable的列渲染规则对齐

具体实现代码

1. 组件TS核心逻辑

先定义全局网格配置,完成原始数据到网格行的转换,对接分页参数:

// 固定每行展示的摄像头列数,可根据需求调整为3/4列
readonly GRID_COLUMN_COUNT = 2;
// 每页展示的网格行数,根据摄像头单页承载量调整
readonly PAGE_SIZE = 2;
// 完整的网格行缓存(避免分页时重复计算)
private fullGridRows = [];
// 传给datatable的当前页行数据
gridRows = [];
// 分页参数
totalRows = 0;
currentPageOffset = 0;

// 你的原始摄像头数据
rawCameraList = [
  { name: "Pet shop", id: "1", video: 'https://xxx' },
  { name: "E-shop", id: "2", video: 'https://xxx' },
  { name: "My house", id: "3", url: 'https://xxx' },
  { name: "Garage", id: "4", url: 'https://xxx' },
  { name: "Front door", id: "5", url: 'https://xxx' } // 测试奇数数据的占位场景
];

ngOnInit() {
  this.transformToGridRows();
  // 初始化加载第一页数据
  this.updatePageData();
}

// 核心:把一维摄像头列表转为对齐的网格行
private transformToGridRows() {
  this.fullGridRows = [];
  // 按列数切片分组
  for (let i = 0; i < this.rawCameraList.length; i += this.GRID_COLUMN_COUNT) {
    const currentRowCameras = this.rawCameraList.slice(i, i + this.GRID_COLUMN_COUNT);
    // 不足列数的补null占位,保证行列对齐
    while (currentRowCameras.length < this.GRID_COLUMN_COUNT) {
      currentRowCameras.push(null);
    }
    // 转为datatable可识别的行结构,key对应网格列位置
    this.fullGridRows.push({
      col0: currentRowCameras[0],
      col1: currentRowCameras[1]
    });
  }
  // 同步总数据量给分页组件
  this.totalRows = this.fullGridRows.length;
}

// 分页切换时更新当前页的行数据
onPageChange(event) {
  this.currentPageOffset = event.offset;
  this.updatePageData();
}

private updatePageData() {
  const start = this.currentPageOffset * this.PAGE_SIZE;
  const end = start + this.PAGE_SIZE;
  this.gridRows = this.fullGridRows.slice(start, end);
}

2. 页面模板配置

直接在HTML中定义自定义列模板,渲染摄像头卡片,开启行列分隔和分页:

<ngx-datatable
  [rows]="gridRows"
  [columnMode]="'force'"
  [headerHeight]="0" <!-- 不需要表头可直接设为0隐藏 -->
  [rowHeight]="220" <!-- 匹配摄像头卡片的高度 -->
  [limit]="PAGE_SIZE"
  [count]="totalRows"
  [offset]="currentPageOffset"
  (page)="onPageChange($event)"
  [verticalSeparator]="true" <!-- 开启列之间的分隔线 -->
  [horizontalSeparator]="true" <!-- 开启行之间的分隔线 -->
>
  <!-- 第一列摄像头模板 -->
  <ngx-datatable-column>
    <ng-template ngx-datatable-cell-template let-row="row">
      <div *ngIf="row.col0" class="camera-card">
        <div class="camera-title">{{ row.col0.name }}</div>
        <div class="camera-stream">
          <!-- 这里替换为你的实际视频播放组件/标签 -->
          视频地址:{{ row.col0.video || row.col0.url }}
        </div>
      </div>
      <div *ngIf="!row.col0" class="empty-cell"></div>
    </ng-template>
  </ngx-datatable-column>

  <!-- 第二列摄像头模板 -->
  <ngx-datatable-column>
    <ng-template ngx-datatable-cell-template let-row="row">
      <div *ngIf="row.col1" class="camera-card">
        <div class="camera-title">{{ row.col1.name }}</div>
        <div class="camera-stream">
          视频地址:{{ row.col1.video || row.col1.url }}
        </div>
      </div>
      <div *ngIf="!row.col1" class="empty-cell"></div>
    </ng-template>
  </ngx-datatable-column>
</ngx-datatable>

3. 样式实现(强化行列分隔效果)

/* 给datatable整体加外边框,强化网格边界 */
.ngx-datatable {
  border: 1px solid #e5e7eb;
  border-radius: 4px;
}
/* 摄像头卡片样式 */
.camera-card {
  width: 100%;
  height: 100%;
  background: #fff;
  display: flex;
  flex-direction: column;
}
.camera-title {
  height: 36px;
  padding: 0 12px;
  line-height: 36px;
  font-size: 14px;
  font-weight: 500;
  border-bottom: 1px solid #e5e7eb;
  background: #f9fafb;
}
.camera-stream {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #9ca3af;
  background: #111827;
}
/* 空单元格占位 */
.empty-cell {
  width: 100%;
  height: 100%;
  background: #f3f4f6;
}

通用适配说明

  • 如果需要调整为每行3/4列的网格效果,仅需修改GRID_COLUMN_COUNT的值,对应增加<ngx-datatable-column>模板、在transformToGridRows方法里补充col2/col3的映射即可,无需调整核心逻辑
  • 分页能力完全复用ngx-datatable原生能力,支持页码切换、每页数量调整等内置功能,无需额外开发分页组件
  • 摄像头数量为奇数时,自动在最后一行补空单元格占位,不会出现单元格错位、边框断开的问题

内容的提问来源于stack exchange,提问作者Edson Junior

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.08 13:36:11