Giter Club home page Giter Club logo

mafs's Introduction

Mafs

Mafs is a set of opinionated React components for creating math visualizations.

Visit the docs →


Development

Development is done inside of the Next.js documentation site, which directly imports Mafs components from src/. To start the development server, run:

pnpm install
pnpm start

The version of pnpm in use can be viewed by checking the packageManager field of package.json. Using corepack to install pnpm will keep this up-to-date automatically. Mafs pins pnpm to a precise version to avoid spurious pnpm-lock.yaml changes.

Then visit localhost:3000.

Tests

Mafs uses unit, end-to-end, and visual regression testing to ensure consistency between updates. It takes literal screenshots of components as rendered by the browser, and compares them to a known "correct" screenshot. Two of the browsers may require a Mac to run (Safari and iOS Safari).

All examples on the documentation site are visually tested automatically—the test file is autogenerated.

pnpm test      # run both suites
pnpm test:unit # to run just the Jest tests
pnpm test:e2e  # to run Playwright (end-to-end and visual tests)
pnpm test -- --update-snapshots # to update the visual test baselines

mafs's People

Contributors

benchristel avatar ggcr avatar handeyeco avatar mesoptier avatar sritchie avatar stevenpetryk avatar zawie avatar zthxxx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mafs's Issues

CI is needed

Unsure whether to use GH Actions or CircleCI...

API documentation

  • Add TSDoc comments to all components and props
  • Spit out some kind of documentation to embed on the website, perhaps a Gatsby plugin can help out here

Polar coordinates

Cartesian coordinates aren't enough—gotta draw some circles too.

Add support for limiting panning

Zooming can currently be limited, but not panning. Limiting panning would be pretty easy—would just be a matter of limiting the extent to which the camera matrix can be translated in Mafs.tsx.

Zooming

Let's let people pinch that canvas!

To increase margin between nav items

Need to increase the margin between the nav items because when we hover any item the background colour of the hover item gets coincide with the background colour of the active item

image

Automatically smooth function plots using a triangle area-based heuristic

A long time ago I read a cool developer blog post: Orbit Tessellation. It discusses how Kerbal Space Program 2 will adaptively increase the number of points used to draw an ellipse based on the position of the camera, thus solving an issue in KSP1 where orbits would appear blocky up close.

It would be interesting to try to use this approach when plotting functions. Especially parametric functions.

At the moment, FunctionGraph.OfX uses a naive approach: roughly every 2 pixels (really depending on zoom) gets a sample. You can increase the quality by setting quality="medium" or quality="high", which increase the subsampling to 1x and 2x, respectively.

FunctionGraph.Parametric uses an even more naive approach, just taking 1000 samples from t0 to tf, and allowing the user to increase the sample size if they want.

This approach is flawed, because it is completely undynamic. It doesn't care how sharp a function curves, or how long a parametric line is. A better approach would be to continually tesselate the line down to a reasonable limit, like how they show in the KSP2 blog post:

08_TriangleHeuristic.mp4

Movable point

Any example code to write a function y = f(x) and given a point on the function, move it along?

Eg: given y = 2x + 5 and the starting point (0,5), how would I use mafs to move the (0,5) point along the y = 2x + 5 function

Center + zoom viewport

Instead of having a viewport be based around "extents" (which isn't a great name imo), it would be nice to also allow users to say "center the viewport around this point, and zoom to this level". Perhaps setting an aspect ratio could be supported too.

Text shadow makes other text colors appears fuzzy

When specifying a color other than the default for the Text component, the edges of the text become fuzzy and appears bold

For example, here's what the default text color looks like:

<Text
    x={yTip[0]}
    y={yTip[1]}
    attach="e"
    attachDistance={25}
>
    Y
</Text>

image

And here's how it appears with a different color specified:

<Text
    x={yTip[0]}
    y={yTip[1]}
    attach="e"
    attachDistance={25}
    color={Theme.green}
>
    Y
</Text>

image

This happens because when a custom color is set, the Text component uses that color as its stroke instead of using the background color (line https://github.com/stevenpetryk/mafs/blob/7d86d79c916606c6ea8e48dad7fce69b1e5377b4/src/display/Text.tsx#LL66). However this causes the size of the text to inflate and become fuzzy because of the simulated shadow effect from the mafs-shadow class not playing nice with colours other than white.

Here's how the above example looks like with the stroke set back to mafs-bg:
image

Proposed solution: Update Text to still use the mafs-bg color as the text stroke, even when a custom color is specified.

Add a license

I'm interested in aping this library in vue, but without a license file I don't know whether that is permissible.

Themes/colors are completely undocumented

Themes are supported using CSS custom properties:

--mafs-bg: black;
--mafs-fg: white;

--mafs-origin-color: var(--mafs-fg);
--mafs-line-color: #555;
--grid-line-subdivision-color: #222;

--mafs-red: #f11d0e;
--mafs-orange: #f14e0e;
--mafs-yellow: #ffe44a;
--mafs-green: #15e272;
--mafs-blue: #58a6ff;
--mafs-indigo: #7c58ff;
--mafs-violet: #ae58ff;
--mafs-pink: #ee00ab;
export const theme = {
  foreground: "var(--mafs-fg)",
  background: "var(--mafs-bg)",

  red: "var(--mafs-red)",
  orange: "var(--mafs-orange)",
  green: "var(--mafs-green)",
  blue: "var(--mafs-blue)",
  indigo: "var(--mafs-indigo)",
  violet: "var(--mafs-violet)",
  pink: "var(--mafs-pink)",
}

But it might be nice to indicate how to swap out the Mafs default theme (right now, the main way is to overwrite these custom properties on .MafsView, as in the home page riemann sum example.

Line components

It's silly to expect people to model lines as functions (and it's wasteful computationally), so having a few primitives would be helpful:

  • Line through two points
  • Line at point and angle (from x-axis)
  • Line at point with slope
  • Vertical line (maybe)
  • Horizontal line (maybe)

Color schemes

Color schemes could be implemented as CSS variables or as React props, or both. Unclear which will be the most ergonomic for folks. Right now there are several CSS variables, but colors are placed randomly throughout the codebase, so that'll need to be fixed. It would also be great if there were some type of standard color scheme.

  • Decide on how to model color schemes
  • Consolidate all colors in to the color scheme
  • Define a nice palette of default colors to choose from (so that "blue" isn't CSS blue, but fancy blue)

Building mafs error

This is probably due to my inexperience running someone else's react project, and not specifically mafs, however...

Whenever I run the command "yarn start" I always get this error:

Screen Shot 2020-09-30 at 5 59 08 PM

All I ran was "yarn" before.

I have some edits I made on my fork of mafs that I want to test before making a pull request. However, I can't test at this injunction!

As a more general issue, it would be nice to include how to setup on the README.

More generically: how do I test my changes before making a pull request!

Bézier curves | Curved line

Points and Lines are first-class objects in mafs. I think curved lines should also be first class objects (I see an example on Bézier curves, perhaps there's a way to exact the curved lines from there, but it looks quite complicated).

Panning using the keyboard

Currently, users cannot pan using the keyboard. This is an easy fix, just something I neglected in the beta.

Vector Field Opacity Function

A lot of the times, vector arrows can get way too long. It would be nice to be able define a function, say opacity(x,y) that would return an opacity value for each arrow.

how to import css properly

I read official doc and
put
@import "mafs/index.css";

into index.css but

Failed to compile

./src/index.css (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-4-1!./node_modules/postcss-loader/src??postcss!./src/index.css)
Error: Can't resolve 'mafs/index.css' in '/Users/plato/dev/math_tutorial/vector_test/src'

How to import css?

Flash of 1px wide canvas on initial render

Initial render: the <svg> is rendered with width={1}, causing it to appear very stretched for a single frame.
mafs stretched canvas

On the next frame: the useResizeObserver hook returns an actual value for the width and the canvas renders correctly.
mafs canvas

See https://react-mnnsnw.stackblitz.io. In this example I render a whole bunch of points to slow the rendering down and emulate a heavy visualization, such that the issue is more easily visible.

Besides looking a little bit janky, this can also cause significant performance issues for page loads, since the <Coordinates.Cartesian> component might render tens of thousands of lines and labels. This performance issue is the actual problem I'm facing in my project.


Potential solutions

  • I think the simplest solution is to just not render the <svg> on the first frame, before the resize observer is ready. This way the first actual render will have the correct dimensions.

  • If the user passes both width and height, it should be possible to omit the resize observer altogether and just use the provided dimensions. This is the approach used by other libraries (e.g. react-window) and also better matches the API of the <canvas> and <svg> elements.

    If you're interested in this solution, you might point users to the AutoSizer component from react-virtualized (also published as a standalone package: https://github.com/bvaughn/react-virtualized-auto-sizer). Their description makes it sounds like what you're looking for here:

    Many react-virtualized components require explicit dimensions but sometimes you just want a component to just grow to fill all of the available space. The AutoSizer component can be useful in this case.

Cartesian coordinates have hard-coded boundaries

The CartesianCoordinates component renders the grid pattern only out to some huge power of 10. Probably won't affect any early adopters, but should be fixed—I was just too lazy to do the math. Theoretically if you panned millions of pixels to a particular side, the grid would vanish.

Allow creation of custom elements

Internally, Mafs uses React Context to keep track of how "math-space" (x and y on the coordinate plane) maps to "pixel-space" (x and y in the SVG element). The contexts are ScaleContext, MapContext, CoordinateContext, and PaneContext. The usage of each should be documented. I also think the number of contexts might be able to be reduced, and the number of parameters in each object can be simplified using linear algebra (i.e., I can have a MatrixContext that just encapsulates the entire linear transformation in one array).

Informing users about accessibility standards

When building math visualizations, it's common to have mouse-based interactions. It's worth warning people, especially ed-tech people, that they must accommodate keyboard users to comply with various parts of WCAG.

Vector fields don't have arrows, just squares

To avoid doing annoying math (ironically), I draw little boxes at the tip of vector field vectors rather than proper triangles. I need to change that, just haven't been able to prioritize it.

Docs code examples have bad highlighting

For example, here's the docs:

image

Here is VS Code:

image

I should probably find a way to use VS Code's syntax highlighter/parser for these examples. All these regex-based highlighters seem to suck for the most part.

Error: export 'vec' (imported as 'vec') was not found in 'mafs'

When importing vec, you may get the following error from your bundler:

export 'vec' (imported as 'vec') was not found in 'mafs'

This is a known error in Mafs version 0.8.0. Upgrade to 0.8.1 to fix it. Leaving this open in the meantime for visibility.

LaTeX

LaTeX could be implemented with a number of libraries. I'm partial to KaTeX, and it's what the original demo page uses, but there are certainly others.

Not sure how sophisticated peoples' LaTeX would get.

Leaving out the integration for now. If anything it'll be implemented as a separate file, like:

import { Latex, latex } from "mafs/latex"

<Latex expression={latex`\frac{1}{2}`} />

(the latex template tag would be a wrapper around String.raw to avoid JavaScript escaping backslashes)

WebGL component

I think it'd be nice to add some sort of API for easily integrating webgl/threejs/react-three-fiber if someone wants to embed some really performance-intensive stuff into Mafs.

Much like the Mafs SVG stuff, this would really just be a matter of making sure that a WebGL canvas "has its bearings" and knows how to map things from coordinate space to pixel space.

An interesting idea would be to move Function and VectorField to WebGL to improve performance. VectorField would especially benefit. We do, however, lose server side rendering with that approach.

Side-note: I would never want Mafs to be pure WebGL, because it's really difficult to make that accessible. I enjoy how Mafs is keyboard accessible by default at the moment.

Intractable Elements

Hi I want to open a prompt for the users to change the points of a line or polygon manually. Currently there is no onClick functions for your elements.

Exported TypeScript types are all wrong

Parcel seems to be rolling up all exported TypeScript types into the mafs module. So you can write code like this:

import { OfY } from "mafs"

<OfY ... />

And TypeScript doesn't show any errors, but in reality, OfY is undefined at runtime (the correct way to use OfY is to import Plot and then use Plot.OfY).

To fix this, I've confirmed that API extractor does a better job at doing .d.ts rollup, so now I just have to figure out how to disable Parcel's type rollup.

Mafs is (ironically) not very good at plotting graphs

Plotting is a pretty hard problem. Mafs does a good job of plotting pretty mundane graphs, but as soon as you plot something like 1/x, problems become apparent.

Some better heuristics around evaluating functions would be great.

CodeAndExample: collapsable code is overflowing on Safari

Hi @stevenpetryk

Noticed that the Collapsable code from the Docs is overflowing in Safari. Check the attached images below.

Issue

The problem is that overflow: clip; is not supported for Safari 15.6.

MacOS

macOS Monterey 12.5

Safari Version

Version 15.6 (17613.3.9.1.5)

Captura de Pantalla 2023-01-10 a las 20 22 00

Google Chrome Version

Version 108.0.5359.124

Captura de Pantalla 2023-01-10 a las 20 23 37

Proposed solution

Setting overflow: auto by default works because the max-height property will crop the text either way.

Tested it on Safari 16.2 and it works too

Captura de pantalla 2023-01-10 a las 21 45 21

Not all elements are affected by Transform

It would be handy if CartesianCoordinates, Text, Functions, and VectorFields were affected by Transform.

CartesianCoordinates, VectorFields, and both Function types are currently not supported simply because they use the "pane context", which is Mafs' way of not computing offscreen elements. All these components only render roughly the area you're looking at. However, I'm no wizard and I feel like the linear algebra involved in doing the lazy evaluation in a transformed coordinate space would be really tough.

Text is not transformed just because I figured people would want to preserve the legibility of the text and only transform the anchor point. We could definitely transform the text itself though (or make it an option). Maybe something like <Text transformBehavior="anchor|distort" /> or something.

Required, but non exported Vector2 Type

Moveable point:
Screen Shot 2020-10-02 at 12 42 48 AM
Trying to import Vector2:
Screen Shot 2020-10-02 at 12 50 27 AM

I've been playing around implementing mafs in tsx instead of js, however, now that I am using tsx, useMoveablePoint requires a Vector2 type to be passed in, however, mafs doesn't export that type!

Vector markers are unnecessarily duplicated

Every vector defines its own marker with a unique ID, but all vectors have the exact same marker. This definition could be hoisted up to the main view to cut down on the number of elements that need to be rendered.

https://github.com/stevenpetryk/mafs/blob/main/src/display/Vector.tsx#L34-L46

Of course, it gets a little complicated when we start using colors... might need to experiment and see if the line's marker can inherit its color. Maybe it already does. idk.

Snap to Grid

Is it possible to snap moveable points only to the grid?

Function components

Need a better name than this to avoid ambiguity between JS/React and Mafs. Maybe FunctionPlot? Anyway, should have the following:

  • Function of x
  • Function of y
  • Parametric functions

One issue is that this library will only supports injective functions of y and x. Relations require some kind of solver, meaning things like non-parametrically defined circles, hyperbolas, solution curves, etc. will not be plottable.

At least a lot of calculus and below can be plotted with this.

Testing strategy

I'm trying to think of ways to write tests.

  • Snapshot testing could work, but I dislike it. It's flaky to small changes that have no visual effect.
  • Screenshot testing might be nice—Mafs is, after all, basically an SVG image. But I wonder if it's slow.
  • Interactive elements should have accessibility testing to make sure they're focusable, keyboard operable, etc.

Netlify build notifications

I need some way to be notified when the Netlify site fails to build. I don't think I want to add a pull request check, because Netlify takes forever to pick up GitHub's webhooks and build the site. I would rather be reactive.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.