PyScript中Matplotlib图表及刻度显示异常,Pydroid运行正常求助
问题排查与解决
核心问题分析
- 绘图状态未重置:每次调用
run函数时,Matplotlib的全局绘图对象没有被重置,新图表会叠加在旧图表上,导致显示混乱。 - 数据类型错误:通过
Element().value获取的输入框值是字符串类型,直接存入numpy数组后,X轴会被识别为类别型数据而非数值型,引发刻度显示异常。 - PyScript环境适配问题:Matplotlib在PyScript中的默认后端渲染逻辑与本地Python环境(如Pydroid)不同,直接输出全局绘图对象会导致渲染异常。
修复后的完整代码
Python逻辑部分
import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_agg import FigureCanvasAgg def run(*args, **kwargs): # 重置所有旧绘图,创建新画布和轴对象 plt.close('all') fig, ax = plt.subplots() # 封装输入值转换函数,处理字符串转数值 def get_numeric_value(element_id): raw_val = Element(element_id).value try: return float(raw_val) if '.' in raw_val else int(raw_val) except ValueError: return 0 # 兜底处理无效输入 # 获取并转换所有输入数据 x_data = [get_numeric_value(f"te{i}") for i in range(1,6)] y_data = [get_numeric_value(f"te{i}") for i in range(6,11)] title = Element("title").value x_label = Element("xl").value y_label = Element("yl").value # 设置图表基础属性 ax.set_title(title) ax.set_xlabel(x_label) ax.set_ylabel(y_label) x = np.array(x_data) y = np.array(y_data) bar_colors = ["darkorange", "deeppink", "#04aa6d", "orchid", "dodgerblue"] # 根据选择绘制对应图表 chart_type = Element("selection").value if chart_type == "line" or chart_type == "": ax.plot(x, y) elif chart_type == "scatter": ax.scatter(x, y) elif chart_type == "barg": ax.bar(x, y, color=bar_colors) elif chart_type == "pie": # 饼图单独处理,清除原有轴并创建新子图 fig.clear() ax = fig.add_subplot() ax.pie(y, labels=x) ax.legend() # 渲染图像为RGBA数组,适配PyScript页面输出 canvas = FigureCanvasAgg(fig) canvas.draw() img_array = np.asarray(canvas.buffer_rgba()) pyscript.write("res", img_array)
HTML完整结构
<!-- 图表类型选择下拉框 --> <select id="selection"> <option value="" selected disabled>Select ( Graph / Chart ) Type</option> <option value="line">Line Graph</option> <option value="scatter">Scattered Graph</option> <option value="barg">Bar Graph</option> <option value="pie">Pie Chart</option> </select> <!-- X轴数据输入区 --> <div id="table1"> <input type="number" id="te1" placeholder="enter a no." value="1"> <input type="number" id="te2" placeholder="enter a no." value="2"> <input type="number" id="te3" placeholder="enter a no." value="3"> <input type="number" id="te4" placeholder="enter a no." value="4"> <input type="number" id="te5" placeholder="enter a no." value="5"> </div> <!-- Y轴数据输入区 --> <div> <input type="number" id="te6" placeholder="enter a no." value="48"> <input type="number" id="te7" placeholder="enter a no." value="53"> <input type="number" id="te8" placeholder="enter a no." value="60"> <input type="number" id="te9" placeholder="enter a no." value="68"> <input type="number" id="te10" placeholder="enter a no." value="72"> </div> <!-- 图表标题与轴标签输入 --> <input type="text" id="title" placeholder="Enter chart title" value="Sample Chart"> <input type="text" id="xl" placeholder="X-axis label" value="X Values"> <input type="text" id="yl" placeholder="Y-axis label" value="Y Values"> <!-- 提交按钮 --> <button id="sub" pys-onClick="run">Submit</button> <!-- 图表输出容器 --> <div id="res"></div>
关键修复点说明
- 重置绘图状态:每次调用
run时执行plt.close('all')清除旧画布,创建新的fig和ax对象,彻底避免图表叠加问题。 - 数据类型转换:新增
get_numeric_value函数将输入的字符串值转为数值类型,确保numpy数组存储的是数值而非字符串,解决X轴刻度显示异常。 - 适配PyScript渲染:使用
FigureCanvasAgg将Matplotlib画布渲染为RGBA数组,再通过pyscript.write输出到页面,解决浏览器环境下的渲染适配问题。 - 饼图特殊处理:清除原有轴对象并重新创建子图,避免饼图与常规轴布局冲突。
内容的提问来源于stack exchange,提问作者Web Host
相关产品推荐
相关产品推荐

