鱼C论坛

 找回密码
 立即注册
楼主: kerln888

[已解决]html5 左边菜单栏保持展开或者关闭的状态

  [复制链接]
发表于 前天 17:29 | 显示全部楼层
kerln888 发表于 2026-02-18 17:29
@FishC javasript Plotly.js如何创建子图

在 Plotly.js 中创建子图,通常使用 make_subplots 函数。以下是具体步骤:


  • 引入 Plotly.js 库和 make_subplots 函数。

    1. <script src="[url=https://cdn.plot.ly/plotly-latest.min.js"></script>]https://cdn.plot.ly/plotly-latest.min.js"></script>[/url]
    2. <script>
    3.     // 代码将写在这里
    4. </script>
    复制代码

  • 使用 Plotly.makeSubplots 创建子图网格。

    1. // 创建一个 2x2 的子图网格
    2. var fig = {
    3.     data: [],
    4.     layout: {},
    5.     config: {responsive: true}
    6. };

    7. Plotly.makeSubplots({
    8.     rows: 2,
    9.     cols: 2,
    10.     subplotTitles: ['子图 1', '子图 2', '子图 3', '子图 4']
    11. }).then(function(figure) {
    12.     fig = figure;
    13.    
    14.     // 添加数据到每个子图
    15.     // 示例:为每个子图添加散点图
    16.     for (var i = 0; i < 4; i++) {
    17.         fig.addTrace({
    18.             x: [1, 2, 3],
    19.             y: [Math.random() * 10, Math.random() * 10, Math.random() * 10],
    20.             type: 'scatter',
    21.             mode: 'lines+markers',
    22.             name: '数据系列 ' + (i + 1)
    23.         }, Math.floor(i / 2) + 1, (i % 2) + 1); // 指定行和列
    24.     }
    25.    
    26.     // 绘制图表到指定的 div 元素
    27.     Plotly.newPlot('myDiv', fig.data, fig.layout, fig.config);
    28. });
    复制代码

  • 在 HTML 中添加一个容器 div。

    1. <div id="myDiv" style="width: 800px; height: 600px;"></div>
    复制代码



关键点:

  • 使用 Plotly.makeSubplots 创建网格布局。
  • 使用 addTrace 方法添加数据到指定位置(行和列从 1 开始计数)。
  • 子图类型可以是散点图、折线图、柱状图等,通过 type 参数设置。


提示:

  • 确保 Plotly.js 库已正确加载。
  • 调整 rowscols 参数可以改变子图数量。
  • 使用 subplotTitles 为每个子图添加标题。


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 前天 17:33 | 显示全部楼层
FishC 发表于 2026-2-18 17:29
  • 引入 Plotly.js 库和 make_subplots 函数。

  • @FishC javasript中使用make_subplots函数,而不是makeSubplots!!请写出正确的例子
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 前天 17:33 | 显示全部楼层
    kerln888 发表于 2026-02-18 17:33
    FishC 发表于 2026-2-18 17:29
    引入 Plotly.js 库和  ...


    在 JavaScript 的 Plotly.js 库中,创建子图的正确函数是 Plotly.makeSubplots(驼峰命名法),而不是 make_subplots。以下是一个使用该函数的示例:

    1. // 引入 Plotly.js 库后,使用 Plotly.makeSubplots 创建子图
    2. // 假设已通过 CDN 等方式引入 Plotly.js

    3. // 定义两个轨迹数据
    4. var trace1 = {
    5.   x: [1, 2, 3],
    6.   y: [2, 3, 1],
    7.   type: 'scatter',
    8.   name: '散点图'
    9. };

    10. var trace2 = {
    11.   x: [1, 2, 3],
    12.   y: [4, 1, 2],
    13.   type: 'bar',
    14.   name: '柱状图'
    15. };

    16. // 使用 Plotly.makeSubplots 创建子图布局(2 行 1 列)
    17. Plotly.makeSubplots({
    18.   rows: 2,
    19.   cols: 1,
    20.   subplotTitles: ['子图1: 散点图', '子图2: 柱状图']
    21. }).then(function(fig) {
    22.   // 将轨迹添加到子图的指定位置
    23.   fig.addTrace(trace1, 1, 1); // 第一行第一列
    24.   fig.addTrace(trace2, 2, 1); // 第二行第一列

    25.   // 在页面中绘制图表,假设有一个 id 为 'myDiv' 的容器
    26.   Plotly.newPlot('myDiv', fig.data, fig.layout);
    27. });
    复制代码


    注意:确保在 HTML 中有一个 <div id="myDiv"></div> 元素来显示图表。此示例展示了如何创建包含散点图和柱状图的子图。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 前天 17:36 | 显示全部楼层
    FishC 发表于 2026-2-18 17:33
    在 JavaScript 的 Plotly.js 库中,创建子图的正确函数是 Plotly.makeSubplots(驼峰命名法),而不是  ...

    @FishC 报错了,Uncaught TypeError: Plotly.makeSubplots is not a function
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 前天 17:36 | 显示全部楼层
    kerln888 发表于 2026-02-18 17:36
    FishC 发表于 2026-2-18 17:33
    在 JavaScript 的 Plo ...


    嗨,遇到这个错误,通常是因为函数名写错了或者Plotly.js的版本不对。

    请按以下步骤检查和解决:

    1.  **检查函数名拼写是否正确(最重要的步骤)**
        正确的大小写是:Plotly.makeSubplots
        请仔细核对你的代码,确保没有写成 `makeSubplots`、`Makesubplots` 或其他变体。

    2.  **检查并更新你的 Plotly.js 版本**
        makeSubplots 函数是在相对较新的版本中引入的。如果你的版本太旧,这个函数就不存在。
        *   **推荐方法**:直接使用官方CDN链接引入一个较新的版本(例如 1.x.x 或 2.x.x)。
        *   在你HTML文件的 `<head>` 或 `<body>` 末尾,将旧的Plotly引用替换为:
          

    1.         <script src="[url=https://cdn.plot.ly/plotly-2.18.2.min.js"></script>]https://cdn.plot.ly/plotly-2.18.2.min.js"></script>[/url]
    2.         
    复制代码


    3.  **如果更新版本后问题依旧,请使用以下正确代码示例进行测试**
        这是一个最基本的使用方法:
       

    1.     // 1. 定义子图的网格布局
    2.     var layout = {
    3.         grid: {
    4.             rows: 2,
    5.             columns: 1,
    6.             pattern: 'independent' // 子图使用独立的坐标轴
    7.         },
    8.         title: '使用 makeSubplots 创建的示例'
    9.     };

    10.     // 2. 定义两个简单的数据轨迹
    11.     var trace1 = {
    12.         x: [1, 2, 3],
    13.         y: [2, 5, 3],
    14.         type: 'scatter',
    15.         name: '图表 A'
    16.     };
    17.     var trace2 = {
    18.         x: [1, 2, 3, 4],
    19.         y: [10, 15, 13, 17],
    20.         type: 'scatter',
    21.         name: '图表 B',
    22.         xaxis: 'x2', // 指定使用第二套X轴
    23.         yaxis: 'y2'  // 指定使用第二套Y轴
    24.     };

    25.     var data = [trace1, trace2];

    26.     // 3. 创建图表!注意函数名:Plotly.makeSubplots
    27.     Plotly.makeSubplots({
    28.         rows: 2,
    29.         cols: 1,
    30.         specs: [ [{}, {}] ] // 为每个子图指定配置,这里两个都使用默认{}
    31.     })
    32.     .then(function(fig) { // makeSubplots 返回一个 Promise
    33.         // fig 是一个包含了布局和初始数据的对象
    34.         // 将我们的数据添加到对应的子图位置
    35.         fig.addTraces(trace1, 1, 1); // 第一行,第一列
    36.         fig.addTraces(trace2, 2, 1); // 第二行,第一列

    37.         // 应用我们自定义的布局(包含 grid 配置)
    38.         fig.layout = layout;

    39.         // 渲染图表到指定的 div 元素
    40.         Plotly.newPlot('myDiv', fig.data, fig.layout);
    41.     });
    42.    
    复制代码

        对应的HTML需要一个id为 `myDiv` 的元素:
       

    1.     <div id="myDiv"></div>
    2.    
    复制代码


    **总结一下,请这样做:**

    *   第一步:检查并修正代码中的函数名拼写。
    *   第二步:将你的 Plotly.js 库链接更新到最新或较新的版本。
    *   第三步:用上面的完整示例代码替换你的代码,测试是否能正常运行。

    如果按照以上步骤操作后问题仍然存在,请告诉我你使用的Plotly.js具体版本号,我们再进一步排查。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 00:44 | 显示全部楼层
    @FishC 下载了plotly-3.3.0.min.js,nodejs 如何在前端html引入这个库
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 00:44 | 显示全部楼层
    kerln888 发表于 2026-02-19 00:44
    @FishC 下载了plotly-3.3.0.min.js,nodejs 如何在前 ...

    首先,将下载的 plotly-3.3.0.min.js 文件放在你的项目文件夹中,例如 js 目录下。然后,在前端 HTML 文件中使用 <script> 标签引入这个本地文件。

    示例 HTML 代码:


    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4.     <title>Plotly 示例</title>
    5. </head>
    6. <body>
    7.     <div id="chart"></div>

    8.     <!-- 引入本地 Plotly 库 -->
    9.     <script src="js/plotly-3.3.0.min.js"></script>
    10.     <script>
    11.         // 使用 Plotly 绘制图表
    12.         var data = [{
    13.             x: [1, 2, 3, 4],
    14.             y: [10, 15, 13, 17],
    15.             type: 'scatter'
    16.         }];
    17.         Plotly.newPlot('chart', data);
    18.     </script>
    19. </body>
    20. </html>
    复制代码


    注意:src 中的路径要正确对应文件位置。如果文件在 HTML 同级目录,直接写 plotly-3.3.0.min.js;如果在子目录如 js 中,则写 js/plotly-3.3.0.min.js

    如果你使用 Node.js 作为后端服务器,可能需要配置静态文件服务,以确保浏览器能访问到该 JS 文件。例如,使用 Express 框架时:


    1. const express = require('express');
    2. const app = express();
    3. const path = require('path');

    4. // 设置静态文件目录(假设文件放在 public/js/ 中)
    5. app.use(express.static(path.join(__dirname, 'public')));

    6. app.get('/', (req, res) => {
    7.     res.sendFile(path.join(__dirname, 'public', 'index.html'));
    8. });

    9. app.listen(3000, () => {
    10.     console.log('服务器已启动:[url=http://localhost:3000');]http://localhost:3000');[/url]
    11. });
    复制代码


    plotly-3.3.0.min.js 放入 public/js/ 文件夹,并在 HTML 中将 src 改为 /js/plotly-3.3.0.min.js。这样,前端就能成功引入 Plotly 库了。


    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 21:20 | 显示全部楼层
    @FishC matplotlib创建了2*2的子图,能否实现点击任意子图,点击的子图放大占满整个画布,其他子图隐藏。再点击子图缩小到原来大小,显示其他子图,布局和点击之前一样
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 21:20 | 显示全部楼层
    kerln888 发表于 2026-02-19 21:20
    @FishC matplotlib创建了2*2的子图,能否实现点击任意 ...

    我们可以通过以下步骤实现这个交互功能:

    1. 创建2x2的子图,并存储每个子图的原始位置信息
    2. 为每个子图添加点击事件监听器
    3. 在点击事件中切换子图的放大/缩小状态

    下面是完整的实现代码:

    1. import matplotlib.pyplot as plt
    2. import numpy as np

    3. # 创建2x2的子图
    4. fig, axes = plt.subplots(2, 2, figsize=(8, 6))
    5. fig.subplots_adjust(wspace=0.3, hspace=0.3)  # 调整子图间距

    6. # 存储每个子图的原始位置和状态
    7. original_positions = {}
    8. is_zoomed = False
    9. current_zoomed_ax = None

    10. # 为每个子图创建示例数据
    11. titles = ['Subplot 1', 'Subplot 2', 'Subplot 3', 'Subplot 4']
    12. for i, ax in enumerate(axes.flat):
    13.     x = np.linspace(0, 2*np.pi, 100)
    14.     y = np.sin(x + i*np.pi/4)
    15.     ax.plot(x, y)
    16.     ax.set_title(titles[i])
    17.     ax.grid(True)
    18.    
    19.     # 存储原始位置
    20.     original_positions[ax] = ax.get_position()

    21. # 点击事件处理函数
    22. def on_click(event):
    23.     global is_zoomed, current_zoomed_ax
    24.    
    25.     # 检查点击是否发生在某个子图内
    26.     for ax in axes.flat:
    27.         if ax.contains(event)[0]:
    28.             if not is_zoomed:
    29.                 # 放大点击的子图
    30.                 zoom_ax(ax)
    31.                 is_zoomed = True
    32.                 current_zoomed_ax = ax
    33.             elif current_zoomed_ax == ax:
    34.                 # 如果点击的是已经放大的子图,则恢复
    35.                 restore_all()
    36.                 is_zoomed = False
    37.                 current_zoomed_ax = None
    38.             else:
    39.                 # 如果已经有放大的子图,先恢复再放大新点击的子图
    40.                 restore_all()
    41.                 zoom_ax(ax)
    42.                 current_zoomed_ax = ax
    43.             plt.draw()
    44.             break

    45. # 放大指定子图
    46. def zoom_ax(ax):
    47.     # 隐藏所有子图
    48.     for a in axes.flat:
    49.         a.set_visible(False)
    50.    
    51.     # 显示并放大选中的子图
    52.     ax.set_visible(True)
    53.     ax.set_position([0.1, 0.1, 0.8, 0.8])  # 设置到画布中央
    54.     ax.set_title(f'{ax.get_title()} (Zoomed)', fontsize=14, fontweight='bold')

    55. # 恢复所有子图到原始状态
    56. def restore_all():
    57.     for ax in axes.flat:
    58.         ax.set_visible(True)
    59.         ax.set_position(original_positions[ax])
    60.         # 恢复原始标题(去掉Zoomed标记)
    61.         original_title = ax.get_title().replace(' (Zoomed)', '')
    62.         ax.set_title(original_title)

    63. # 连接点击事件
    64. fig.canvas.mpl_connect('button_press_event', on_click)

    65. plt.show()
    复制代码

    代码说明:

    1. original_positions:字典,存储每个子图的原始位置
    2. is_zoomed:布尔值,记录当前是否有子图被放大
    3. current_zoomed_ax:记录当前被放大的子图对象

    主要函数:
    - on_click():处理点击事件
    - zoom_ax():放大指定子图,隐藏其他子图
    - restore_all():恢复所有子图到原始状态

    使用方式:
    1. 运行代码后,点击任意子图,该子图会放大并占满画布
    2. 再次点击放大的子图,会恢复到原来的2x2布局
    3. 如果已经有放大的子图,点击其他子图会先恢复再放大新点击的子图

    注意事项:
    - 确保安装了最新版本的matplotlib
    - 代码中的坐标轴位置参数可以根据需要调整
    - 可以根据需要修改子图的大小和间距


    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 22:22 | 显示全部楼层
    @FishC
    fig = Figure(figsize=(19.2, 10.8), dpi=100)
    fig.subplots_adjust(left=0.1, right=0.9, top=0.95, bottom=0.05)
    gs = gridspec.GridSpec(nrows=2, ncols=3)
    ax1 = self.fig.add_subplot(gs[0, 0])
    ax2 = self.fig.add_subplot(gs[0, 1])
    ax3 = self.fig.add_subplot(gs[0, 2])
    ax4 = self.fig.add_subplot(gs[1, 0])
    ax5_6 = self.fig.add_subplot(gs[1, 1:3])
    matplotlib这样创建的子图,能否实现点击任意子图,点击的子图放大占满整个画布,其他子图隐藏。再点击子图缩小到原来大小,显示其他子图,布局和点击之前一样
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 22:23 | 显示全部楼层
    kerln888 发表于 2026-02-19 22:22
    @FishC
    fig = Figure(figsize=(19.2, 10.8), dpi=100 ...


    要实现点击子图放大/缩小的交互功能,需要使用 matplotlib 的事件处理系统。以下是完整的解决方案:


    1. import matplotlib.pyplot as plt
    2. from matplotlib import gridspec
    3. import matplotlib

    4. class InteractiveSubplots:
    5.     def __init__(self):
    6.         self.fig = plt.figure(figsize=(19.2, 10.8), dpi=100)
    7.         self.fig.subplots_adjust(left=0.1, right=0.9, top=0.95, bottom=0.05)
    8.         gs = gridspec.GridSpec(nrows=2, ncols=3)
    9.         
    10.         # 创建子图
    11.         self.ax1 = self.fig.add_subplot(gs[0, 0])
    12.         self.ax2 = self.fig.add_subplot(gs[0, 1])
    13.         self.ax3 = self.fig.add_subplot(gs[0, 2])
    14.         self.ax4 = self.fig.add_subplot(gs[1, 0])
    15.         self.ax5_6 = self.fig.add_subplot(gs[1, 1:3])
    16.         
    17.         # 保存所有子图
    18.         self.all_axes = [self.ax1, self.ax2, self.ax3, self.ax4, self.ax5_6]
    19.         
    20.         # 保存原始位置信息
    21.         self.original_positions = {}
    22.         for ax in self.all_axes:
    23.             self.original_positions[ax] = ax.get_position()
    24.         
    25.         # 当前放大的子图
    26.         self.zoomed_ax = None
    27.         
    28.         # 绑定点击事件
    29.         for ax in self.all_axes:
    30.             ax._zoom_id = self.fig.canvas.mpl_connect('button_press_event',
    31.                                                     lambda event, ax=ax: self.on_click(event, ax))
    32.         
    33.         # 为每个子图添加示例内容以便区分
    34.         for i, ax in enumerate(self.all_axes, 1):
    35.             ax.text(0.5, 0.5, f'Subplot {i}', ha='center', va='center', fontsize=20)
    36.             ax.set_title(f'Ax{i}')
    37.         
    38.     def on_click(self, event, ax):
    39.         if event.inaxes != ax:
    40.             return
    41.         
    42.         if self.zoomed_ax is None:
    43.             # 放大选中的子图
    44.             self.zoomed_ax = ax
    45.             
    46.             # 隐藏其他子图
    47.             for other_ax in self.all_axes:
    48.                 if other_ax != ax:
    49.                     other_ax.set_visible(False)
    50.             
    51.             # 将选中的子图调整到整个画布
    52.             ax.set_position([0, 0, 1, 1])
    53.             ax.set_title(f'{ax.get_title()} (Full Screen) - Click to return', fontsize=16)
    54.             
    55.         elif self.zoomed_ax == ax:
    56.             # 恢复原始布局
    57.             ax.set_position(self.original_positions[ax])
    58.             ax.set_title(ax.get_title().replace(' (Full Screen) - Click to return', ''))
    59.             
    60.             # 显示所有子图
    61.             for other_ax in self.all_axes:
    62.                 other_ax.set_visible(True)
    63.             
    64.             self.zoomed_ax = None
    65.         
    66.         # 重绘画布
    67.         self.fig.canvas.draw_idle()

    68. # 使用示例
    69. if __name__ == "__main__":
    70.     interactive = InteractiveSubplots()
    71.     plt.show()
    复制代码


    关键点说明:

    1. get_position()set_position():用于保存和恢复子图的原始位置
    2. set_visible(False/True):控制子图的显示/隐藏
    3. mpl_connect('button_press_event', ...):绑定点击事件处理函数
    4. event.inaxes:判断点击事件发生在哪个坐标轴内
    5. fig.canvas.draw_idle():更新画布显示

    注意事项:

    1. 点击子图时会将其放大到整个画布,其他子图隐藏
    2. 再次点击已放大的子图会恢复到原始布局
    3. 点击画布空白区域不会触发任何操作
    4. 确保安装了最新版本的 matplotlib:pip install matplotlib --upgrade

    扩展建议:

    1. 可以添加动画效果让过渡更平滑
    2. 可以添加键盘快捷键支持(如按ESC键返回)
    3. 可以保存更多状态信息(如坐标轴范围)以便完全恢复

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 昨天 23:01 | 显示全部楼层
    @FishC
    fig = Figure(figsize=(19.2, 10.8), dpi=100)
    fig.subplots_adjust(left=0.1, right=0.9, top=0.95, bottom=0.05)
    gs = gridspec.GridSpec(nrows=2, ncols=3)
    ax1 = self.fig.add_subplot(gs[0, 0])
    ax2 = self.fig.add_subplot(gs[0, 1])
    ax3 = self.fig.add_subplot(gs[0, 2])
    ax3r = ax3.twinx()
    ax4 = self.fig.add_subplot(gs[1, 0])
    ax5_6 = self.fig.add_subplot(gs[1, 1:3])
    matplotlib这样创建的子图,其中ax3子图中创建一个共享 x 轴但具有独立 y 轴的双 y 轴图表ax3r,能否实现点击任意子图,点击的子图放大占满整个画布,其他子图隐藏。再点击子图缩小到原来大小,显示其他子图,布局和点击之前一样
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 昨天 23:02 | 显示全部楼层
    kerln888 发表于 2026-02-19 23:01
    @FishC
    fig = Figure(figsize=(19.2, 10.8), dpi=100 ...


    可以的,需要给子图添加事件监听器来实现这个功能。以下是完整的实现代码:


    1. import matplotlib.pyplot as plt
    2. import matplotlib.gridspec as gridspec

    3. class InteractiveFigure:
    4.     def __init__(self):
    5.         self.fig = plt.figure(figsize=(19.2, 10.8), dpi=100)
    6.         self.fig.subplots_adjust(left=0.1, right=0.9, top=0.95, bottom=0.05)
    7.         
    8.         # 创建原始网格布局
    9.         self.gs = gridspec.GridSpec(nrows=2, ncols=3)
    10.         self.ax1 = self.fig.add_subplot(self.gs[0, 0])
    11.         self.ax2 = self.fig.add_subplot(self.gs[0, 1])
    12.         self.ax3 = self.fig.add_subplot(self.gs[0, 2])
    13.         self.ax3r = self.ax3.twinx()
    14.         self.ax4 = self.fig.add_subplot(self.gs[1, 0])
    15.         self.ax5_6 = self.fig.add_subplot(self.gs[1, 1:3])
    16.         
    17.         # 保存原始布局信息
    18.         self.original_layout = {
    19.             'fig': {'left': 0.1, 'right': 0.9, 'top': 0.95, 'bottom': 0.05},
    20.             'grid': self.gs,
    21.             'axes': [self.ax1, self.ax2, self.ax3, self.ax3r, self.ax4, self.ax5_6]
    22.         }
    23.         
    24.         self.is_zoomed = False  # 标记是否处于放大状态
    25.         self.current_zoomed_axes = None  # 当前被放大的坐标轴
    26.         
    27.         # 绑定点击事件到所有坐标轴
    28.         self.bind_click_events()
    29.         
    30.     def bind_click_events(self):
    31.         """为所有坐标轴绑定点击事件"""
    32.         for ax in self.original_layout['axes']:
    33.             # 跳过双Y轴中的第二个Y轴,避免重复处理
    34.             if ax is not self.ax3r:
    35.                 ax.figure.canvas.mpl_connect('button_press_event',
    36.                                            lambda event, ax=ax: self.on_click(event, ax))
    37.         
    38.     def on_click(self, event, ax):
    39.         """点击事件处理函数"""
    40.         if event.inaxes != ax:
    41.             return
    42.             
    43.         if not self.is_zoomed:
    44.             self.zoom_axes(ax)
    45.         else:
    46.             self.restore_layout()
    47.    
    48.     def zoom_axes(self, ax):
    49.         """放大指定坐标轴"""
    50.         # 隐藏所有其他坐标轴
    51.         for other_ax in self.original_layout['axes']:
    52.             other_ax.set_visible(False)
    53.         
    54.         # 显示点击的坐标轴及其相关坐标轴(针对双Y轴)
    55.         if ax in [self.ax3, self.ax3r]:
    56.             self.ax3.set_visible(True)
    57.             self.ax3r.set_visible(True)
    58.         else:
    59.             ax.set_visible(True)
    60.         
    61.         # 调整布局:点击的坐标轴占满整个画布
    62.         self.fig.subplots_adjust(left=0.05, right=0.95, top=0.95, bottom=0.05)
    63.         
    64.         # 如果是双Y轴情况,需要重新调整子图位置
    65.         if ax in [self.ax3, self.ax3r]:
    66.             # 移除原来的坐标轴并重新创建以重新布局
    67.             self.ax3.remove()
    68.             self.ax3r.remove()
    69.             
    70.             # 创建占满整个画布的坐标轴
    71.             self.ax3 = self.fig.add_subplot(111)
    72.             self.ax3r = self.ax3.twinx()
    73.             
    74.             # 这里需要重新绘制原始数据(为了示例,我们只创建空坐标轴)
    75.             # 实际应用中,需要保存原始数据并重新绘制
    76.         
    77.         self.is_zoomed = True
    78.         self.current_zoomed_axes = ax
    79.         self.fig.canvas.draw()
    80.    
    81.     def restore_layout(self):
    82.         """恢复原始布局"""
    83.         # 恢复所有坐标轴的可见性
    84.         for ax in self.original_layout['axes']:
    85.             ax.set_visible(True)
    86.         
    87.         # 恢复原始布局设置
    88.         self.fig.subplots_adjust(**self.original_layout['fig'])
    89.         
    90.         # 如果之前放大的是双Y轴,需要恢复原始布局
    91.         if self.current_zoomed_axes in [self.ax3, self.ax3r]:
    92.             # 清除当前坐标轴
    93.             plt.clf()
    94.             
    95.             # 按照原始布局重新创建所有子图
    96.             self.gs = gridspec.GridSpec(nrows=2, ncols=3)
    97.             self.ax1 = self.fig.add_subplot(self.gs[0, 0])
    98.             self.ax2 = self.fig.add_subplot(self.gs[0, 1])
    99.             self.ax3 = self.fig.add_subplot(self.gs[0, 2])
    100.             self.ax3r = self.ax3.twinx()
    101.             self.ax4 = self.fig.add_subplot(self.gs[1, 0])
    102.             self.ax5_6 = self.fig.add_subplot(self.gs[1, 1:3])
    103.             
    104.             # 这里需要重新绘制原始数据
    105.         
    106.         self.is_zoomed = False
    107.         self.current_zoomed_axes = None
    108.         self.bind_click_events()  # 重新绑定事件
    109.         self.fig.canvas.draw()

    110. # 使用示例
    111. if __name__ == "__main__":
    112.     interactive_fig = InteractiveFigure()
    113.    
    114.     # 为每个子图添加一些示例数据
    115.     interactive_fig.ax1.plot([1, 2, 3], [1, 4, 9])
    116.     interactive_fig.ax1.set_title("子图1")
    117.    
    118.     interactive_fig.ax2.plot([1, 2, 3], [3, 2, 1])
    119.     interactive_fig.ax2.set_title("子图2")
    120.    
    121.     interactive_fig.ax3.plot([1, 2, 3], [2, 4, 6], 'r-')
    122.     interactive_fig.ax3.set_title("子图3(双Y轴)")
    123.     interactive_fig.ax3.set_ylabel("左Y轴", color='r')
    124.    
    125.     interactive_fig.ax3r.plot([1, 2, 3], [10, 20, 30], 'b-')
    126.     interactive_fig.ax3r.set_ylabel("右Y轴", color='b')
    127.    
    128.     interactive_fig.ax4.plot([1, 2, 3], [5, 5, 5])
    129.     interactive_fig.ax4.set_title("子图4")
    130.    
    131.     interactive_fig.ax5_6.plot([1, 2, 3], [0, 1, 0])
    132.     interactive_fig.ax5_6.set_title("子图5-6")
    133.    
    134.     plt.show()
    复制代码


    关键实现要点:

    1. zoom_axes()方法:隐藏其他子图,将被点击的子图放大到全屏
       - 对于普通子图:直接设置该子图为可见,其他为不可见
       - 对于双Y轴子图:需要同时显示主坐标轴和双生坐标轴

    2. restore_layout()方法:恢复原始布局
       - 重新设置所有子图为可见
       - 恢复原始的布局参数
       - 对于双Y轴子图,需要重新创建坐标轴以确保布局正确

    3. 事件绑定:
       - 为每个子图绑定点击事件(跳过双生坐标轴避免重复)
       - 点击时判断当前状态,执行放大或恢复操作

    4. 状态管理:
       - is_zoomed:标记是否处于放大状态
       - current_zoomed_axes:记录当前被放大的坐标轴
       - original_layout:保存原始布局信息用于恢复

    注意事项:
    - 在实际应用中,需要保存每个子图的绘图数据,在恢复布局时重新绘制
    - 双Y轴子图需要特殊处理,确保两个坐标轴都能正确显示和隐藏
    - 可以通过调整subplots_adjust参数来优化放大时的边距

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

     楼主| 发表于 3 小时前 | 显示全部楼层
    @FishC matplotlib如何创建一个仪表盘
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    发表于 3 小时前 | 显示全部楼层
    kerln888 发表于 2026-02-20 01:10
    @FishC matplotlib如何创建一个仪表盘

    FishC解答:使用 matplotlib 创建仪表盘,可以结合极坐标和图形元素绘制。以下是一个简单示例:
    1. import matplotlib.pyplot as plt
    2. import numpy as np

    3. fig = plt.figure(figsize=(8, 8))
    4. ax = fig.add_subplot(111, projection='polar')

    5. # 设置角度范围(0到180度,转换为弧度)
    6. theta = np.linspace(0, np.pi, 100)
    7. # 绘制半圆背景
    8. ax.plot(theta, [1]*100, color='gray', linewidth=20, alpha=0.3)

    9. # 设置刻度范围和标签
    10. ax.set_ylim(0, 1)
    11. ax.set_xticks(np.linspace(0, np.pi, 5))
    12. ax.set_xticklabels(['0', '45', '90', '135', '180'])

    13. # 绘制指针(例如指向90度位置)
    14. pointer_angle = np.pi / 2  # 90度
    15. ax.plot([pointer_angle, pointer_angle], [0, 0.8], color='red', linewidth=4)

    16. # 隐藏径向标签和网格
    17. ax.set_yticklabels([])
    18. ax.grid(True)

    19. plt.show()
    复制代码


    • 使用 projection='polar' 创建极坐标轴。
    • 通过 np.linspace 生成角度数据,绘制半圆弧作为仪表盘背景。
    • ax.plot 绘制指针,通过调整角度和半径控制指向。
    • 隐藏径向标签并使用网格线增强可读性。


    如需更复杂效果(如渐变颜色、多指针),可叠加多个绘图元素或使用 patches 模块绘制扇形。

    以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
    小甲鱼最新课程 -> https://ilovefishc.com
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

    GMT+8, 2026-2-20 04:44

    Powered by Discuz! X3.4

    © 2001-2023 Discuz! Team.

    快速回复 返回顶部 返回列表