Skip to content

Commit

Permalink
Clean up + Fixing Safari Zoom bug + using KaTeX font
Browse files Browse the repository at this point in the history
  • Loading branch information
SonicScrewdriver committed Sep 4, 2024
1 parent d24ee14 commit e35ce3e
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 238 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@ import useGraphConfig from "../reducer/use-graph-config";

import type {Interval, vec} from "mafs";

// The size of the ticks and labels in pixels
const tickSize = 10;
const tickLabelSize = 14;

// Style for the ticks on the x and y axes
const tickStyle: React.CSSProperties = {
stroke: "black",
strokeWidth: 1,
};

// Common text attributes for the x and y axis labels
const commonTextAttributes: React.SVGAttributes<SVGTextElement> = {
style: {
fontSize: `${tickLabelSize}px`,
fontFamily: "KaTeX_Main", // We're using the KaTeX font as MathJax has Safari issues
},
stroke: "white",
strokeWidth: 5,
paintOrder: "stroke",
};

const YGridTick = ({y, range}: {y: number; range: [Interval, Interval]}) => {
// If the graph requires out-of-bounds labels, we want to make sure to set the
// coordinates to the edge of the visible range of the graph. Otherwise,
Expand Down Expand Up @@ -56,16 +69,8 @@ const YGridTick = ({y, range}: {y: number; range: [Interval, Interval]}) => {
<line x1={x1} y1={y1} x2={x2} y2={y2} style={tickStyle} />
{showLabel && (
<text
height={20}
width={50}
style={{
fontSize: `${tickLabelSize}px`,
fontFamily: "Mafs-MJXTEX",
}}
{...commonTextAttributes}
textAnchor={"end"}
stroke="white"
strokeWidth={5}
paintOrder="stroke"
x={xPositionText}
y={yPositionText}
>
Expand Down Expand Up @@ -121,16 +126,8 @@ const XGridTick = ({x, range}: {x: number; range: [Interval, Interval]}) => {
<line x1={x1} y1={y1} x2={x2} y2={y2} style={tickStyle} />
{
<text
height={20}
width={50}
style={{
fontSize: `${tickLabelSize}px`,
fontFamily: "Mafs-MJXTEX",
}}
{...commonTextAttributes}
textAnchor="middle"
stroke="white"
strokeWidth={5}
paintOrder="stroke"
x={xPositionText}
y={yPositionText}
>
Expand Down

This file was deleted.

103 changes: 7 additions & 96 deletions packages/perseus/src/widgets/interactive-graphs/backgrounds/grid.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {Coordinates, usePaneContext, useTransformContext, vec} from "mafs";
import {Coordinates} from "mafs";
import * as React from "react";

import {MAX, MIN, X, Y} from "../math";
import {X, Y} from "../math";

import type {GraphRange} from "../../../perseus-types";
import type {SizeClass} from "../../../util/sizing-utils";
import type {Interval} from "mafs";
import type {vec} from "mafs";

interface GridProps {
tickStep: vec.Vector2;
Expand All @@ -17,28 +17,6 @@ interface GridProps {
height: number;
}

/**
* lineLabelText get the text that should
* be displayed for a specific tick place
*
* @param {number} n the tick number
* @param {number} tickStep how frequently a label should appear
* @param {vec.Vector2} range the min/max range on the axis
*/
export const lineLabelText = (
n: number,
tickStep: number,
range: vec.Vector2,
): string => {
const [min, max] = range;
const isOnStep = n % tickStep === 0;
const isNegativeOne = n === -1;
const isMin = n === min;
const isMax = n === max;
const shouldRender = isOnStep && !isNegativeOne && !isMin && !isMax;
return shouldRender ? `${n}` : "";
};

/**
* axisOptions determine axis options for Mafs
*
Expand All @@ -60,78 +38,11 @@ const axisOptions = (
};
};

// Get the vertical adjustment for the grid clippig mask based on the range
const getVerticalClipAdjustment = (range: GraphRange) => {
const yMax = range[1][1];
// If the yMax is odd, less than or equal to 0, and not -1 (special case),
// then we need to adjust the grid by 6.6 units to accomodate the
// size of the axis arrows. Otherwise, we need to adjust by 0.5 units
// to accommodate for just the grid border.
return yMax <= 0 && yMax % 2 !== 0 && yMax !== -1 ? 6.6 : 0.5;
};

// Generate the clip path for the grid so that the
// grid lines are confined within the graph bounds
const getClipPath = (
viewTransform: vec.Matrix,
xPaneRange: Interval,
yPaneRange: Interval,
height: number,
width: number,
range: GraphRange,
) => {
// Get the true bounds of the SVG from mafs
const xMin = xPaneRange[0];
const yMax = yPaneRange[1];

// Adjust the necessary padding for the clipping path
// by the range of the graph and the graph bounds
const xPad = range[X][MIN] - Math.min(0, xMin);
const yPad = range[Y][MAX] - Math.max(0, yMax);

// Transform the padding to pixel coordinates
const pad = vec.transform([xPad, yPad], viewTransform);

// Calculate any necessary adjustments to the horizontal and vertical
// padding to account for the grid border lines and axis arrows
const horizontalAdjustment = range[0][0] > 0 ? 0 : -0.5;
const verticalAdjustment = getVerticalClipAdjustment(range);

// Combine the padding and adjustments to get the coordinates for the clip path,
// while also adding 1 to the width and height to account for the grid border.
const rectTop = pad[1] + verticalAdjustment - 1;
const rectBottom = pad[1] + height + verticalAdjustment;
const rectLeft = pad[0] + horizontalAdjustment;
const rectRight = pad[0] + width + horizontalAdjustment + 1;

return `path('M ${rectLeft} ${rectTop} H ${rectRight} V ${rectBottom} H ${rectLeft} Z')`;
};

export const Grid = (props: GridProps) => {
const {viewTransform} = useTransformContext();
const {xPaneRange, yPaneRange} = usePaneContext();

// Set up the clip path for the grid so that grid
// lines do not render outside the graph bounds
const clipPath = getClipPath(
viewTransform,
xPaneRange,
yPaneRange,
props.height,
props.width,
props.range,
);

return props.markings === "none" ? null : (
<g
style={{
clipPath: clipPath,
}}
>
<Coordinates.Cartesian
xAxis={axisOptions(props, X)}
yAxis={axisOptions(props, Y)}
/>
</g>
<Coordinates.Cartesian
xAxis={axisOptions(props, X)}
yAxis={axisOptions(props, Y)}
/>
);
};
29 changes: 20 additions & 9 deletions packages/perseus/src/widgets/interactive-graphs/mafs-graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,27 @@ export const MafsGraph = (props: MafsGraphProps) => {
>
{/* Svg definitions to render only once */}
<SvgDefs />
{/* Background layer */}
<Grid
tickStep={props.step}
gridStep={props.gridStep}
range={state.range}
containerSizeClass={props.containerSizeClass}
markings={props.markings}
{/* Cartesian grid nested in an SVG to prevent overflow */}
<svg
width={width}
height={height}
/>
viewBox={viewBox}
preserveAspectRatio="xMidYMin"
x={viewboxX}
y={viewboxY}
>
<Grid
tickStep={props.step}
gridStep={props.gridStep}
range={state.range}
containerSizeClass={
props.containerSizeClass
}
markings={props.markings}
width={width}
height={height}
/>
</svg>
{/* Axis Ticks, Labels, and Arrows */}
{
// Only render the axis ticks and arrows if the markings are set to a full "graph"
Expand All @@ -155,7 +166,7 @@ export const MafsGraph = (props: MafsGraphProps) => {
</>
)
}
{/* Nested SVG to prevent figures from overflowing the graph bounds */}
{/* Locked & Interactive elements nested an SVG to prevent overflow*/}
<svg
width={width}
height={height}
Expand Down
43 changes: 0 additions & 43 deletions packages/perseus/src/widgets/interactive-graphs/mafs-styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -216,49 +216,6 @@
.MafsView pattern g {
stroke: rgba(33, 36, 44, 0.32);
}
.axis-tick-labels {
font-size: 14px;
font-family: "Mafs-MJXTEX";
line-height: 1.5em;
/* Prevent labels from being selected, and from interfering with click and
* drag interactions on the graph. */
user-select: none;
pointer-events: none;
/* Prevent labels from covering up interaction points. */
z-index: -1;
}

.y-axis-tick-labels {
width: 1.75em;
display: flex;
flex-flow: column;
transform: translateX(calc(-100% - 0.5em));
position: absolute;
text-align: right;
}
.y-axis-right-of-grid {
transform: translateX(calc(50% + 0.5em));
}
.x-axis-tick-labels {
display: flex;
flex-flow: row;
flex-direction: row-reverse;
position: absolute;
transform: translateY(calc(50% - 0.25em));
}
.x-axis-top-of-grid {
transform: translateY(calc(-100% + 0.25em));
}

.y-axis-tick-labels span {
display: inline-block;
height: var(--y-axis-label-height, 20px);
}

.x-axis-tick-labels span {
text-align: center;
width: var(--x-axis-label-width, 20px);
}

.MafsView .angle-arc,
.MafsView .arc-right-angle {
Expand Down

0 comments on commit e35ce3e

Please sign in to comment.