Skip to content

fix: AxisLabels module-global state and axis label zoom scaling - #548

Open
bewuwy wants to merge 6 commits into
mainfrom
worktree-fix-492-478-axis-labels
Open

bewuwy wants to merge 6 commits into
mainfrom
worktree-fix-492-478-axis-labels

Conversation

@bewuwy

@bewuwy bewuwy commented Sep 12, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes Fix AxisLabels module-global state and stop re-deriving the camera transform #492: AxisLabels.ts had mutable module-global camera-baseline state shared across every CanvasD3 instance, breaking split view. Baseline is now per-canvas state, passed explicitly into pure getXLabelX/getYLabelY. The duplicated 15/30 base-scale literal is now one constant (HALF_GRID_SIZE_2D/GRID_SIZE_2D), and the pixel/screen-unit conversion that used it is now shared too (CameraViewport.ts), instead of being re-derived separately in transformScene and AxisLabels.ts.
  • Fixes Axis labels are bad with zoom #478: axis labels only compensated for the initial zoom, so they grew/shrank as you zoomed. Latex2D gains a fixedScreenScale prop that counters live zoom via Projection2D.liveZoomK.
  • Also extended fixedScreenScale to tick numbers, the origin label, and gridline/tick stroke width (non-scaling-stroke), otherwise the title labels stayed fixed-size while everything around them kept scaling, which looked broken rather than fixed. Bumped AXIS_LABEL_FONT_SIZE since text was reported too small either way. Not asked for by Axis labels are bad with zoom #478 directly, but needed to make the fix actually look done.
  • Deduped the repeated fixedScreenScale/fontSize props across Axis.svelte's label call sites into one snippet.

This PR changes quite a lot how the applets look like, since now all the axis labels, ticks, etc are screen-size static.

…abels fixed-size under zoom

AxisLabels.ts held mutable module-global camera-baseline state that was
shared across every CanvasD3 instance, breaking split view (fixes #492).
Baseline is now per-canvas $state passed explicitly into the now-pure
AxisLabels functions; getYabelY is renamed to getYLabelY. The base-scale
constant (15/30, half/whole of GRID_SIZE_2D) is now a single named
export instead of being duplicated as a bare literal in four places.

Also fixes #478: axis-label text only compensated for the static initial
zoom, so it grew/shrank as the user interactively zoomed. Latex2D gains
an opt-in fixedScreenScale prop (used only by axis labels) that divides
the label's scale by the live zoom factor exposed via a new
'current-zoom-k' context.
@netlify

netlify Bot commented Sep 12, 2026

Copy link
Copy Markdown

Deploy Preview for openla-preview ready!

Name Link
🔨 Latest commit 027a3f5
🔍 Latest deploy log https://app.netlify.com/projects/openla-preview/deploys/6aa952fc4c912e000869b177
😎 Deploy Preview https://deploy-preview-548--openla-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Sep 12, 2026

Copy link
Copy Markdown

Screenshot diff report

263 applets changed visually vs main (threshold: >0.1% pixels).
43 skipped (3D/WebGL).

Applet % changed
/applet/matrix_operations/nilpotent 2.85%
/applet/complex_basics/complex_inversion 2.35%
/applet/detextras/orientation 1.79%
/applet/injectivity_and_surjectivity/injsurj-nonsurjex 1.61%
/applet/geom_lin_trans/sheartrans 1.54%
/applet/dot_product/perpendicularline 1.35%
/applet/dot_product/innerproduct_projectionvectorline 1.34%
/applet/vectors/rules 1.33%
/applet/complex_basics/complex_addition 1.32%
/applet/geom_lin_trans/reflect_in_r2 1.31%
/applet/dot_product/triangle_inequality 1.31%
/applet/geom_lin_trans/rotisdoublerefl 1.30%
/applet/lines_and_planes/parametric_vector_equation 1.28%
/applet/calculus/graphs_and_extreme_values/disadvantage_of_the_second_derivative_test 1.28%
/applet/lines_and_planes/vector_equation 1.26%
/applet/calculus/complex_numbers/triangle_inequalities 1.25%
/applet/calculus/graphs_and_extreme_values/critical_points 1.24%
/applet/calculus/graphs_and_extreme_values/absolute_value 1.22%
/applet/calculus/rational_functions/witch_of_Agnesi 1.21%
/applet/calculus/limits_at_a_point/sine_of_one_over_x 1.20%
/applet/injectivity_and_surjectivity/injsurj-injex 1.18%
/applet/calculus/definite_integrals/piecewise_function 1.18%
/applet/calculus/complex_numbers/adding_complex_numbers 1.18%
/applet/calculus/limits_at_a_point/visualisation_of_a_limit 1.14%
/applet/lines_and_planes/normal_equation_line 1.13%
/applet/eigenvalue_eigenvector/no_eigenvector 1.10%
/applet/calculus/graphs_and_extreme_values/extreme_value_theorem 1.10%
/applet/other/testing/diagonal_matrix 1.08%
/applet/injectivity_and_surjectivity/injsurj-injex-example3 1.07%
/applet/other/testing/advanced_house 1.04%
/applet/leastsquares/leastsquares 0.99%
/applet/calculus/limits_at_a_point/two_parabolas_and_an_oscillating_function 0.98%
/applet/calculus/limits_at_infinity/one_over_one_plus_e_to_the_minus_x 0.98%
/applet/leastsquares/bestlines_point_drag 0.97%
/applet/calculus/fundamental_theorem_of_calculus/error_function 0.96%
/applet/geom_lin_trans/proj_in_r2 0.94%
/applet/calculus/trigonometry/six_trigonometric_ratios 0.94%
/applet/injectivity_and_surjectivity/injsurj-injex-example2 0.92%
/applet/calculus/fundamental_theorem_of_calculus/integral_of_sine 0.91%
/applet/calculus/continuity/continuity_and_inverse 0.90%
/applet/leastsquares/bestlines_split_canvas 0.90%
/applet/calculus/fundamental_theorem_of_calculus/visualisation_2_of_part_1 0.90%
/applet/linear_combinations/linearcombinations 0.89%
/applet/dot_product/diagonal_parallelogram 0.88%
/applet/calculus/differentiability/failing_differentiability 0.88%
/applet/calculus/approximating_functions/taylors_inequality 0.86%
/applet/calculus/slopes_of_curves_in_R2/dropplet 0.86%
/applet/calculus/properties_of_functions/exponential_square_root 0.85%
/applet/calculus/integration/simple_methods_custom 0.85%
/applet/calculus/continuity/some_other_function 0.85%
/applet/calculus/graphs_and_extreme_values/local_extrema 0.85%
/applet/calculus/graphs_and_extreme_values/local_and_global_extrema 0.85%
/applet/calculus/integration_by_substitution/visualisation_4 0.80%
/applet/symmetric_matrices/quadratic_forms 0.77%
/applet/calculus/graphs_and_extreme_values/cauchy_mean_value_theorem 0.74%
/applet/calculus/homogeneous_problems_with_constant_coefficients/complete_mass-spring_system 0.74%
/applet/calculus/curves_in_R^2/a_parabola 0.74%
/applet/calculus/curves_in_R^2/types_of_parabolas 0.74%
/applet/calculus/curves_in_R^2/introduction_to_ellipses 0.73%
/applet/calculus/derivatives_of_inverse_functions/failure_of_inverse_function_theorem_2 0.73%
/applet/calculus/product_and_quotient_rule/differentiable_but_not_continuously_differentiable 0.73%
/applet/calculus/curves_in_R^2/introduction_to_hyperbolas 0.73%
/applet/calculus/curves_in_R^2/three_parts_of_the_folium_of_Descartes 0.72%
/applet/calculus/fundamental_theorem_of_calculus/visualisation_1_of_part_1 0.72%
/applet/calculus/fundamental_theorem_of_calculus/fresnel_integrals 0.72%
/applet/subspaces_in_rn/the_game 0.70%
/applet/calculus/limits_at_a_point/limit_of_x_squared_near_2 0.70%
/applet/injectivity_and_surjectivity/injsurj-injex-example 0.69%
/applet/calculus/complex_numbers/using_De_Moivre 0.69%
/applet/calculus/integration_by_substitution/visualisation_1 0.68%
/applet/calculus/properties_of_functions/odd_and_even_periodic_extensions 0.67%
/applet/calculus/slopes_of_curves_in_R2/unit_circle 0.67%
/applet/calculus/homogeneous_problems_with_constant_coefficients/damped_mass-spring_system 0.67%
/applet/calculus/graphs_and_extreme_values/classifying_critical_points 0.64%
/applet/differential/differential-equations 0.63%
/applet/other/testing/house 0.58%
/applet/calculus/graphs_and_extreme_values/second_derivative_test 0.57%
/applet/calculus/graphs_and_extreme_values/closed_interval_method_1 0.56%
/applet/calculus/approximating_functions/linearisation 0.55%
/applet/calculus/graphs_and_extreme_values/mean_value_theorem 0.55%
/applet/calculus/graphs_and_extreme_values/sum_of_two_arctan_functions 0.54%
/applet/calculus/approximating_functions/taylor_polynomial_of_order_2 0.53%
/applet/calculus/limits_at_infinity/limits_of_reciprocals 0.51%
/applet/calculus/properties_of_functions/stretching_shifting_and_reflecting_2 0.48%
/applet/calculus/limits_at_infinity/limit_of_arctan_at_infinity 0.46%
/applet/calculus/continuity/continuity_for_IVT_1 0.45%
/applet/calculus/integration_by_substitution/visualisation_3 0.43%
/applet/other/testing/function_plotting 0.43%
/applet/calculus/graphs_and_extreme_values/first_derivative_test 0.43%
/applet/calculus/homogeneous_problems_with_constant_coefficients/pendulum 0.43%
/applet/calculus/fundamental_theorem_of_calculus/proof_of_part_1 0.43%
/applet/calculus/graphs_and_extreme_values/roots_of_a_cubic_function 0.43%
/applet/calculus/integration/method_errors 0.42%
/applet/calculus/graphs_and_extreme_values/rolle's_theorem 0.42%
/applet/other/testing/axis_labels 0.42%
/applet/other/testing/arcs2d 0.41%
/applet/other/testing/animation_studio 0.41%
/applet/calculus/curves_in_R^2/parametrisation_of_quadratic_function 0.41%
/applet/calculus/graphs_and_extreme_values/increasing_and_decreasing 0.41%
/applet/other/testing/more_languages 0.39%
/applet/calculus/properties_of_functions/sum_of_periodic_functions_1 0.38%
/applet/calculus/integration_by_parts/indefinite_integral_2 0.38%
/applet/calculus/properties_of_functions/sum_of_periodic_functions_2 0.38%
/applet/calculus/graphs_and_extreme_values/necessity_of_continuity 0.38%
/applet/other/testing/canvas_scale 0.38%
/applet/dot_product/angleandprojection 0.37%
/applet/calculus/complex_numbers/visualisation_of_the_complex_plane 0.37%
/applet/appendix/complex_numbers 0.37%
/applet/calculus/limits_at_a_point/two_rational_functions 0.37%
/applet/calculus/integration_by_parts/indefinite_integral_3 0.37%
/applet/calculus/complex_numbers/polar_coordinates_3 0.36%
/applet/calculus/complex_numbers/polar_coordinates_2 0.36%
/applet/calculus/complex_numbers/polar_coordinates 0.36%
/applet/calculus/integration_by_parts/indefinite_integral_1 0.36%
/applet/calculus/properties_of_functions/sum_of_even_and_odd_functions 0.36%
/applet/calculus/functions_of_one_variable/absolute_value 0.36%
/applet/calculus/continuity/rational_function 0.36%
/applet/calculus/continuity/continuity_from_the_right 0.36%
/applet/calculus/properties_of_functions/quadratic_function 0.36%
/applet/calculus/functions_of_one_variable/two_implicit_curves 0.36%
/applet/calculus/slope_fields/building_a_slope_field 0.36%
/applet/calculus/properties_of_functions/odd_and_even_periodic_extensions_2 0.35%
/applet/calculus/complex_numbers/complex_conjugation 0.35%
/applet/calculus/limits_at_a_point/a_function_with_two_vertical_asymptotes 0.35%
/applet/calculus/functions_of_one_variable/linear_function 0.35%
/applet/calculus/complex_numbers/polar_coordinates_4 0.34%
/applet/calculus/integration/simple_methods 0.34%
/applet/calculus/differentiability/tangent_line_3 0.34%
/applet/calculus/curves_in_R^2/introduction_to_parabolas 0.34%
/applet/calculus/classifications_and_solutions/solution_of_an_initial_value_problem 0.34%
/applet/calculus/functions_of_one_variable/quadratic_function_2 0.34%
/applet/calculus/integration_by_substitution/visualisation_2 0.34%
/applet/calculus/continuity/some_function 0.34%
/applet/calculus/properties_of_functions/a_piecewise_function 0.34%
/applet/calculus/functions_of_one_variable/quadratic_function_1 0.34%
/applet/calculus/limits_at_a_point/piecewise_function 0.34%
/applet/calculus/complex_numbers/adding_trigonometric_functions 0.33%
/applet/calculus/inverse_functions/reflection_of_composite_function 0.33%
/applet/calculus/functions_of_one_variable/vertical_line_test_1 0.33%
/applet/calculus/continuity/illustration_of_IVT 0.33%
/applet/calculus/properties_of_functions/hyperbolic_functions 0.33%
/applet/calculus/trigonometry/angle_in_standard_position 0.33%
/applet/calculus/inverse_functions/polling_question_B 0.33%
/applet/calculus/inverse_functions/polling_question_C 0.33%
/applet/calculus/inverse_functions/graph_of_restricted_tangent_function 0.33%
/applet/calculus/inverse_functions/graph_of_restricted_sine_function 0.33%
/applet/calculus/limits_at_a_point/two_parabolas 0.33%
/applet/calculus/inverse_functions/reflection_of_sine_function 0.33%
/applet/calculus/inverse_functions/reflection_of_tangent_function 0.33%
/applet/calculus/inverse_functions/graph_of_restricted_cosine_function 0.33%
/applet/calculus/inverse_functions/polling_question_A 0.33%
/applet/calculus/inverse_functions/polling_question_F 0.33%
/applet/calculus/inverse_functions/reflection_of_cosine_function 0.32%
/applet/calculus/functions_of_one_variable/vertical_line_test_2 0.32%
/applet/calculus/inverse_functions/polling_question_D 0.32%
/applet/calculus/limits_at_a_point/sign_function 0.32%
/applet/symmetric_matrices/spectral_theorem 0.32%
/applet/calculus/inverse_functions/graph_of_tangent_function 0.32%
/applet/calculus/inverse_functions/graph_of_cosine_function_with_focus 0.32%
/applet/calculus/inverse_functions/polling_question_E 0.32%
/applet/calculus/inverse_functions/graph_of_cosine_function 0.32%
/applet/calculus/inverse_functions/graph_of_cotangent_function 0.32%
/applet/calculus/rational_functions/a_rational_function 0.32%
/applet/calculus/inverse_functions/graph_of_sine_function 0.32%
/applet/calculus/rational_functions/reciprocal_function 0.32%
/applet/calculus/limits_at_a_point/limit_of_sign_function_near_0 0.31%
/applet/calculus/functions_of_one_variable/implicit_curves 0.31%
/applet/calculus/differentiability/introduction_differentiability 0.31%
/applet/calculus/curves_in_R^2/a_simple_hyperbola 0.31%
/applet/calculus/limits_at_infinity/squeeze_theorem 0.31%
/applet/calculus/homogeneous_problems_with_constant_coefficients/undamped_mass-spring_system 0.30%
/applet/pts/distributions/central_limit_theorem 0.30%
/applet/pts/distributions/distributions 0.30%
/applet/calculus/slope_fields/a_slope_field 0.30%
/applet/calculus/slope_fields/sketching_in_a_slope_field 0.30%
/applet/calculus/template/template_applet 0.29%
/applet/calculus/inverse_functions/reflection_of_exponential_with_base_2 0.29%
/applet/calculus/inverse_functions/reflection_of_exponential_with_base_1_over_2 0.29%
/applet/calculus/derivatives_of_inverse_functions/failure_of_inverse_function_theorem 0.29%
/applet/calculus/properties_of_functions/sum_of_periodic_extensions 0.28%
/applet/calculus/continuity/continuity_for_IVT_2 0.28%
/applet/calculus/limits_at_a_point/square_root_function 0.28%
/applet/calculus/limits_at_infinity/sine_of_x_over_x_squared 0.28%
/applet/calculus/definite_integrals/piecewise_function_with_negative_and_positive_values 0.27%
/applet/calculus/definite_integrals/an_interval_training 0.27%
/applet/det_geometric/linearity_one 0.27%
/applet/calculus/approximating_functions/taylor_polynomials_of_the_exponential_function 0.27%
/applet/calculus/slopes_of_curves_in_R2/folium_of_Descartes 0.27%
/applet/calculus/continuity/investigating_continuity 0.27%
/applet/calculus/homogeneous_problems_with_constant_coefficients/two_distinct_real_roots 0.27%
/applet/linear_independence/linind_example_in_2d 0.27%
/applet/calculus/curves_in_R^2/folium_of_Descartes 0.26%
/applet/calculus/derivatives_of_inverse_functions/inverse_function_theorem 0.26%
/applet/calculus/trigonometry/addition_and_subtraction_formulas 0.26%
/applet/calculus/trigonometry/supplementary_angles 0.26%
/applet/calculus/trigonometry/negative_angles 0.26%
/applet/calculus/trigonometry/trigonometric_ratios_and_the_unit_circle 0.26%
/applet/calculus/homogeneous_problems_with_constant_coefficients/double_real_root 0.26%
/applet/calculus/trigonometry/complementary_angles 0.25%
/applet/calculus/riemann_sum/riemann_sum_2d_custom 0.25%
/applet/calculus/homogeneous_problems_with_constant_coefficients/two_non-real_roots 0.25%
/applet/calculus/properties_of_functions/fundamental_period 0.25%
/applet/calculus/riemann_sum/riemann_sum_2d 0.25%
/applet/calculus/limits_at_infinity/a_function_with_limit_2_at_infinity 0.25%
/applet/calculus/curves_in_R^2/definition_of_a_parabola 0.24%
/applet/calculus/definite_integrals/linear_function 0.24%
/applet/calculus/curves_in_R^2/proof_of_equation_of_parabola 0.24%
/applet/calculus/curves_in_R^2/vertical_line_test_for_the_unit_circle 0.23%
/applet/calculus/slopes_of_curves_in_R2/parametric_curve 0.23%
/applet/calculus/properties_of_functions/another_odd_function 0.23%
/applet/calculus/properties_of_functions/even_and_odd_extensions 0.23%
/applet/calculus/classifications_and_solutions/solution_of_another_initial_value_problem 0.23%
/applet/calculus/inverse_functions/reflection_of_linear_function 0.22%
/applet/calculus/limits_at_infinity/temperature_of_a_cauliflower 0.22%
/applet/calculus/curves_in_R^2/two_parametrisations_of_one_hyperbola 0.22%
/applet/calculus/indefinite_integrals/several_functions 0.22%
/applet/calculus/slope_fields/logistic_equation 0.22%
/applet/other/testing/vector_field 0.22%
/applet/calculus/functions_of_one_variable/newton's_law_of_universal_gravitation 0.22%
/applet/calculus/differentiability/tangent_line_2 0.22%
/applet/calculus/curves_in_R^2/vertical_line_test_for_two_unit_semi-circles 0.22%
/applet/calculus/graphs_and_extreme_values/sign_chart 0.22%
/applet/calculus/graphs_and_extreme_values/closed_interval_method_2 0.22%
/applet/calculus/differentiability/tan_h_greater_than_h 0.22%
/applet/calculus/functions_of_one_variable/heaviside_step_function 0.21%
/applet/calculus/continuity/finding_roots_with_IVT 0.20%
/applet/calculus/graphs_and_extreme_values/estimating_function_values 0.20%
/applet/calculus/functions_of_one_variable/ideal_gas_law 0.20%
/applet/calculus/slopes_of_curves_in_R2/vertical_tangent_line 0.20%
/applet/calculus/curves_in_R^2/parametrisation_of_the_unit_circle 0.20%
/applet/calculus/inverse_functions/reflection_of_square_root_function 0.20%
/applet/calculus/inverse_functions/reflection_of_quadratic_function 0.20%
/applet/calculus/properties_of_functions/odd_function 0.19%
/applet/calculus/complex_numbers/division_in_polar_coordinates 0.19%
/applet/calculus/indefinite_integrals/a_function 0.19%
/applet/calculus/continuity/electrical_circuit 0.19%
/applet/calculus/properties_of_functions/even_function 0.19%
/applet/calculus/complex_numbers/multiplication_in_polar_coordinates 0.19%
/applet/calculus/complex_numbers/complex_conjugation_in_polar_coordinates 0.18%
/applet/calculus/inverse_functions/reflection_of_restricted_polynomial 0.18%
/applet/calculus/properties_of_functions/sum_of_two_functions 0.18%
/applet/calculus/fundamental_theorem_of_calculus/mean_value_theorem 0.18%
/applet/det_geometric/linearity_two 0.18%
/applet/calculus/functions_of_one_variable/power_functions_even 0.18%
/applet/calculus/functions_of_one_variable/power_functions_odd 0.18%
/applet/calculus/properties_of_functions/product_of_two_functions 0.17%
/applet/calculus/continuity/continuity_of_sine_and_cosine 0.17%
/applet/calculus/definite_integrals/positive_continuous_function 0.17%
/applet/calculus/classifications_and_solutions/logistic_equation 0.17%
/applet/calculus/complex_numbers/a_sequence_for_Euler's_formula 0.16%
/applet/calculus/functions_of_one_variable/exponential_functions 0.16%
/applet/calculus/functions_of_one_variable/a_piecewise_defined_function 0.16%
/applet/calculus/limits_at_a_point/one_over_x_squared 0.16%
/applet/calculus/differentiability/tangent_line 0.16%
/applet/calculus/functions_of_one_variable/trigonometric_functions 0.16%
/applet/calculus/limits_at_a_point/some_function 0.16%
/applet/calculus/limits_at_a_point/rounding_to_integers 0.15%
/applet/calculus/curves_in_R^2/definition_of_an_ellipse 0.15%
/applet/calculus/properties_of_functions/stretching_shifting_and_reflecting_1 0.14%
/applet/calculus/continuity/investigating_continuity_2 0.14%
/applet/calculus/functions_of_one_variable/negative_powers 0.11%
/applet/calculus/trigonometry/standard_angles 0.11%
/applet/calculus/curves_in_R^2/two_parametrisations_of_one_ellipse 0.10%

Before/after/diff images are attached as the screenshot-diff workflow artifact on this run: https://github.com/PRIME-TU-Delft/Open-LA-Applets/pull/548/checks

…legate live-zoom to Projection2D

- getXLabelX/getYLabelY now take a single AxisLabelLayout object instead of
  6-7 positional params that always travelled together (Data Clumps), and
  share a normalizeAxisLabelLayout() preamble instead of repeating the
  guard/baseline/zoom derivation in both functions (Duplicated Code).
- Projection2D now carries the live interactive zoom factor (liveZoomK),
  so Latex2D reads it off the projection it already has instead of a
  separate 'current-zoom-k' Svelte context threaded through a closure and
  an `as` cast.
- cameraBaseline in CanvasD3 is now set once from the initial camera
  position instead of being lazily captured from whichever zoom transform
  happens to fire first, removing the remaining per-instance
  order-dependence.
Removed doc comments on AxisLabelLayout and normalizeAxisLabelLayout that
just restated the type/function name, and an unused svelte-ignore that
eslint flagged (cameraBaseline's initializer reads a plain let, not
$state, so state_referenced_locally never fires there). Ran prettier and
eslint clean.
…xt size

Axis tick number labels (and the origin "O") weren't passed
fixedScreenScale, so only the x/y axis title labels stayed put on
screen while tick numbers kept growing/shrinking with live zoom.
Applied fixedScreenScale to all of Axis.svelte's Latex2D calls so
tick numbers behave the same way.

Also bumped the shared axis label font size (new AXIS_LABEL_FONT_SIZE
constant, 1.3x the prior default) since both tick numbers and axis
labels were reported as too small; used consistently by Axis.svelte's
tick/origin labels and CanvasD3's xLabel/yLabel default.

Verified with Playwright against a local production build: effective
on-screen text scale (getScreenCTM) stays locked at 1.3 across rest,
zoom-in, and zoom-out for tick numbers and axis labels alike.
Axis labels now correctly stay a fixed screen size while zooming, but
gridlines, tick marks, and axis lines had their stroke-width specified
in world units, so they kept thickening as the user zoomed in -
eventually dwarfing the (now fixed-size) tick text next to them.

Added vector-effect="non-scaling-stroke" to all of Axis.svelte's grid,
tick-mark, and axis lines so their stroke stays a constant screen-pixel
width regardless of the ambient zoom transform - the same approach
Desmos/GeoGebra use for gridline chrome. stokeWidth()'s return values
and the new tick-mark width are now real pixel widths instead of
world-unit fractions, since non-scaling-stroke interprets stroke-width
in that space.

Verified with Playwright against a local production build: gridlines
render as thin, constant-width lines at rest and after zooming in,
instead of growing thick.
…creen-unit math

- Axis.svelte's 5 <Latex2D> axis-label call sites each repeated
  fixedScreenScale={true} + fontSize={AXIS_LABEL_FONT_SIZE} verbatim
  (Data Clump / Duplicated Code). Collapsed into one local axisLabel
  snippet that bakes in both defaults; call sites now only pass what
  differs (latex/position/alignX/alignY/color/offset).
- #492 asked for label placement to stop re-deriving the camera
  transform so it has a single owner. The constant (HALF_GRID_SIZE_2D)
  was already centralized, but the pixel<->screen-unit conversion
  itself was still hand-rolled independently in CanvasD3.svelte's
  transformScene (forward) and AxisLabels.ts's getYLabelY (inverse,
  recovering the same pixel-space pan for edge-margin math). Extracted
  both directions into new CameraViewport.ts (pixelDeltaToScreenUnit /
  screenUnitToPixelDelta) and pointed both call sites at it. Same
  arithmetic, reordered through one shared function instead of two
  independent formulas - existing AxisLabels.test.ts (including the
  split-view regression case) passes unchanged, confirming no
  behavioural difference.
@bewuwy
bewuwy marked this pull request as ready for review September 15, 2026 14:18
@bewuwy
bewuwy requested review from douden and smarlene September 15, 2026 14:19
@bewuwy bewuwy self-assigned this Sep 15, 2026

@douden douden left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a quick look, and also checked the diff-images.

To me it looks good 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix AxisLabels module-global state and stop re-deriving the camera transform Axis labels are bad with zoom

2 participants