整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

动态数据可视化:python生成折线赛车动画

码解析

代码主要完成了从 SQLite 数据库读取数据,然后利用 Matplotlib 库创建一个动态的折线赛车图。以下是代码的主要结构和功能点:

  1. 库导入部分: 导入了 numpy, pandas, sqlite3, matplotlib 等库和函数。
  2. 设置 FFmpeg 路径: 用于动画视频的生成。
  3. 读取数据函数 read_data_from_db: 连接 SQLite 数据库,读取指定表的数据,并对数据进行处理,包括重命名列名,舍入数据和设置索引。
  4. 生成线性赛车图动画函数 line_chart_race: 该函数具有多个参数,包括数据库表名、日期列名称、输出文件名、图表标题、图表尺寸、DPI 和动画帧持续时间。 在函数内部,它首先读取数据,然后使用 matplotlib 创建一个动画对象,该对象在每个帧上调用 plot_frame 函数来绘制折线图。 最后,如果提供了文件名,它将动画保存为 MP4 文件,否则,它将尝试在 Jupyter Notebook 中以交互方式显示动画。
  5. 主函数部分: 调用 line_chart_race 函数来生成并保存动画。

代码

import numpy as np
import pandas as pd
import sqlite3
import matplotlib as mpl
from matplotlib import pyplot as plt
import matplotlib.animation as animation
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl


mpl.rcParams['animation.ffmpeg_path'] = r"D:\RJ\ffmpeg-5.1.2-essentials_build\bin\ffmpeg.exe"  # 请替换为你的 ffmpeg 的路径


# 读取数据,并对其进行处理,参数为数据库的表
def read_data_from_db(table_name, column_name=None):
    # 连接到数据库
    conn = sqlite3.connect(r'D:\wenjian\python\smart\data\req_data.db')

    # 读取数据表
    query = f"SELECT * FROM {table_name}"
    dfdata = pd.read_sql_query(query, conn)

    # 关闭数据库连接
    conn.close()

    dfdata = dfdata.rename({column_name: "date"}, axis=1)
    # 对数据进行舍入
    for col in dfdata.columns:
        if col != "date":
            dfdata.loc[:, col] = np.round(dfdata.loc[:, col], 3)

    # 设置索引
    dfdata.set_index("date")

    return dfdata

# 生成线性赛车图动画
def line_chart_race(table_name, column_name=None, filename=None, title="", figsize=(8, 4.5), dpi=300, duration=0.5):
    """
    参数:
        table_name: 读取数据库(r'D:\wenjian\python\smart\data\req_data.db'的表名
        column_name: 作为date的列名
        filename: 输出文件的名称,如果提供,将保存为MP4文件,否则在Jupyter Notebook中以交互方式显示
        title: 图表的标题
        figsize: 图表的尺寸,以英寸为单位,格式为 (宽度, 高度)
        dpi: 图表的像素密度,每英寸的点数
        duration: 动画中每个帧的持续时间,以秒为单位
    """
    # 设置中文显示
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体显示中文

    # 颜色映射列表
    cmap = ['#2E91E5', '#1CA71C', '#DA16FF', '#B68100', '#EB663B', '#00A08B', '#FC0080', '#6C7C32', '#862A16', '#620042', '#DA60CA', '#0D2A63'] * 100

    mpl.rcParams['animation.writer'] = 'ffmpeg'  # 更改为 'ffmpeg' 或 'avconv'
    mpl.rcParams['animation.embed_limit'] = 200  # 设置为较大的值,例如100MB

    
    df = read_data_from_db(table_name, column_name)

    assert "date" in df.columns, "df应该有一个名为date的列!"
    assert filename is None or filename.endswith(".mp4"), "文件名应该以*.mp4结尾!"  # 更改为 '*.mp4'

    fig, ax = plt.subplots(figsize=figsize, dpi=dpi)  # 在函数内部定义 fig 和 ax

    ax.set_facecolor("0.9")     # 设置坐标轴背景颜色的代码,0.9为灰色

    # 调整spines(图表的边框显示),False为不显示
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.spines["left"].set_visible(False)
    ax.spines["bottom"].set_visible(False)

    def plot_frame(date):
        # 根据日期筛选数据
        dfdata = df.loc[df["date"] <= date, :]
        dfdata.index = dfdata["date"]
        idx = range(len(dfdata))

        ax.clear()
        cols = [name for name in dfdata.columns if name != "date"]
        for i, col in enumerate(cols):
            # 绘制数据曲线
            ax.plot(idx, dfdata[col], color=cmap[i], lw=2)
            px, py = idx[-1], dfdata[col].iloc[-1]
            # 绘制数据点
            ax.scatter(px, py, color=cmap[i], edgecolor="black",
                       s=80, lw=2.5, zorder=4)

            # 添加数据点注释
            ax.annotate(col + ":\n" + str(py), xy=(px, py), xycoords="data",
                        xytext=(10, 2), fontweight="bold", color=cmap[i], textcoords="offset points")

        # 根据当前显示的数据调整x轴和y轴范围
        xlim = (0, px + 0.15 * (px - 0) + 0.1)  # 调整x轴最大值,使数据点位于左三分之二的位置,并添加一个小的偏移量
        ax.set_xlim(xmin=xlim[0], xmax=xlim[1])
        values = dfdata[[x for x in dfdata.columns if x != "date"]].values
        ylim = (values.min(), values.max())
        ax.set_ylim(ymin=ylim[0] - (ylim[1] - ylim[0]) / 10, ymax=ylim[1] + (ylim[1] - ylim[0]) / 10)

        # 设置xticks
        ticks_num = 12
        delta = int(np.ceil(len(dfdata) / ticks_num))
        ticks = list(range(0, len(dfdata), delta))
        dates = dfdata["date"].tolist()
        ticklabels = [dates[i] for i in ticks]
        ax.set_xticks(ticks)
        ax.set_xticklabels(ticklabels, rotation=45)  # 旋转x轴标签

        ax.tick_params(bottom=False, left=False, labelsize=8, direction="in", length=2)

        # 添加辅助元素
        s = dfdata["date"].iloc[-1]
        ax.text(0.5, 0.2, s, va="center", ha="center", alpha=0.3, size=25, transform=ax.transAxes)
        ax.grid(axis="x", color="white", lw=1, ls="-")
        ax.set_title(title, color="black", fontsize=12)

    line_animation = animation.FuncAnimation(fig, plot_frame, frames=df["date"], interval=int(duration * 1000))
    if filename is None:
        try:
            from IPython.display import HTML
            return HTML(line_animation.to_jshtml())
        except ImportError:
            pass
    else:
        line_animation.save(filename)  # 保存为MP4
        return filename


# 调取函数
if __name__ == '__main__':
    # 生成线性赛车图动画,参数分别是数据库的表、作为date列名称、导出视频名称和格式、图片大小、分解率、加解码时间
    line_chart_race('测试2', '年份', '测试.mp4', title="测试2", figsize=(8, 4.5), dpi=300, duration=0.2)

FFmpeg 的安装

  1. 下载 FFmpeg: 访问 FFmpeg 的官方下载页面。 在页面上,你会看到不同系统的下载链接,选择 Windows 的链接。通常,你可能会被重定向到一个第三方下载页面,例如 Gyan.dev 或 BtbN。 选择适合你的系统的版本(例如,如果你的系统是 64 位的,选择 64 位版本),然后下载 zip 文件。
  2. 解压 FFmpeg: 找到你刚刚下载的 zip 文件,通常会在你的“下载”文件夹中。 右键点击 zip 文件,然后选择“解压缩”或“提取”到一个你想要的目录,例如 C:\Program Files\ffmpeg。
  3. 添加 FFmpeg 到系统 PATH: 右键点击“此电脑”或“我的电脑”图标,然后选择“属性”。 点击“高级系统设置”。 点击“环境变量”按钮。 在“系统变量”区域,找到并选择“Path”变量,然后点击“编辑”。 在编辑窗口中,点击“新建”,然后输入你的 FFmpeg 的 bin 目录的路径,例如 C:\Program Files\ffmpeg\bin。 点击“确定”保存你的设置。
  4. 验证 FFmpeg 安装: 打开一个新的命令提示符或 PowerShell 窗口(关闭任何旧的窗口,以确保新的环境变量设置生效)。 输入 ffmpeg -version,然后按 Enter。 如果 FFmpeg 已正确安装,你应该能看到 FFmpeg 的版本信息。

现代前端开发中,可视化设计器逐渐成为了一个重要的功能模块,广泛应用于图形编辑、流程图绘制等领域。特别是在处理复杂路径、折线和最优路径应用时,通过Konva这一强大的HTML5 2D绘图库,开发者能够迅速构建功能强大、界面美观的可视化设计器。本文将深入探讨如何使用Konva实现折线的绘制与最优路径的应用,为你的开发之旅提供实用指南。

一、Konva简介

Konva是一个用于在浏览器中绘制2D图形的JavaScript库,基于HTML5 Canvas技术。它具有以下特点:

  • 高性能:能够处理大量图形对象。
  • 易用性:API简单、易于上手。
  • 丰富的功能:支持图形变换、事件处理、动画等。

二、项目初始化

1.安装Konva库

首先,需要在你的项目中引入Konva库。可以通过npm进行安装:

npm install konva

2.创建基本画布

创建一个基础的HTML页面,并添加一个用于绘图的容器。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Konva Visualization</title>
    <style>
        #container {
            width: 100%;
            height: 100vh;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <div id="container"></div>
    <script src="https://cdn.jsdelivr.net/npm/konva@8.2.1/konva.min.js"></script>
    <script src="script.js"></script>
</body>
</html>

在 script.js 文件中,初始化Konva舞台(Stage)和层(Layer)。

document.addEventListener('DOMContentLoaded', function () {
    var stage = new Konva.Stage({
        container: 'container',
        width: window.innerWidth,
        height: window.innerHeight
    });

    var layer = new Konva.Layer();
    stage.add(layer);
});

三、绘制折线

1.定义折线数据

折线由多个点构成,每个点用一个数组表示。假设我们要绘制一条从(50, 50)到(200, 200)的折线:

var points = [
    { x: 50, y: 50 },
    { x: 150, y: 150 },
    { x: 200, y: 50 }
];

2.创建并添加折线

使用Konva的Line对象绘制折线,并将其添加到层中。

var line = new Konva.Line({
    points: points.flatMap(point => [point.x, point.y]),
    stroke: 'red',
    strokeWidth: 2,
    lineCap: 'round',
    lineJoin: 'round'
});

layer.add(line);
layer.draw();

四、实现最优路径算法

最优路径算法在诸如导航、物流等应用中至关重要。我们以Dijkstra算法为例,计算两个点之间的最优路径

1.创建图数据结构

定义图的节点和边。

var graph = {
    A: { B: 1, C: 4 },
    B: { A: 1, C: 2, D: 5 },
    C: { A: 4, B: 2, D: 1 },
    D: { B: 5, C: 1 }
};

2.Dijkstra算法实现

实现一个简化版的Dijkstra算法来计算最优路径。

function dijkstra(graph, start, end) {
    var distances = {};
    var prev = {};
    var unvisited = new Set(Object.keys(graph));
  
    for (var node in graph) {
        distances[node] = Infinity;
        prev[node] = null;
    }
    distances[start] = 0;

    while (unvisited.size > 0) {
        var closestNode = Array.from(unvisited).reduce((nearest, node) => {
            return distances[node] < distances[nearest] ? node : nearest;
        });

        unvisited.delete(closestNode);

        if (closestNode === end) {
            var path = [];
            while (prev[closestNode]) {
                path.unshift(closestNode);
                closestNode = prev[closestNode];
            }
            return [start, ...path];
        }

        for (var neighbor in graph[closestNode]) {
            var distance = distances[closestNode] + graph[closestNode][neighbor];
            if (distance < distances[neighbor]) {
                distances[neighbor] = distance;
                prev[neighbor] = closestNode;
            }
        }
    }
    return [];
}

3.可视化最优路径

假设我们要计算A点到D点的最优路径:

var optimalPath = dijkstra(graph, 'A', 'D');

// 转换路径点为Konva可用的格式
var optimalPoints = optimalPath.map(point => {
    switch (point) {
        case 'A': return { x: 50, y: 50 };
        case 'B': return { x: 150, y: 150 };
        case 'C': return { x: 200, y: 50 };
        case 'D': return { x: 300, y: 200 };
    }
});

var optimalLine = new Konva.Line({
    points: optimalPoints.flatMap(point => [point.x, point.y]),
    stroke: 'blue',
    strokeWidth: 2,
    lineCap: 'round',
    lineJoin: 'round',
    dash: [10, 5] // 虚线效果
});

layer.add(optimalLine);
layer.draw();

五、优化与扩展

  1. 用户交互:可以添加拖拽和点击事件,让用户可以动态创建和修改折线。
  2. 动画效果:为折线添加动画效果,使路径绘制更加生动。
  3. 复杂路径算法:根据需求,集成其他更加复杂的路径算法,如A*算法等。

结语

通过Konva强大的绘图能力和简单易用的API,我们可以轻松实现强大的可视化设计器功能。无论是基础的折线绘制,还是复杂的最优路径计算,Konva都能够胜任。希望本文能帮你快速上手Konva,打造功能强大的可视化设计工具。

如果你在使用Konva的过程中有更多的心得或疑问,欢迎在评论区留言讨论。让我们共同学习,共同进步,探索前端开发的更多可能性!

学 设 计

教 学 内 容

折线图数据变化的实现

教 学 目 标

知识目标:了解数据在图形变化中的作用

能力目标:能够完成折线图数据修改的代码编写

素质目标:培养学生团结互助、热爱祖国的综合素质

重 点

Echarts中折线图定义和使用

难 点

折线图数据修改效果的代码编写

教学方法

讲授法、任务驱动法、启发法

课堂教学进程

教学环节

教师活动

学生活动

设计理念

1、 课堂考勤、上节课知识点回顾、课后作用问题处理(10分钟)

2、 课堂导入:折线图效果的实现(5分钟)

3、 新课内容:使用电子课件和效果演示工具的使用(20分钟)

以练习案例的方式引导学生自己动手实现效果,感受代码编写(45分钟)

4、总结课堂内容,布置作业(5分钟)

5