From f9cec2809743a01d5c78c4a429e9d15364f9e2e4 Mon Sep 17 00:00:00 2001 From: Sarah Third Date: Thu, 22 Aug 2024 12:08:30 -0700 Subject: [PATCH] Added more edge cases, and started refactoring. Everything appears to be working! Just rewriting comments and tidying up calculateNestedSVGViewBox --- .../widgets/interactive-graphs/mafs-graph.tsx | 105 ++++++++++-------- 1 file changed, 61 insertions(+), 44 deletions(-) diff --git a/packages/perseus/src/widgets/interactive-graphs/mafs-graph.tsx b/packages/perseus/src/widgets/interactive-graphs/mafs-graph.tsx index 0091162421..0fab224348 100644 --- a/packages/perseus/src/widgets/interactive-graphs/mafs-graph.tsx +++ b/packages/perseus/src/widgets/interactive-graphs/mafs-graph.tsx @@ -2,6 +2,7 @@ import {View} from "@khanacademy/wonder-blocks-core"; import {UnreachableCaseError} from "@khanacademy/wonder-stuff-core"; import {Mafs} from "mafs"; import * as React from "react"; +import {range} from "underscore"; import AxisArrows from "./backgrounds/axis-arrows"; import AxisLabels from "./backgrounds/axis-labels"; @@ -55,47 +56,13 @@ export const MafsGraph = (props: MafsGraphProps) => { const [width, height] = props.box; const tickStep = props.step as vec.Vector2; - // We need to adjust the nested SVG viewbox based on the range of the graph - // in order to ensure that the graph is centered within the SVG and the clipping mask - let xMin = 0; - const totalXRange = - Math.abs(state.range[X][0]) + Math.abs(state.range[X][1]); - - // X RANGE ADJUSTMENTS - // If the x range is entirely negative, we need to adjust the xMin to be -width - if (state.range[X][1] === 0) { - xMin = -width; - } - - // If the x range is entirely positive, we need to adjust the xMin to be 0 - if (state.range[X][0] >= 0) { - xMin = 0 + (width / totalXRange) * Math.abs(state.range[X][0] + 1); - } - - // If the xMin is negative, we need to manually adjust - if (state.range[X][0] < 0) { - xMin = -(width / totalXRange) * Math.abs(state.range[X][0]); - } - - // Y RANGE ADJUSTMENTS - let yMin = -height; - const totalYRange = - Math.abs(state.range[Y][0]) + Math.abs(state.range[Y][1]); - - // If the y range is entirely positive, we want to subtract the e - if (state.range[Y][0] > 0) { - yMin = -height - (height / totalYRange) * Math.abs(state.range[Y][0]); - } - - // If the yMin is negative, we need to manually adjust - if (state.range[Y][0] < 0) { - yMin = -height + (height / totalYRange) * Math.abs(state.range[Y][0]); - } - - // Create the viewbox for the nested SVG - const viewBox = `${xMin} ${yMin} ${width} ${height}`; - const x = xMin; - const y = yMin; + // Calculate the viewBox for the nested SVG that contains + // the interactive elements and locked figures + const viewBoxSettings = calculateNestedSVGViewBox( + state.range, + width, + height, + ); return ( { {props.lockedFigures && ( { ); }; +const getRangeDiff = (range: vec.Vector2) => { + const [min, max] = range; + return Math.abs(max - min); +}; + +// We need to adjust the nested SVG viewbox min values based on the range of the graph +// in order to ensure that the graph is centered within the SVG and the clipping mask +const calculateNestedSVGViewBox = ( + range: vec.Vector2[], + width: number, + height: number, +) => { + // X RANGE + let xMin = 0; // When range.xMin is 0, we want to use 0 as the xMin value for the SVG + const totalXRange = getRangeDiff(range[X]); + const gridCellWidth = width / totalXRange; + + // If the x range is entirely positive, we need to adjust the xMin to be 0 + if (range[X][0] > 0) { + const leftAdjustment = gridCellWidth * Math.abs(range[X][0]); + xMin = leftAdjustment; + } + // If the xMin is negative, we need to manually adjust + if (range[X][0] < 0) { + xMin = -gridCellWidth * Math.abs(range[X][0]); + } + + // Y RANGE + let yMin = -height; // When yMin is 0, we want to use the full height of the SVG + const totalYRange = getRangeDiff(range[Y]); + const gridCellHeight = height / totalYRange; + + // If the y range is entirely positive, we want to subtract the height + // from the sum of the gridcell height and the min y value + if (range[Y][0] > 0) { + yMin = -height - gridCellHeight * Math.abs(range[Y][0]); + } + + // If the yMin is negative, we want to + if (range[Y][0] < 0) { + yMin = -height + gridCellHeight * Math.abs(range[Y][0]); + } + + // Create the viewbox for the nested SVG + return { + x: xMin, + y: yMin, + }; +}; + const renderGraph = (props: { state: InteractiveGraphState; dispatch: (action: InteractiveGraphAction) => unknown;