You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Storybook中JSXGraph数轴如何保持1:1单位纵横比实现响应式设计

解决React+Storybook中JSXGraph响应式1:1单位比例问题

核心思路

放弃JSXGraph自带的keepAspectRatio属性,通过动态计算坐标范围+监听窗口resize的方式,手动控制画板的boundingbox,既保证容器宽度100%、高度固定400px,又维持x/y轴单位长度1:1的比例,同时避免内容溢出边界。

具体实现步骤

1. React组件代码实现

import React, { useEffect, useRef } from 'react';
import JXG from 'jsxgraph';

const ResponsiveJSXGraph = () => {
  const boardRef = useRef(null);
  const boardInstance = useRef(null);

  useEffect(() => {
    if (!boardRef.current) return;

    // 初始化画板逻辑
    const initBoard = () => {
      const container = boardRef.current;
      const containerWidth = container.offsetWidth;
      const fixedHeight = 400;

      // 计算最大可容纳的1:1单位范围:取宽/2、高/2中的较小值
      // 这里的"2"对应坐标范围[-maxUnit, maxUnit],可根据需求调整
      const maxUnit = Math.min(containerWidth / 2, fixedHeight / 2);

      // 初始化画板,禁用自带的比例控制
      boardInstance.current = JXG.JSXGraph.initBoard(boardRef.current, {
        boundingbox: [-maxUnit, maxUnit, maxUnit, -maxUnit], // [xmin, ymax, xmax, ymin]
        keepAspectRatio: false,
        showNavigation: false,
        zoom: { wheel: false }, // 禁用滚轮缩放避免比例混乱
        pan: { enabled: false } // 禁用平移,如需平移需额外处理比例
      });

      // 绘制示例数轴
      boardInstance.current.create('axis', [[0, 0], [1, 0]], { name: 'x轴' });
      boardInstance.current.create('axis', [[0, 0], [0, 1]], { name: 'y轴' });
    };

    initBoard();

    // 监听窗口resize,实时更新坐标范围
    const handleResize = () => {
      if (!boardInstance.current || !boardRef.current) return;
      const container = boardRef.current;
      const containerWidth = container.offsetWidth;
      const fixedHeight = 400;
      const maxUnit = Math.min(containerWidth / 2, fixedHeight / 2);

      // 更新画板的boundingbox,自动适配容器尺寸
      boardInstance.current.setBoundingBox([-maxUnit, maxUnit, maxUnit, -maxUnit]);
    };

    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
      boardInstance.current?.destroy();
    };
  }, []);

  return (
    <div 
      ref={boardRef} 
      style={{ 
        width: '100%', 
        height: '400px', 
        overflow: 'hidden', // 防止内容溢出容器
        border: '1px solid #eee' // 可选,方便查看容器边界
      }} 
    />
  );
};

export default ResponsiveJSXGraph;

2. Storybook配置

直接在stories文件中引入组件即可,无需额外配置:

import ResponsiveJSXGraph from './ResponsiveJSXGraph';

export default {
  title: 'JSXGraph/ResponsiveAxis',
  component: ResponsiveJSXGraph,
};

export const Default = () => <ResponsiveJSXGraph />;

3. 关键细节说明

  • 禁用keepAspectRatio:JSXGraph自带的该属性会强制画板整体等比例缩放,导致非正方形容器内的内容溢出,必须关闭。
  • 动态计算boundingbox:每次resize时根据容器的实际宽度和固定高度,计算出能完全容纳的最大1:1坐标范围,保证x/y轴单位长度一致。
  • 禁用缩放和平移:如果需要保留这类交互,需额外添加逻辑,确保操作时维持1:1的单位比例,避免失衡。
  • overflow: hidden:给容器添加该样式,可避免极端情况下的内容溢出(如计算误差)。

内容的提问来源于stack exchange,提问作者lena mashukova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:23:11