如何实现mpld3生成的HTML图表标记点随缩放动态调整大小?
问题描述
我写了一段Python脚本,用Matplotlib生成不同哈希算法与字符串长度的平均哈希时间对比图,再通过mpld3转成交互式HTML。目前图表里的标记点在HTML缩放时大小不变,想优化体验:
- 标记点随缩放级别动态调整:放大时缩小,缩小时放大
- 解决放大到最大级别时标记点不再继续缩小的问题
现有代码
import hashlib import random import string import time import matplotlib.pyplot as plt import multiprocessing import os from datetime import datetime import mpld3 algorithms = ['sha1', 'sha256', 'sha3_256'] string_lengths = [10, 25, 50, 75, 100] num_samples = 50000 random_seed = 42 random.seed(random_seed) custom_colors = ['#1f77b4', '#FFD700', '#2ca02c'] def generate_random_string(length): characters = string.ascii_letters + string.digits return ''.join(random.choice(characters) for _ in range(length)) def hash_string(input_string, algorithm): hash_func = hashlib.new(algorithm) hash_func.update(input_string.encode()) return hash_func.hexdigest() def hash_and_measure_avg_time(args): algorithm, random_strings = args num_samples = len(random_strings) start_time = time.time_ns() [hash_string(s, algorithm) for s in random_strings] end_time = time.time_ns() total_time = end_time - start_time return total_time / num_samples def main(): for i in range(10): num_cpus = multiprocessing.cpu_count() cpu_count = os.cpu_count() print(f"\nUsing {num_cpus} CPU cores for analysis") print(f"Number of CPU cores available: {cpu_count}") random_strings = {} for length in string_lengths: random_strings[length] = [generate_random_string(length) for _ in range(num_samples)] results = {} timestamp = datetime.now().strftime("%m-%d-%Y-%H-%M-%S") results_folder = f"results_{timestamp}" os.makedirs(results_folder, exist_ok=True) for algorithm in algorithms: results[algorithm] = {} print(f"\nTesting hashing algorithm: {algorithm}") with multiprocessing.Pool(processes=num_cpus) as pool: args = [(algorithm, random_strings[length]) for length in string_lengths] results_list = pool.map(hash_and_measure_avg_time, args) for length, result in zip(string_lengths, results_list): results[algorithm][length] = result time.sleep(1) plt.figure(figsize=(10, 6)) for i, (algorithm, avg_times) in enumerate(results.items()): avg_times = [avg_times[length] for length in string_lengths] plt.plot( string_lengths, avg_times, marker='o', markersize=4, label=algorithm, color=custom_colors[i] ) plt.title('Average Hashing Time vs. String Length') plt.xlabel('String Length') plt.ylabel('Average Hashing Time (ns)') plt.legend() plt.grid(True) interactive_plot = mpld3.fig_to_html(plt.gcf()) plot_filename = f"c_result_{timestamp}.html" with open(os.path.join(results_folder, plot_filename), 'w') as html_file: html_file.write(interactive_plot) if __name__ == "__main__": print("\n----- Welcome to the Hashing Performance Benchmark -----") main()
当前缩放效果
未缩放时

缩放后

最大缩放级别

解决方案
要实现标记点随缩放动态调整,需要给mpld3添加自定义JavaScript插件,监听缩放事件并调整标记点大小,同时设置大小限制避免过度缩小。
修改步骤:
- 在Python代码中,替换生成交互式HTML的部分,添加自定义插件:
将原来的interactive_plot = mpld3.fig_to_html(plt.gcf())替换为以下代码:
# 注册动态调整标记点大小的自定义插件 plugins = [mpld3.plugins.connect(plt.gcf(), mpld3.plugins.Plugin( "dynamicmarkersize", {}, js_code=""" var DynamicMarkerSize = function(fig, props){ var markers = fig.canvas.querySelectorAll(".mpld3-marker"); var originalRadius = []; // 保存每个标记点的原始半径 markers.forEach(function(marker){ originalRadius.push(parseFloat(marker.getAttribute("r"))); }); // 设置标记点的最小/最大半径限制 var minRadius = 1; var maxRadius = 8; // 监听缩放事件 fig.plugins.zoom.on("zoom", function(){ var scale = fig.zoom.scale; markers.forEach(function(marker, idx){ // 根据缩放比例反向调整半径 var newRadius = originalRadius[idx] / scale; // 限制半径范围,避免过度缩小或放大 newRadius = Math.max(minRadius, Math.min(maxRadius, newRadius)); marker.setAttribute("r", newRadius); }); }); }; mpld3.register_plugin("dynamicmarkersize", DynamicMarkerSize); """ ))] # 生成带插件的交互式HTML interactive_plot = mpld3.fig_to_html(plt.gcf(), plugins=plugins)
效果说明:
- 缩放时,标记点半径会根据当前缩放比例反向调整:放大(scale>1)时缩小半径,缩小(scale<1)时放大半径
- 通过
minRadius和maxRadius限制标记点的尺寸范围,解决最大缩放时标记点过度缩小的问题,同时避免缩小时标记点过大遮挡内容
内容的提问来源于stack exchange,提问作者user22734651
相关产品推荐
相关产品推荐

