Languages

Version

Theme

Widget

图表 Widget

简介

Filament 自带多个图表 Widget 模板,你可以用来展示实时、交互式图表。

使用以下命令开始创建 Widget:

php artisan make:filament-widget BlogPostsChart --chart

有一个 ChartWidget 类用于所有图表。图表的类型通过 getType() 方法设置。在这个例子中,该方法返回字符串 'line'

protected ?string $heading 变量用于设置图表的标题。如果你想要动态设置标题,可以重写 getHeading() 方法。

getData() 方法用于返回一个包含数据集和标签的数组。每个数据集都是一个用来绘制到图表的点构成的标签化数组,每个标签都是一个字符串。Filament 用来渲染图表的这种数据结构,与 Chart.js 库是一致的。你可以借助 Chart.js 文档去了解 getData() 方法基于图表类型可能的返回值。

<?php

namespace App\Filament\Widgets;

use Filament\Widgets\ChartWidget;

class BlogPostsChart extends ChartWidget
{
    protected ?string $heading = 'Blog Posts';

    protected function getData(): array
    {
        return [
            'datasets' => [
                [
                    'label' => 'Blog posts created',
                    'data' => [0, 10, 5, 2, 21, 32, 45, 74, 65, 45, 77, 89],
                ],
            ],
            'labels' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
        ];
    }

    protected function getType(): string
    {
        return 'line';
    }
}

现在,你可以到仪表盘上查看该 Widget 了。

可用图表类型

以下是你可以继承的图表 Widget 类,以及他们对应的 Chart.js 文档页面,从中你可以了解 getData() 应该返回哪些值。

自定义图表颜色

通过设置 $color 属性,你可以自定义图表数据的颜色

protected string $color = 'info';

如果你要进一步自定义颜色,或者在多个数据集中使用多种颜色,你仍然可以在数据中使用 Chart.js 的颜色选项

protected function getData(): array
{
    return [
        'datasets' => [
            [
                'label' => 'Blog posts created',
                'data' => [0, 10, 5, 2, 21, 32, 45, 74, 65, 45, 77, 89],
                'backgroundColor' => '#36A2EB',
                'borderColor' => '#9BD0F5',
            ],
        ],
        'labels' => ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    ];
}

从 Eloquent 模型中生成图表数据

要想从 Eloquent 模型中生成图表数据,Filament 推荐你安装 flowframe/laravel-trend 包。查看其文档

以下是使用 laravel-trend 包从模型中生成图表数据的一个示例:

use Flowframe\Trend\Trend;
use Flowframe\Trend\TrendValue;

protected function getData(): array
{
    $data = Trend::model(BlogPost::class)
        ->between(
            start: now()->startOfYear(),
            end: now()->endOfYear(),
        )
        ->perMonth()
        ->count();

    return [
        'datasets' => [
            [
                'label' => 'Blog posts',
                'data' => $data->map(fn (TrendValue $value) => $value->aggregate),
            ],
        ],
        'labels' => $data->map(fn (TrendValue $value) => $value->date),
    ];
}

过滤图表数据

你可以设置图表过滤器,用以调整图表上显示的数据。通常用来调整图表数据渲染的时间周期:

要设置过滤器的默认值,使用 $filter 属性:

public ?string $filter = 'today';

然后,定义 getFilters() 方法,以返回一个值和标签组成的数组给过滤器:

protected function getFilters(): ?array
{
    return [
        'today' => 'Today',
        'week' => 'Last week',
        'month' => 'Last month',
        'year' => 'This year',
    ];
}

你可以在 getData() 方法内使用当前活跃的过滤值:

protected function getData(): array
{
    $activeFilter = $this->filter;

    // ...
}

实时更新图表数据(轮询)

图表 Widget 默认每 5 秒钟刷新一次数据。

你可以通过重写类上的 $pollingInterval 属性自定义间隔时间:

protected ?string $pollingInterval = '10s';

或者,也可以完全禁用轮询:

protected ?string $pollingInterval = null;

设置图表最大高度

使用 $maxHeight 属性,你可以在图表上设置一个最大高度,以避免其变得过大:

protected ?string $maxHeight = '300px';

设置图表配置项

你可以在图表类中指定 $options 属性,用以控制 Chart.js 库提供的多个配置项。比如,你想让 Line Chart 关闭 legend

protected ?array $options = [
    'plugins' => [
        'legend' => [
            'display' => false,
        ],
    ],
];

此外,你可以重写 getOptions() 方法,返回选项的动态数组:

protected function getOptions(): array
{
    return [
        'plugins' => [
            'legend' => [
                'display' => false,
            ],
        ],
    ];
}

这些 PHP 数组会在图表渲染时转换成 JSON 对象。如果你想在该方法中返回原始 JavaScript,可以返回 RawJs 对象。如果你想使用 JavaScript 回调函数,这就很有用。比如:

use Filament\Support\RawJs;

protected function getOptions(): RawJs
{
    return RawJs::make(<<<JS
        {
            scales: {
                y: {
                    ticks: {
                        callback: (value) => '€' + value,
                    },
                },
            },
        }
    JS);
}

添加描述

使用 getDescription() 方法,你可以在图表的标题下面添加描述:

public function getDescription(): ?string
{
    return 'The number of blog posts published per month.';
}

禁用懒加载

默认情况下,Widget 使用懒加载。这意味着只有当它们在页面中可见时才会加载。

要禁用该行为,你可以在 Widget 类中重写 $isLazy 属性:

protected static bool $isLazy = true;

让图表可折叠

通过将 Widget 类的 $isCollapsible 属性设置成 true,你可以让图表变成可折叠:

protected bool $isCollapsible = true;

使用自定义 Chart.js 插件

Chart.js 提供了强大的插件系统,允许你扩展其功能并创建自定义图表行为。本指南将详解如何在图表 Widget 中使用它们。

第 1 步: 使用 NPM 安装插件

要开始使用,请先在项目中使用 NPM 安装该插件。本指南中,我们将安装 chartjs-plugin-datalabels

npm install chartjs-plugin-datalabels --save-dev

第 2 步: 创建 JavaScript 文件导入该插件

你可以创建 JavaScript 文件,在其中定义自定义插件。本指南针中,我们称之为 filament-chart-js-plugins。导入该插件,并将其添加到 window.filamentChartJsPlugins 数组:

import ChartDataLabels from 'chartjs-plugin-datalabels'

window.filamentChartJsPlugins ??= []
window.filamentChartJsPlugins.push(ChartDataLabels)

如果数组还没有初始化,那么在 push 之前对其进行初始化是很重要的。这可以确保注册 Chart.js 插件的多个 JavaScript 文件(尤其是来自 Filament 插件的文件)不会相互覆盖,无论它们的启动顺序如何。

你可以将想要的插件推入到 filamentChartJsPlugins 数组,你无需单独文件来导入每个插件:

第 3 步: 使用 Vite 编译 JavaScript 文件

现在,你需要使用 Vite 或者其他捆绑器(Bundler)编译 JavaScript 文件。在 Vite 配置(通常是 vite.config.js)中导入该文件。比如:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: [
                'resources/css/app.css',
                'resources/js/app.js',
                'resources/css/filament/admin/theme.css',
                'resources/js/filament-chart-js-plugins.js', // Include the new file in the `input` array so it is built
            ],
        }),
    ],
});

使用 npm run build 编译该文件。

第 4 步: 在 Filament 中注册该 JavaScript 文件

Filament 需要知道在渲染图表 Widget 时导入此 JavaScript 文件。你可以在类似 AppServiceProvider 的服务提供者的 boot() 方法中执行此操作:

use Filament\Support\Assets\Js;
use Filament\Support\Facades\FilamentAsset;
use Illuminate\Support\Facades\Vite;

FilamentAsset::register([
    Js::make('chart-js-plugins', Vite::asset('resources/js/filament-chart-js-plugins.js'))->module(),
]);

可查看更多关于资源注册以及为特定面板注册资源

Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion

Previous
统计概览 Widget