Skip to content

Commit

Permalink
Added more edge cases, and started refactoring. Everything appears to…
Browse files Browse the repository at this point in the history
… be working! Just rewriting comments and tidying up calculateNestedSVGViewBox
  • Loading branch information
SonicScrewdriver committed Aug 22, 2024
1 parent 5035f38 commit f9cec28
Showing 1 changed file with 61 additions and 44 deletions.
105 changes: 61 additions & 44 deletions packages/perseus/src/widgets/interactive-graphs/mafs-graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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 (
<GraphConfigContext.Provider
Expand Down Expand Up @@ -181,10 +148,10 @@ export const MafsGraph = (props: MafsGraphProps) => {
<svg
width={width}
height={height}
viewBox={viewBox}
viewBox={`${viewBoxSettings.x} ${viewBoxSettings.y} ${width} ${height}`}
preserveAspectRatio="xMidYMin"
x={x}
y={y}
x={viewBoxSettings.x}
y={viewBoxSettings.y}
>
{props.lockedFigures && (
<GraphLockedLayer
Expand All @@ -208,6 +175,56 @@ export const MafsGraph = (props: MafsGraphProps) => {
);
};

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;
Expand Down

0 comments on commit f9cec28

Please sign in to comment.