Skip to content

Commit

Permalink
feat: add animation to hero background (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fran McDade authored and Fran McDade committed Sep 9, 2024
1 parent 527cf4a commit be33439
Show file tree
Hide file tree
Showing 24 changed files with 509 additions and 149 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { smokeLightest } from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import {
smokeLightest,
smokeMain,
} from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import styled from "@emotion/styled";
import {
Section,
Expand All @@ -8,6 +11,7 @@ import {

export const StyledSection = styled(Section)`
background-color: ${smokeLightest};
border-top: 1px solid ${smokeMain};
overflow: hidden;
`;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Fragment } from "react";
import {
FILL,
GRID_SIZE,
} from "../../../../../../../Layout/components/Hero/common/constants";
import {
ELEMENT_ID,
Height,
} from "../../../../../../../Layout/components/Hero/common/entities";
import {
getElementHref,
getFillUrl,
getViewBox,
} from "../../../../../../../Layout/components/Hero/common/utils";
import { BlueCircle } from "../../../../../../../Layout/components/Hero/components/Defs/BlueCircle/blueCircle";
import { BlueRect } from "../../../../../../../Layout/components/Hero/components/Defs/BlueRect/blueRect";
import { CoralPinkCircle } from "../../../../../../../Layout/components/Hero/components/Defs/CoralPinkCircle/coralPinkCircle";
import { SmokeCircle } from "../../../../../../../Layout/components/Hero/components/Defs/SmokeCircle/smokeCircle";
import { SmokeRect } from "../../../../../../../Layout/components/Hero/components/Defs/SmokeRect/smokeRect";
import { YellowRect } from "../../../../../../../Layout/components/Hero/components/Defs/YellowRect/yellowRect";

export interface HeroProps {
gridSize?: number;
height?: Height;
}

export const Hero = ({
gridSize = GRID_SIZE,
height = GRID_SIZE * 3,
}: HeroProps): JSX.Element => {
return (
<svg
fill={FILL.NONE}
height={height}
preserveAspectRatio="xMinYMin meet"
viewBox={getViewBox(gridSize, height)}
width="100vw"
xmlns="http://www.w3.org/2000/svg"
>
<SmokeRect gridSize={gridSize} />
<SmokeCircle gridSize={gridSize} />
<BlueRect gridSize={gridSize} />
<YellowRect gridSize={gridSize} />
<BlueCircle gridSize={gridSize} />
<CoralPinkCircle gridSize={gridSize} />
{[
ELEMENT_ID.PATTERN_SMOKE_RECT,
ELEMENT_ID.PATTERN_SMOKE_CIRCLE,
ELEMENT_ID.PATTERN_BLUE_RECT,
ELEMENT_ID.PATTERN_YELLOW_RECT,
].map((elementId) => (
<Fragment key={elementId}>
<rect
fill={getFillUrl(elementId)}
height={height}
width="100vw"
x={0}
y={0}
/>
</Fragment>
))}
<use href={getElementHref(ELEMENT_ID.GROUP_BLUE_CIRCLE)} x={0} />
<use href={getElementHref(ELEMENT_ID.GROUP_CORAL_PINK_CIRLCLE)} />
</svg>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { smokeLightest } from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import styled from "@emotion/styled";

export const Section = styled.section`
background-color: ${smokeLightest};
position: fixed;
z-index: -1;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Hero } from "./components/Hero/hero";
import { Section } from "./sectionBranding.styles";

export const SectionBranding = (): JSX.Element => {
return (
<Section>
<Hero />
</Section>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { mediaTabletUp } from "@databiosphere/findable-ui/lib/styles/common/mixins/breakpoints";
import { white } from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import {
smokeMain,
white,
} from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import styled from "@emotion/styled";
import {
Section,
Expand All @@ -12,6 +15,7 @@ import {

export const StyledSection = styled(Section)`
background-color: ${white};
border-top: 1px solid ${smokeMain};
`;

export const SectionLayout = styled(DefaultLayout)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,14 @@ import {
mediaDesktopSmallUp,
mediaTabletUp,
} from "@databiosphere/findable-ui/lib/styles/common/mixins/breakpoints";
import {
inkLight,
smokeLightest,
} from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import { inkLight } from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import { textBodyLarge400 } from "@databiosphere/findable-ui/lib/styles/common/mixins/fonts";
import styled from "@emotion/styled";
import {
Section,
sectionGrid,
SectionLayout as DefaultLayout,
} from "../../section.styles";

export const StyledSection = styled(Section)`
background: url("/hero/hero.svg") 0 0 repeat, ${smokeLightest};
`;

export const SectionLayout = styled(DefaultLayout)`
${sectionGrid};
align-content: flex-end;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Button } from "@mui/material";
import { ROUTES } from "../../../../../../../routes/constants";
import { Section } from "../../section.styles";
import {
Head,
Headline,
SectionLayout,
StyledSection as Section,
Subhead,
SubHeadline,
SubHeadlinePositioner,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { white } from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import {
smokeMain,
white,
} from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import { textBodySmall500 } from "@databiosphere/findable-ui/lib/styles/common/mixins/fonts";
import styled from "@emotion/styled";
import { Chip as MChip } from "@mui/material";
Expand All @@ -10,6 +13,7 @@ import {

export const StyledSection = styled(Section)`
background-color: ${white};
border-top: 1px solid ${smokeMain};
`;

export const SectionLayout = styled(DefaultLayout)`
Expand Down

This file was deleted.

7 changes: 7 additions & 0 deletions app/components/Layout/components/Footer/footer.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Footer } from "@databiosphere/findable-ui/lib/components/Layout/components/Footer/footer";
import { smokeLightest } from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import styled from "@emotion/styled";

export const StyledFooter = styled(Footer)`
background-color: ${smokeLightest};
`;
36 changes: 36 additions & 0 deletions app/components/Layout/components/Hero/common/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const ANIMATE_MOTION = {
begin: "1s",
dur: "40s",
repeatCount: "indefinite",
};

export const FILL = {
BLUE: "#28285B",
CORAL_PINK: "#FC5E60",
NONE: "none",
SMOKE: "#E1E3E5",
YELLOW: "#FEDC6E",
};

export const GRID_SIZE = 297;

export const SHAPE_HEIGHT = {
BLUE_CIRCLE: 18,
BLUE_RECT: 6,
CORAL_PINK_CIRCLE: 18,
YELLOW_RECT: 49,
};

export const SHAPE_WIDTH = {
BLUE_CIRCLE: 18,
BLUE_RECT: 49,
YELLOW_RECT: 6,
};

export const X_POSITION = {
BLUE_RECT: 100,
};

export const Y_POSITION = {
YELLOW_RECT: 200,
};
18 changes: 18 additions & 0 deletions app/components/Layout/components/Hero/common/entities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export enum ELEMENT_ID {
GROUP_BLUE_CIRCLE = "groupBlueCircle",
GROUP_BLUE_RECT = "groupBlueRect",
GROUP_CORAL_PINK_CIRLCLE = "groupCoralPinkCircle",
GROUP_SMOKE_CIRCLE = "groupSmokeCircle",
GROUP_SMOKE_RECT = "groupSmokeRect",
GROUP_YELLOW_RECT = "groupYellowRect",
PATTERN_BLUE_RECT = "patternBlueRect",
PATTERN_SMOKE_CIRCLE = "patternSmokeCircle",
PATTERN_SMOKE_RECT = "patternSmokeRect",
PATTERN_YELLOW_RECT = "patternYellowRect",
}

export type Height = number; // Should be a multiple of GRID_SIZE.

export enum PATTERN_UNIT {
USER_SPACE_ON_USE = "userSpaceOnUse",
}
101 changes: 101 additions & 0 deletions app/components/Layout/components/Hero/common/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { SHAPE_HEIGHT, SHAPE_WIDTH, X_POSITION, Y_POSITION } from "./constants";

/**
* Returns the path for the animateMotion element of the blue rectangle.
* @param gridSize - Grid size.
* @returns animate motion path.
*/
export function getAnimateMotionPathBlueRect(gridSize: number): string {
return `M 0,0 L -${X_POSITION.BLUE_RECT},0 L ${
gridSize - X_POSITION.BLUE_RECT - SHAPE_WIDTH.BLUE_RECT
},0 L 0,0`;
}

/**
* Returns the path for the animateMotion element of the yellow rectangle.
* @param gridSize - Grid size.
* @returns animate motion path.
*/
export function getAnimateMotionPathYellowRect(gridSize: number): string {
return `M 0,0 L 0,${
gridSize - Y_POSITION.YELLOW_RECT - SHAPE_HEIGHT.YELLOW_RECT
} L 0,-${Y_POSITION.YELLOW_RECT} L 0,0`;
}

/**
* Returns the transform for the animateMotion element of the blue or coral pink circle.
* @param pos - Position.
* @param gridSize - Grid size.
* @param gridShift - Grid shift.
* @returns animate motion transform.
*/
export function getAnimateMotionTransformCircle(
pos: number,
gridSize: number,
gridShift = 0
): string {
return `${pos} ${gridSize / 2 + gridSize * gridShift} ${gridSize / 2}`;
}

/**
* Returns the starting x position for the blue or coral pink circle.
* @param gridSize - Grid size.
* @param angle - Angle.
* @returns x position.
*/
export function calculateCircleXPosition(
gridSize: number,
angle: number
): number {
return gridSize / 2 + (gridSize / 2) * Math.cos(degreesToRadians(angle));
}

/**
* Returns the starting y position for the blue or coral pink circle.
* @param gridSize - Grid size.
* @param angle - Angle.
* @returns y position.
*/
export function calculateCircleYPosition(
gridSize: number,
angle: number
): number {
return gridSize / 2 - (gridSize / 2) * Math.sin(degreesToRadians(angle));
}

/**
* Returns radians from degrees.
* @param angle - Angle.
* @returns radians.
*/
function degreesToRadians(angle: number): number {
return (angle * Math.PI) / 180;
}

/**
* Returns element href for the given ID.
* @param id - Element ID.
* @returns href.
*/
export function getElementHref(id: string): string {
return `#${id}`;
}

/**
* Returns fill URL for the given ID.
* @param id - ID.
* @returns fill URL.
*/
export function getFillUrl(id: string): string {
return `url(#${id})`;
}

/**
* Returns the viewBox attribute for an SVG element.
* @param width - SVG width.
* @param height - SVG height.
* @returns view box.
*/
export function getViewBox(width: number, height: number): string {
return `0 0 ${width} ${height}`;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ANIMATE_MOTION, FILL, SHAPE_HEIGHT } from "../../../common/constants";
import { ELEMENT_ID } from "../../../common/entities";
import {
calculateCircleXPosition,
calculateCircleYPosition,
getAnimateMotionTransformCircle,
} from "../../../common/utils";

export interface BlueCircleProps {
gridSize: number;
}

export const BlueCircle = ({ gridSize }: BlueCircleProps): JSX.Element => {
return (
<defs>
<g id={ELEMENT_ID.GROUP_BLUE_CIRCLE}>
<circle
cx={calculateCircleXPosition(gridSize, 310)}
cy={calculateCircleYPosition(gridSize, 310)}
fill={FILL.BLUE}
r={SHAPE_HEIGHT.BLUE_CIRCLE / 2}
>
<animateTransform
{...ANIMATE_MOTION}
attributeName="transform"
from={getAnimateMotionTransformCircle(0, gridSize)}
to={getAnimateMotionTransformCircle(360, gridSize)}
type="rotate"
/>
</circle>
</g>
</defs>
);
};
Loading

0 comments on commit be33439

Please sign in to comment.