Skip to content

Commit

Permalink
Add Image component
Browse files Browse the repository at this point in the history
  • Loading branch information
stevenpetryk committed Oct 20, 2024
1 parent 3501d8d commit 551b0fa
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 0 deletions.
26 changes: 26 additions & 0 deletions docs/app/guides/display/images/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { PropTable } from "components/PropTable"

import CodeAndExample from "components/CodeAndExample"
import ImageExample from "guide-examples/display/images/ImageExample"
import type { Metadata } from "next"

export const metadata: Metadata = {
title: "Vectors",
}

function Vectors() {
return (
<>
<p>
Images in Mafs are just wrappers around the SVG <code>image</code> element, with some
improvements. For exa
</p>

<CodeAndExample example={ImageExample} />

<PropTable of={"Vector"} />
</>
)
}

export default Vectors
2 changes: 2 additions & 0 deletions docs/app/guides/guides.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
TextIcon,
CursorArrowIcon,
PlayIcon,
ImageIcon,
} from "@radix-ui/react-icons"

import {
Expand Down Expand Up @@ -62,6 +63,7 @@ export const Guides: Section[] = [
{ title: "Plots", icon: FunctionIcon, slug: "plots" },
{ title: "Text", icon: TextIcon, slug: "text" },
{ title: "Vectors", icon: ArrowTopRightIcon, slug: "vectors" },
{ title: "Images", icon: ImageIcon, slug: "images" },
{ separator: true },
{ title: "Transform", icon: RotateCounterClockwiseIcon, slug: "transform" },
{ title: "Debug", icon: DebugIcon, slug: "debug" },
Expand Down
27 changes: 27 additions & 0 deletions docs/components/guide-examples/display/images/ImageExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use client"

import {
Coordinates,
Debug,

Check failure on line 5 in docs/components/guide-examples/display/images/ImageExample.tsx

View workflow job for this annotation

GitHub Actions / lint

'Debug' is defined but never used
Image,
Mafs,
useMovablePoint,

Check failure on line 8 in docs/components/guide-examples/display/images/ImageExample.tsx

View workflow job for this annotation

GitHub Actions / lint

'useMovablePoint' is defined but never used
} from "mafs"

import mafs from "./mafs.png"

export default function VectorExample() {
return (
<Mafs viewBox={{ x: [-1, 7], y: [-1, 5] }}>
<Coordinates.Cartesian />
<Image
src={mafs.src}
anchor="cc"
x={2}
y={2}
width={2}
height={2}
/>
</Mafs>
)
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions src/display/Image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Anchor, computeAnchor } from "../math"

export interface ImageProps {
src: string
x: number
y: number
width: number
height: number
anchor?: Anchor
preserveAspectRatio?: string
svgImageProps?: React.SVGProps<SVGImageElement>
}

export function Image({
src,
x,
y,
width,
height,
anchor = "bl",
preserveAspectRatio,
svgImageProps,
}: ImageProps) {
const [actualX, actualY] = computeAnchor(anchor, x, y, width, height)

const scaleX = width < 0 ? -1 : 1

Check failure on line 26 in src/display/Image.tsx

View workflow job for this annotation

GitHub Actions / lint

'scaleX' is assigned a value but never used
const scaleY = height < 0 ? -1 : 1

Check failure on line 27 in src/display/Image.tsx

View workflow job for this annotation

GitHub Actions / lint

'scaleY' is assigned a value but never used

console.log(actualX - (width < 0 ? -width : 0))

Check failure on line 29 in src/display/Image.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected console statement

return (
<image
href={src}
x={actualX - (width < 0 ? -width : 0)}
y={actualY - (height < 0 ? -height : 0)}
width={Math.abs(width)}
height={Math.abs(height)}
preserveAspectRatio={preserveAspectRatio}
{...svgImageProps}
style={{
transform: [`var(--mafs-view-transform)`, `var(--mafs-user-transform)`, `scaleY(-1) `].join(
" ",
),
}}
/>
)
}
3 changes: 3 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export type { PointProps } from "./display/Point"
export { Vector } from "./display/Vector"
export type { VectorProps } from "./display/Vector"

export { Image } from "./display/Image"
export type { ImageProps } from "./display/Image"

export { Text } from "./display/Text"
export type { TextProps, CardinalDirection } from "./display/Text"

Expand Down
57 changes: 57 additions & 0 deletions src/math.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type Interval = [min: number, max: number]
export type Anchor = "tl" | "tc" | "tr" | "cl" | "cc" | "cr" | "bl" | "bc" | "br"

export function round(value: number, precision = 0): number {
const multiplier = Math.pow(10, precision || 0)
Expand All @@ -24,3 +25,59 @@ export function range(min: number, max: number, step = 1): number[] {
export function clamp(number: number, min: number, max: number): number {
return Math.min(Math.max(number, min), max)
}

/**
* Given an anchor and a bounding box (x, y, width, height), compute the x and y coordinates of the
* anchor such that rendering an element at those coordinates will align the element with the anchor.
*/
export function computeAnchor(
anchor: Anchor,
x: number,
y: number,
width: number,
height: number,
): [number, number] {
let actualX = x
let actualY = y

switch (anchor) {
case "tl":
actualX = x
actualY = -y
break
case "tc":
actualX = x - width / 2
actualY = -y
break
case "tr":
actualX = x - width
actualY = -y
break
case "cl":
actualX = x
actualY = -y - height / 2
break
case "cc":
actualX = x - width / 2
actualY = -y - height / 2
break
case "cr":
actualX = x - width
actualY = -y - height / 2
break
case "bl":
actualX = x
actualY = -y - height
break
case "bc":
actualX = x - width / 2
actualY = -y - height
break
case "br":
actualX = x - width
actualY = -y - height
break
}

return [actualX, actualY]
}

0 comments on commit 551b0fa

Please sign in to comment.