Skip to content

Commit

Permalink
Implemented interactive and animated port project SVG illustration
Browse files Browse the repository at this point in the history
A static vector graphic that is currently placed in the port section of
the landing (`/`) page has been implemented as interactive animated
component. It uses a 3D depth effect for the port project's logos by
moving against the direction of the current mouse position where the
larger logos will move more to give the impression that they are closer.

For the interactive animation the awesome react-spring (1) project is
used which allows, like the fantastic and also already used react-pose
(2) library, to use spring-physics based animations.
The advantage of react-spring is that it bails out of the React renderer
to avoid unnecessary renders and instead uses native methods to get the
best performance even for complex animations.
It comes with first-class support for Hooks (3), a great and extensive
documentation and a lot of examples for inspirations (4).

References:
  (1) https://www.react-spring.io
  (2) https://popmotion.io/pose
  (3) https://www.react-spring.io/docs/hooks/basics
  (4) https://www.react-spring.io/docs/hooks/examples

GH-119
  • Loading branch information
arcticicestudio committed Feb 21, 2019
1 parent 8898013 commit 3161976
Show file tree
Hide file tree
Showing 7 changed files with 679 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <development@arcticicestudio.com>
* Copyright (C) 2018-present Sven Greb <development@svengreb.de>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";

import LogosLayerBottom from "./styled/LogosLayerBottom";
import LogosLayerMiddle from "./styled/LogosLayerMiddle";
import LogosLayerTop from "./styled/LogosLayerTop";
import Window from "./styled/Window";

const Svg = styled.svg`
display: block;
overflow: visible;
`;

const transformLogosBottom = (x, y) => `translate3d(${-x * 0.008}px, ${-y * 0.009}px, 0)`;
const transformLogosMiddle = (x, y) => `translate3d(${-x * 0.015}px, ${-y * 0.02}px, 0)`;
const transformLogosTop = (x, y) => `translate3d(${-x * 0.03}px, ${-y * 0.038}px, 0)`;

/**
* An interactive illustration with a 3D depth effect that reacts and animates floating port project logos based on the
* current mouse poiner position.
* The animation is computed with react-spring through the exported `useFloatingLogos` hook.
*
* @author Arctic Ice Studio <development@arcticicestudio.com>
* @author Sven Greb <development@svengreb.de>
* @since 0.9.0
* @see https://www.react-spring.io
*/
const PortProjectsWindow = ({ logoLayerTransformer, ...passProps }) => (
<Svg {...passProps} viewBox="0 0 1678.836 503.798" xmlns="http://www.w3.org/2000/svg">
<LogosLayerBottom style={{ transform: logoLayerTransformer(transformLogosBottom) }} />
<LogosLayerMiddle style={{ transform: logoLayerTransformer(transformLogosMiddle) }} />
<LogosLayerTop style={{ transform: logoLayerTransformer(transformLogosTop) }} />
<Window />
</Svg>
);

PortProjectsWindow.propTypes = {
logoLayerTransformer: PropTypes.func.isRequired
};

export default PortProjectsWindow;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <development@arcticicestudio.com>
* Copyright (C) 2018-present Sven Greb <development@svengreb.de>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import { useSpring } from "react-spring";

const calcWindowDimensions = (x, y) => [x - window.innerWidth / 2, y - window.innerHeight / 2];

/**
* A hook that provides calculated spring-physic values based on the current window dimensions.
*
* @author Arctic Ice Studio <development@arcticicestudio.com>
* @author Sven Greb <development@svengreb.de>
* @since 0.9.0
*/
export default function useFloatingLogos() {
const [{ xy }, set] = useSpring(() => ({
xy: [0, 0],
config: { mass: 10, tension: 800, friction: 140 }
}));

function calcFloatingLogos(x, y) {
return set({ xy: calcWindowDimensions(x, y) });
}

return { transformLogoLayer: xy.interpolate, calcFloatingLogos };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (C) 2018-present Arctic Ice Studio <development@arcticicestudio.com>
* Copyright (C) 2018-present Sven Greb <development@svengreb.de>
*
* Project: Nord Docs
* Repository: https://github.com/arcticicestudio/nord-docs
* License: MIT
*/

import PortProjectsWindow from "./PortProjectsWindow";
import useFloatingLogos from "./hooks/useFloatingLogos";

export { useFloatingLogos };
export default PortProjectsWindow;
Loading

0 comments on commit 3161976

Please sign in to comment.