Case Study: Akaru 2019

In 2019, a new version of our Akaru studio website has been released.

After long discussions between developers and designers, we found the creative path we wanted to take for the redesign. The idea was to create a connection between our name Akaru and the graphic style. Meaning “to highlight” in Japanese, we wanted Akaru to transmit the light spectrum, the iridescence and reflections that light can have on some surfaces. 

The particularity of the site is the mixing of regular content in the DOM/CSS and interactive background content in WebGL. We’ll have a look at how we planned and decided on the visuals of the main effect, and in the second part will share a technical overview and show how the “iridescent oil” effect was coded.

Design of the liquid effect

In the following, we will go through our iteration process between design and implementation and how we decided on the visuals of the interactive liquid/oil effect.

Visual Search

After some in-depth research, we built an inspirational mood board inspired by 3D artists and photographers. We have therefore selected several colors, and used all the details present in the images of liquids we considered: the mixture of fluids, streaks of colors and lights.

Processus

We started to create our first texture tests in Photoshop using vector shapes, brushes, distortions, and blurs. After several tests we were able to make our first environmental test with an interesting graphic rendering. The best method was to first draw the waves and shapes, then paint over and mix the colors with the different fusion modes.

Challenges

The main challenge was to “feel” a liquid effect on the textures. It was from this moment that the exchange between designers and developers became essential. To achieve this effect, the developers created a parametric tool where the designers could upload a texture, and then decide on the fluid movements using a Flowmap. From there, we could manage amplitudes, noise speed, scale and a multitude of options.

Implementing the iridescent oil effect

Now we will go through the technical details of how the iridescent oil effect was implemented on every page. We are assuming some basic knowledge of WebGL with Three.js and the GLSL language so we will skip over commonly used code, like scene initialization.

Creating the plane

For this project, we use the OrthographicCamera of Three.js. This camera removes all perspective so we can create our plane without caring about the depth of it.

We will create our plane with a geometry which has the width of the viewport, and we get the height by multiplying the width of the plane by the aspect ratio of our texture:

const PLANE_ASPECT_RATIO = 9 / 16;

const planeWidth = window.innerWidth;
const planeHeight = planeWidth * PLANE_ASPECT_RATIO;

const geometry = new PlaneBufferGeometry(planeWidth, planeHeight);

We could keep the number of segments by default since this effect runs on the fragment shader. By doing so, we reduce the amount of vertices we have to render, which is always good for performance.

Then, in the shader we use the UVs to sample our texture:

vec3 color = texture2D(uTexture, vUv).rgb;

gl_FragColor = vec4(color, 1.0);

Oil motion

Now that our texture is rendered on our plane, we need to make it flow.

To create some movement, we sampled the texture with an offset two times with a different offset:

float phase1 = fract(uTime * uFlowSpeed + 0.5);
float phase2 = fract(uTime * uFlowSpeed + 1.0);

// mirroring phase
phase1 = 1.0 - phase1;
phase2 = 1.0 - phase2;

vec3 color1 = texture2D(
    uTexture,
    uv + vec2(0.5, 0.0) * phase1).rgb;

vec3 color2 = texture2D(
    uTexture,
    uv + vec2(0.5, 0.0) * phase2).rgb;

Then we blend our two textures together:

float flowLerp = abs((0.5 - phase1) / 0.5);
vec3 finalColor = mix(color1, color2, flowLerp);

return finalColor;

But we don’t want our texture to always flow in the same direction, we want some areas to flow up, some others to flow to the right, and so on. To achieve this, we used Flow Map or Vector Map, which look like this:

Example Flow Map

A flow map is a texture in which every pixel contains a direction represented as a 2d vector x and y. In this texture, the red component stores the direction on the x axis, while the green component stores the direction on the y axis. Areas where the liquid is stationary are mid red and mid green (you can find those areas on top of the map). In fact, the direction could be in two ways, for example on the x axis the liquid could go to the left or to the right. To store this information a red value of 0 will make the texture go to the left and a red value of 255 will make the texture go to the right. In the shader, we implement this logic like this:

vec2 flowDir = texture2D(uFlowMap, uv).rg;
// make mid red and mid green the "stationary flow" values
flowDir -= 0.5;

// mirroring phase
phase1 = 1.0 - phase1;
phase2 = 1.0 - phase2;

vec3 color1 = texture2D(
    uTexture,
    uv + flowDir * phase1).rgb;

vec3 color2 = texture2D(
    uTexture,
    uv + flowDir * phase2).rgb;

We painted this map using Photoshop and unfortunately, with all exports (jpeg, png, etc.), we always got some weird artefacts. We found out that using PNG resulted in the least “glitchy” exports we could obtain. We guess that it comes from the compression algorithm for exports in Photoshop. These artefacts are invisible to the eye and can only be seen when we use it as a map. To fix that, we blurred the texture two times with glsl-fast-gaussian-blur (one vertically and one horizontally) and blended them together:

vec4 horizontalBlur = blur(
    uFlowMap,
    uv,
    uResolution,
    vec2(uFlowMapBlurRadius, 0.0)
  );
vec4 verticalBlur = blur(
    uFlowMap,
    uv,
    uResolution,
    vec2(0.0, uFlowMapBlurRadius)
  );
vec4 texture = mix(horizontalBlur, verticalBlur, 0.5);

As you can see, we used glslify to import glsl modules hosted on npm; it’s very useful to keep you shader’s code split and as simple as possible.

Make it feel more natural

Now that our liquid flows, we can clearly see when the liquid is repeating. But liquid doesn’t flow this way in real life. To create a better illusion of a realistic flow movement, we added some turbulence to distort our textures. 

To create this turbulence we use glsl-noise to compute a 3D Noise in which x and y will be the UV downscaled a bit to create a large distortion, and Z will be the time elapsed since the first frame, this will create an animated seamless noise:

float x = uv.x * uNoiseScaleX;
float y = uv.y * uNoiseScaleY;

float n = cnoise3(vec3(x, y, uTime * uNoiseSpeed));

Then, instead of sampling our flow with the default UV, we distort them with the noise:

vec2 distordedUv = uv + applyNoise(uv);

vec3 color1 = texture2D(
    uTexture,
    distordedUv + flowDir * phase1).rgb;

...

On top of that, we use a uniform called uNoiseAmplitude to control the noise strength.

To observe how the noise influences the rendering, you can tweak it inside the “Noise” folder in the GUI at the top right of the screen. For example, try to tweak the “amplitude” value:

Adding the mouse trail

To add some user interaction, we wanted to create a trail inside the oil, like a finger pushing the oil, where the finger would be the user’s pointer. This effect consists of three things:

1. Computing the mouse trail

To achieve this we used a Frame Buffer (or FBO). I will not go very deep into what frame buffers are here but if you want to you can learn everything about it here

Basically, it will: 

  1. Draw a circle in the current mouse position
  2. Render this as a texture
  3. Store this texture
  4. Use this texture the next frame to draw on top of it the new mouse position
  5. Repeat

By doing so, we have a trail drawn by the mouse and everything run on the GPU! For this kind of simulations, running them on the GPU is way more performant than running them on the CPU.

2. Blending the trail with the flow map

We can use the frame buffer as texture. It will be a black texture, with a white trail painted by the mouse. So we pass our trail texture via uniform to our Oil shader and we can compute it like this:

float trail = texture2D(uTrailTexture, uv).r;

We use only the red component of our texture since it’s a grayscale map and all colors are equal.

Then inside our flow function we use our trail to change the direction our liquid texture flow:

flowDir.x -= trail;
flowDir.y += trail * 0.075;

3. Adding the mouse acceleration

When we move our finger in a liquid, the trail it will create depends on the speed our finger moves. To recreate this feeling we make the radius of the trail depending on the mouse speed: the faster the mouse will go, the bigger the trail will be.

To find the mouse speed we compute the difference between the damped and the current mouse position:

const deltaMouse = clamp(this.mouse.distanceTo(this.smoothedMouse), 0.0, 1.0) * 100;

Then we normalize it and apply an easing to this value with the easing functions provided by TweenMax to avoid creating a linear acceleration.

const normDeltaMouse = norm(deltaMouse, 0.0, this.maxRadius);
const easeDeltaMouse = Circ.easeOut.getRatio(normDeltaMouse);

The Tech Stack

Here’s an overview of the technologies we’ve used in our project:

  • three.js for the WebGL part
  • Vue.js for the DOM part, it allows us to wrap up the WebGL inside a component which communicate easily with the rest of the UI 
  • GSAP is the tweening library we love and use in almost every project as it is well optimized and performant
  • Nuxt.js to pre-render during deployment and serve all our pages as static files

Prismic is a really easy to use headless CMS with a nice API for image formatting and a lot of others useful features.

Conclusion

We hope you liked this Case Study, if you have any questions, feel free to ask us on Twitter (@lazyheart and @colinpeyrat), we would be very happy to receive your feedback!

Case Study: Akaru 2019 was written by Jeremy Franzese and published on Codrops.

Motion Paths – Past, Present and Future

Making animations that “feel right” can be tricky.

When I’m stuck, I find Disney’s 12 principles of animation useful. They’re from the book ‘The Illusion of Life’ and although the book was written about hand-drawn character animation, a lot of the principles are relevant for animation on the web.

The 7th principle of animation is about arcs:

Most natural action tends to follow an arched trajectory, and animation should adhere to this principle by following implied “arcs” for greater realism.

In other words, animating along a curved path can make movement feel more realistic.

Straight lines are what browsers do best though. When we animate an element from one place to another using a translation the browser doesn’t take realism into account. It’ll always take the fastest and most efficient route.

This is where motion paths can come in handy. Motion paths give us the ability to move an element along a predefined path. They’re great for creating trajectories to animate along.

Use the toggle to see the paths.

See the Pen Alien Abduction- toggle by Cassie Evans (@cassie-codes) on CodePen.default

As well as being useful, they’re quite a lot of fun to play around with.

See the Pen Loop by Cassie Evans (@cassie-codes) on CodePen.default

So, how do you animate along a motion path?

I use GreenSock (GSAP) for most of my SVG animation and I made these demos using the newly released GSAP 3 and their MotionPathPlugin. So, if you want to skip to that bit, go ahead!

Otherwise let’s take a little journey through the past, present and future of motion path animation.

(Did someone say CSS motion paths?)

First, a little setup tip.

Make sure to keep the path and element you’re animating in the same SVG and co-ordinate space, otherwise things get a bit messy.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1300 800">
  <path class="path" d="M1345.7 2.6l2.4-4.4"/>
  <g class="rocket">
    ...
  </g>
</svg>

SMIL

If you google “SVG motion path animation”, you’re going to get a lot of hits talking about SMIL.

SMIL was the original proposed method for SVG animation. It included the ability to animate along a path using the <animatemotion> element.

It’s nice and declarative and currently the browser support is surprisingly good, covering all modern browsers except Edge and Opera Mini.

But, and this is a big but, the future of SMIL is uncertain, and has been for a while.

It was deprecated by Chrome a few years back and although they’ve now suspended that deprecation, implementations still vary and there’s no clear path towards cross-browser support.

Although it’s fun to play around with, SMIL isn’t very future-proof, so I’m only going to touch on it.

In order to animate along a path with the animateMotion element, you reference the path you want to animate along using path="..." and define the element you want to animate using xlink:href="#...":

<animateMotion 
    path="M20.2..."
    xlink:href="#rocket" 
    dur="10s" 
    rotate="auto"
    
/>

See the Pen loop SMIL by Cassie Evans (@cassie-codes) on CodePen.default

With SMIL effectively out of the picture, browser vendors are now focused on supporting modern alternatives like the CSS Motion Path Module.

CSS Motion Path Module

Attention: As of the time of writing, the examples in this section are experimental and best viewed in Chrome.

You can check out which features your browser supports in the demo below.

See the Pen Browser Support – CSS motion path module by Cassie Evans (@cassie-codes) on CodePen.default

If you’ve got all green smiley faces, you’re good to go. But you may have a sad face for offset-anchor. This is because this property is currently still experimental. It’s behind a flag in Chrome, meaning it’s not turned on by default.

You can choose to enable it by going to this URL in Chrome:

chrome://flags/#enable-experimental-web-platform-features

and enabling experimental web platform features.

This module is joint work by the SVG and CSS working groups, so unlike SMIL, we’ll be able to use CSS motion paths to animate both, HTML and SVG DOM elements. I love a CSS-only solution, so although it’s not ready to use in production (yet), this is pretty exciting stuff.

The motion path module consists of five properties:

  • offset (shorthand property for the following)
  • offset-path
  • offset-distance
  • offset-anchor
  • offset-rotate

offset-path

offset-path defines the path that we can place our element on. There are a few proposed values but path() seems to be the only one supported right now.

.rocket {
	offset-path: path('M1345.7 2.6l2.4-4.4');
}

path() takes a path string with SVG coordinate syntax, which may look scary, but you don’t have to write this out. You can create a path in a graphics editing program and copy and paste it in.

offset-distance

offset-distance specifies the position along an offset-path for an element to be placed. This can be either in pixels or as a percentage of the length of the path.

See the Pen Rocket – CSS motion path – offset-distance by Cassie Evans (@cassie-codes) on CodePen.default

offset-anchor

By default the element’s top left corner will be aligned with the path, but we can change this with offset-anchor.
offset-anchor behaves a lot like transform-origin. In fact if set to auto, it’s given the same value as the element’s transform-origin, so we can optionally use transform-origin for the same results.

Like transform-origin it accepts a position with x and y values, either as a percentage or a keyword like bottom or left.

Have a play with the values:

See the Pen Rocket – CSS motion path – offset anchor by Cassie Evans (@cassie-codes) on CodePen.default

offset-rotate

offset-rotate defines the direction the element faces on the path.

By default it’s set to auto and will rotate with the path. You can pass in an optional second value in degrees in order to tweak the direction of this rotation.

See the Pen Rocket – CSS motion path – offset-rotate – auto deg by Cassie Evans (@cassie-codes) on CodePen.default

If you want your element to face the same direction throughout, and not rotate with the path, you can leave out auto and pass in a value in degrees.

See the Pen Rocket – CSS motion path – offset-rotate – deg by Cassie Evans (@cassie-codes) on CodePen.default

These properties were renamed from motion to offset since this spec was proposed. This is because alone, these properties just provide another way to set the position and rotation of absolutely positioned elements. But we can create motion by using them in conjunction with CSS animations and transitions.

.rocket {
  offset-path: path('M20.2...');
  offset-anchor: 50% 50%;
  offset-rotate: auto;
  /*   if offset anchor isn't supported we can use transform-origin instead */
  transform-origin: 50% 50%;
  animation: move 8s forwards linear;
  transform-box: fill-box;
}

@keyframes move {
  from {
    offset-distance: 0%;
  }
  to {
    offset-distance: 100%;
  }
}

See the Pen Rocket – CSS motion path by Cassie Evans (@cassie-codes) on CodePen.default

Attention: SVG transform-origin quirks.

In this demo, I’m using a relatively new CSS property, transform-box.

This is to avoid a browser quirk that’s caught me out a few times. When calculating transforms and transform-origin, some browsers use the element’s bounding box as the reference box and others use the SVG viewbox.

If you set the value to fill-box the objects bounding box is used as the reference box.

And if you set the value to view-box the nearest SVG viewbox is used as the reference box.

You can see what happens to the center of rotation when we change it here:

See the Pen Rocket – CSS motion path – transform-box by Cassie Evans (@cassie-codes) on CodePen.default

GreenSock Animation Platform (GSAP)

While we wait for the CSS solution to be more widely implemented we’re in a bit of a motion path limbo. Thankfully there’s some JavaScript animation libraries that are bridging this gap.

I usually use GreenSock for SVG animation for a few reasons.

There are some cross browser quirks with SVG, especially with how transforms are handled. The folks at GreenSock go above and beyond to handle these inconsistencies.

Animation can also be a bit fiddly, especially when it comes to fine-tuning timings and chaining different animations together. GreenSock gives you a lot of control and makes creating complex animations fun.

They also provide some plugins that are great for SVG animation like DrawSVG, MorphSVG and MotionPathPlugin.

They’re all free to experiment with on Codepen, but some of the plugins are behind a membership fee. MotionPathPlugin is one of the free ones, and part of the new GSAP 3 release.

MotionPathPlugin gives you the ability to turn an SVG path into a motion path, or specify your own path manually. You can then animate SVG or DOM elements along that path, even if those elements are in a completely different coordinate space.

Here’s a demo with the necessary libraries added to start you off.

In order to use a plugin we have to register it, like this:

gsap.registerPlugin(MotionPathPlugin);

Then we can start animating. This is what a tween using the simplified GSAP 3 syntax looks like:

gsap.to(".rocket", {
	motionPath: ...
	duration: 5,
});

The name ‘tween’ comes from the world of hand-drawn animation, too.

Tweening is the process of generating intermediate frames between two images to give the appearance that the first image evolves smoothly into the second image.

That’s pretty much what a GSAP tween does. You feed in the element you want to animate, the duration, and the properties you want to target and the tween will figure out the in-between states.

The motionPath attribute can be used shorthand, and passed a path:

gsap.to(".rocket", {
	motionPath: "#path",
	duration: 5,
});

Or, if we want more control over the settings we can pass it an object of options:

gsap.to(".rocket", {
	motionPath: {
		path: "#path",
		align: "#path",
		autoRotate: true,
	},
	duration: 5,
});

See the Pen Rocket – GSAP motion path by Cassie Evans (@cassie-codes) on CodePen.default

Here are some of the properties we can control.

path

This defines the motion path we’re animating along, we can reference a path that exists in the document by using a selector,

motionPath: {
	path: "#path",
}

a string that contains SVG path data,

motionPath: {
	path: 'M125.7 655a9.4 9.4...',
}

an object containing an array of x and y co-ordinates to move between,

motionPath: {
	path: [{x: 100, y: 100}, {x: 300, y: 20}]
}

or a variable referring to one of these options:

const myPath = 'M125.7 655a9.4 9.4...'

motionPath: {
	path: myPath,
}

align

We can use this to align the element to the path, or other elements in the document by passing in a selector:

motionPath: {
	path: "#path",
	align: "#path"
}

We can also align the element to itself if we want the animation to start from the element’s current position.

motionPath: {
	path: "#path",
	align: "self"
}

In the next demo, the purple rocket is aligned to self and the green rocket is aligned to the path.

align: “self” is like moving the path to the element, rather than the element to the path.

See the Pen Rocket – GSAP motion path – align by Cassie Evans (@cassie-codes) on CodePen.default

By default, the element’s top left corner will be the center of rotation and alignment. In order to align the element accurately on the path you’ll need to set the element’s center of rotation, like this:

gsap.set(".rocket", { 
	xPercent: -50,    
	yPercent: -50,    
	transformOrigin: "50% 50%"
});

autoRotate

This is how we get our element to rotate along with the curvature of the path:

motionPath: {
	path: "#path",
	align: "#path"
	autoRotate: true,
}

We can also provide a number value. This will rotate along with the path, but maintain that angle relative to the path.

motionPath: {
	path: "#path",
	align: "#path"
	autoRotate: 90,
}

start & end

These properties let us define where on the path the motion should begin and end.

By default, it starts at 0 and ends at 1, but we can provide any decimal number:

motionPath: {
	path: "#path",
	align: "#path"
	autoRotate: true,
	start: 0.25,
	end: 0.75,
}

If you want the element to go backwards along the path, you can provide negative numbers.

See the Pen Rocket – GSAP motion path – align by Cassie Evans (@cassie-codes) on CodePen.default

immediateRender

If your element is starting off at a different position in the document and you want it to align with the path you might notice a jump as it moves from its position to the path.

See the Pen Rocket – GSAP motion path – align by Cassie Evans (@cassie-codes) on CodePen.default

You can fix force it to render immediately upon instantiation by adding immediateRender:true to the tween.

// animate the rocket along the path
gsap.to(".rocket", {
    motionPath: {
        path: "#path",
        align: "#path",
        autoRotate: true,
    },
    duration: 5,
    ease: "power1.inOut",
    immediateRender: true,
});

MotionPathHelper

Another super cool feature of the GSAP 3 release is the MotionPathHelper.

It enables you to edit paths directly in the browser! I found this really helpful, as I’m always going back and forth between the browser and my graphics editor.

Give it a go in the demo below. When you’re done, click “copy motion path” to copy the SVG path data to your clipboard. Paste the new path data into the d=”” attribute in the SVG code to update your path.

There are instructions on how to edit the path in the GSAP docs.

See the Pen Rocket – GSAP motion path – helper by Cassie Evans (@cassie-codes) on CodePen.default

GreenSock is a ton of fun to play around with!

There are a bunch of other features and plugins that when paired with motion path animation can be used to create really cool effects.

In this demo, DrawSVG is progressively showing the text path as some staggered elements animate along the path using MotionPathPlugin:

See the Pen Squiggle text animation by Cassie Evans (@cassie-codes) on CodePen.default

If you’ve had fun with these examples and want to explore GreenSock some more, Christina Gorton has written The New Features of GSAP 3 providing a practical overview.

GreenSock also have a great getting started guide.

Happy animating!

Motion Paths – Past, Present and Future was written by Cassie Evans and published on Codrops.

A Guide to Understanding GSAP JavaScript Animation

The use of animation is one of the best ways to make your website stand out. When smartly implemented, it can dazzle users and call attention to your most important content.

Of course, web animation has been around for years. But it’s really taken off with the spread of HTML5, CSS3 and JavaScript. Adding movement to your site has never been easier – or looked better.

Among the most powerful and fascinating tools for creating animation is the GreenSock Animation Platform (GSAP). It is known for its code-based approach and the ability to create some incredible special effects.

Today, we’ll cover the basics of GSAP. We’ll explain what it is and why you’d want to use it over other techniques. Plus, we’ll show you some examples of what it can do. Let’s get started!

GSAP Logo

Animation Through Code

At first, it may sound counterintuitive. Animation is a highly-visual art. So, why would we want to create this through code, rather than a traditional GUI-based tool? And what advantages does it have over good old CSS3 animation that has been built into the standard?

Here is why GSAP may be your best choice for creating animation:

It Works with the Elements Already on Your Page

Virtually any element on a page that can be accessed through JavaScript can be animated via GSAP. It doesn’t require you to create a separate canvas just for animation. CSS elements, SVG images and even JavaScript objects can be manipulated. This allows you to get up and running more quickly.

Compatibility Is Built In

GSAP has been tested across all the major web browsers – including legacy fare such as Internet Explorer. All of the browser-related tweaks and fallbacks have already been built into the platform. As such, you won’t have to create your own hacks to get things working across the board. This has all been done for you. If something’s not supported by a particular browser, it “silently” fails and won’t produce errors.

Meanwhile, GSAP also plays nicely with a variety of JavaScript frameworks and other technologies. So you can feel free to use it in conjunction with React, Vue or jQuery. Pretty much anything you’re already utilizing on your website is likely to be compatible.

It Uses Familiar, Easy to Learn Syntax

In addition to supporting CSS classes and IDs, GSAP also allows you to style animations using common properties. Formatting your code is a familiar mix of JavaScript and CSS. It even supports hex colors.

Fast Performance

Optimization is one of the key benefits of using GSAP. It offers a combination of HTML5 and JavaScript to allow for incredibly smooth animation. Support for hardware acceleration means that you’ll get great performance – even on slower devices. You can take a speed test to compare it other animation techniques such as jQuery and standard CSS.

Fine-Grain Control

When you start to explore GSAP, you may notice how detail-oriented it is. There is a large selection of built-in features that you can use to create virtually any type of animation. You can, for instance, choose to sequence multiple animations in a row or even randomize them. And that’s not even beginning to scratch the surface of what’s possible.

The documentation is deep and there are plenty of code examples you can use to get started. But to get a better understanding of what GSAP is capable of, this introductory video offers some terrific demonstrations:

There Are Plenty of Extras

The GSAP core package (which is free) is required to get started – and it’s plenty powerful. But there are also a number of available plugins that can help you do more. There are plugins for tasks like morphing elements, implementing physics and visually drawing motion paths.

It’s worth noting, however, that plugins are only available to paying members of “Club GreenSock”. This provides special access to both the plugins and extended commercial licensing.

Plus, features are constantly being added to core. Version 3, for example, offers up a simplified API, staggered tween animations and default animation properties, to name a few.

GSAP in Action

Now that we know a little bit more about what makes GSAP such a compelling option, let’s check out some examples of what it can do.

The great thing about each of the following snippets is that they are hosted on CodePen. So, you can feel free to study them, fork them and get a deeper understanding of how everything works.

Deconstructed Advanced Staggers Grid

See the Pen
GSAP 3 Deconstructed Advanced Staggers Grid
by Pete Barr (@petebarr)
on CodePen.

Crinkled Variable Font

See the Pen
GSAP 3 & ETC Crinkled Variable Font
by Pete Barr (@petebarr)
on CodePen.

Simple Camera

See the Pen
Simple Camera
by Blake Bowen (@osublake)
on CodePen.

GSAP 3 Radio

See the Pen
GSAP 3 Radio
by Kasper De Bruyne (@kdbkapsere)
on CodePen.

MotionPath Distribute

See the Pen
MotionPath Distribute GSAP 3.0
by Craig Roblewsky (@PointC)
on CodePen.

Heartbeat 3.0

See the Pen
Heartbeat 3.0
by Chris Gannon (@chrisgannon)
on CodePen.

Squiggle Text Animation

See the Pen
Squiggle text animation
by Cassie Evans (@cassie-codes)
on CodePen.

Cube Walk

See the Pen
GSAP 3 Cube Walk
by Pete Barr (@petebarr)
on CodePen.

Circle Packed Particles

See the Pen
Circle Packed Particles (GSAP3 + PixiJS v5)
by Steve Gardner (@ste-vg)
on CodePen.

DConstruct

See the Pen
DConstruct
by Cassie Evans (@cassie-codes)
on CodePen.

Powerful Animation Made Easier

When it comes to methods for animating your web projects, GSAP offers a rare combination. It’s more powerful than web standards alone, yet it is also optimized for performance. With most other libraries, you tend to sacrifice the latter to get the former.

This lack of compromise, combined with the shiny examples above, make it easy to see why so many developers have adopted GSAP. GreenSock says over 10 million sites are running the software, and one imagines that number will only continue to grow.

So, if you’re looking to up your animation game, give GSAP a try. You’ll be able to work your way up from basic movements all the way to high-end effects quicker than you may have thought possible.

The New Good Ol’ Days

Eighteen years into this game, I love to reminisce back to the good ol’ days of the early to mid-2000s when there was an explosion of creativity on the web. It felt fresh and unbridled, with boundaries expected to be pushed at every turn, and they were. This was mainly down to one thing, the thing of nightmares to some, Flash! It, of course, had some big inherent flaws, but love it or hate it, certainly helped pave the way for what we expected from the open web. Sure, it was probably a more drawn-out process than we'd hoped for, but with some savage new advancements made over the last few years, I now feel that things are really starting to get proper juicy.

Several things come to mind that get me excited these days in designing and developing for the web, some widely adopted now like SVG (even though technically old) and WebGL animation, which draw some obvious parallels to the Flash era. Certainly, CSS Grid stood up and made itself known, shouting from the parapets about how the shackles of layout are now a thing of the past. Kudos to awesome people like Rachel Andrew and Jen Simmons for their serious efforts in educating us mere mortals in this area, helping make the learning curve and adoption that bit more palatable and accessible.

Looking around today you can see how advancements like Grid have helped elevate the rise of more asymmetric layouts, with design styles like Brutalism design going through a bit of a trend over the last year or so. But over time it felt as though typography might have taken the back seat a tad with all the other successes happening in pushing the web forward. Now enter variable fonts 🥳

Variable fonts have certainly piqued my interest this past year or so. Not only do they give us the obvious boost in performance with fewer https requests and smaller sizes compared to the bundles of web fonts we all inject into our pages, but we also gain more control over typography in terms of readability and accessibility. Say goodbye to cheekily adding muddy sacrificial faux bold or italic styles to our CSS!

Taking this further, I feel that variable fonts have really unlocked the door to new creative possibilities that we're only just scratching the surface of. Having the ability to interpolate between different values of the axes just screams out for animation. We have the standardized set of 5 registered axes like font-weight, font-stretch, font-style, etc. which are straight forward enough to appreciate, but when it comes to custom axes via font-variation-settings, things start getting crazy and fun. Type designers can use the interpolation in custom axes to create some really off the wall things beyond, well… text. Just check out Typearture’s fab variable font experiments to see what I mean.

A few months back I was privileged to be invited to experiment with and test Greensock's newly released GSAP 3, which I’m also most definitely excited about. It boasts a new simplified API and 50+ new features, yet is only about half the file size as the previous version. This is currently my catnip though: layering GSAP on top of variable fonts in CodePen to create some lovely kinetic typography in the DOM. This kind of magic, until now I guess, has been more attributed to WebGL, Processing and After Effects. Now, throw some GSAP plugins on top again, and you can definitely create some very cool and unique stuff. I would suggest, however, that you use this new creative power of animating variable fonts in whichever way you do it sparingly, as reflow could become an issue with jank.

I'm excited to see what people will create using variable fonts over the next year as it becomes more widely adopted. Not just limited to typographic treatments in layouts, but also in terms of animation and micro-interactions. It looks like a big undertaking for designers in creating such fonts, but credit to them. I'm sure we'll be all the more appreciative. Thanks in advance type designers!

The post The New Good Ol’ Days appeared first on CSS-Tricks.

Collective #566



C566_gifolio

Gifolio

Gifolio is a brilliant collection of design portfolios presented using animated GIFs. By Roll Studio.

Check it out



C566_masks

Masks

An interactive presentation on masking techniques originally created for a Creative Front-end Belgium meetup hosted by Reed. By Thomas Di Martino.

Check it out




C566_mike

Supermaya

Supermaya is an Eleventy starter kit designed to help you add rich features to a blog or website without the need for a complicated build process.

Check it out


C566_darkmode

Dark Mode

Varun Vachhar shares the challenges he encountered when migrating from Jekyll to Gatsby related to dark mode.

Read it












C566_fresh

Fresh Folk

A beautiful mix-and-match illustration library of people and objects made by Leni Kauffman.

Check it out


C566_arcticvault

GitHub Archive Program

The GitHub Archive Program will safely store every public GitHub repo for 1,000 years in the Arctic World Archive in Svalbard, Norway.

Check it out



Collective #566 was written by Pedro Botelho and published on Codrops.

Collective #565




C565_2019

The 2019 Web Almanac

The Web Almanac is an annual state of the web report combining the expertise of the web community with the data and trends of the HTTP Archive.

Check it out







C565_gauges

Gauges

Amelia Wattenberger coded up a gauge example from Fullstack D3’s Dashboard Design chapter as a React component.

Check it out









C565_innerwolf

My Inner Wolf

An eclectic visual composition of our inner worlds: a project on absence epilepsy seizures by Moniker in collaboration with Maartje Nevejan.

Check it out








Collective #565 was written by Pedro Botelho and published on Codrops.

The New Features of GSAP 3

In this article we will explore many of the new features available from GSAP 3. The GreenSock animation library is a JavaScript library many front-end developers turn to because it can be easy to get started and you can create powerful animations with a lot of control. Now with GSAP 3 getting started with GreenSock is even easier.

Some of the new features we will cover in this article are:

  • GreenSock’s smaller file size
  • A Simplified API which offers a newer syntax
  • Defaults in timelines
  • Easier to use with build tools and bundlers
  • Advanced stagger everywhere!
  • Keyframes
  • MotionPath and MotionPath plugin
  • use of Relative “>” and “<” position prefix in place of labels in Timelines
  • The new “effects” extensibility
  • Utility methods

…and more!

GreenSock’s smaller file size

First and foremost the GreenSock library is now even smaller. It still packs all the amazing features I love, plus more (50+ more to be exact). But it is now about half the size! We will see some of the reasons below like the new simplified API but at its core GSAP was completely rebuilt as modern ES modules.

A Simplified API

With the new version of GreenSock we no longer have to decide whether we want to use TweenMax, TweenLite, TimelineMax, or TimelineLite. Now, everything is in a single simplified API so instead of code that looks like this:

TweenMax.to('.box', 1, {
  scale: 0.5,
  y: 20,
  ease: Elastic.easeOut.config( 1, 0.3)
})

We can write this instead:

gsap.to(".box1",{
  duration: 1,
  scale: 0.5,
  y: 20     // or you can now write translateY: 20,
  ease: "elastic(1, 0.3)",
});

Creating Timelines is easier too. Instead of using new TimelineMax() or new TimelineLite() to create a timeline, you now just use gsap.timeline() (simpler for chaining).

Here is an example of the first syntax change. Note that the old syntax still works in GSAP 3 for backward compatibility. According to GreenSock, most legacy code still works great.

See the Pen GreenSock New vs Old syntax by Christina Gorton (@cgorton) on CodePen.dark

Duration

Previously, the animation’s duration was defined as its own parameter directly after the target element. Like this:

TweenMax.to('.box', 1, {})

With the new version, duration is defined in the same vars object as the rest of the properties you animate and therefore is more explicit.

gsap.to(".box",{
  duration: 2,
});

This adds several benefits such as improved readability. After working with and teaching GSAP for a while now, I agree that having an explicit duration property is helpful for anyone new to GreenSock and those of us who are more experienced. This isn’t the only thing the new API improves though. The other benefits will become more obvious when we look at defaults in timelines and the new Keyframes.

Defaults in timelines

This new feature of GSAP is really wonderful for anyone who creates longer animations with gsap.timeline(). In the past when I would create long animations I would have to add the same properties like ease, duration, and more to each element I was animating in a timeline. Now with defaults I can define default properties that will be used for all elements that are animated unless I specify otherwise. This can greatly decrease the amount of code you are writing for each timeline animation.

Let’s take a look at an example:

This Pen shows a couple of the new features in GSAP 3 but for now we will focus on the defaults property.

See the Pen Quidditch motionPath by Christina Gorton (@cgorton) on CodePen.dark

I use defaults in a few places in this pen but one timeline in particular shows off its power. At the beginning of this timeline I set defaults for the duration, ease, yoyo, repeat, and the autoAlpha property. Now instead of writing the same properties for each tween I can write it one time.

const moving = () => {
  let tl = new gsap.timeline({ 
    defaults: { 
      duration: .02,  
      ease: "back(1.4)", 
      yoyo: true, 
      repeat: 1, 
      autoAlpha: 1 
    }
  })
  tl.to('.wing1',{})
    .to('.wing2',{})
    .to('.wing3',{})
  
  return tl;
}

Without the defaults my code for this timeline would look like this:

const moving = () => {
  let tl = gsap.timeline()
  
  tl.to('.wing1',{
    duration: .02,  
    ease: "back(1.4)", 
    yoyo: true, 
    repeat: 1, 
    autoAlpha: 1
  })
  .to('.wing2',{
    duration: .02,  
    ease: "back(1.4)", 
    yoyo: true, 
    repeat: 1, 
    autoAlpha: 1
  })
  .to('.wing3',{
    duration: .02,  
    ease: "back(1.4)", 
    yoyo: true, 
    repeat: 1, 
    autoAlpha: 1
  })

  return tl;
}

That is around a 10 line difference in code!

Use of Relative > and < position prefix in place of labels in Timelines

This is another cool feature to help with your timeline animations. Typically when creating a timeline I create labels that I then use to add delays or set the position of my Tweens.

As an example I would use tl.add() to add a label then add it to my tween along with the amount of delay I want to use relative to that label.

The way I previously used labels would look something like this:

gsap.timeline()
  .add("s")
  .to(“.box1", { ... }, "s")
  .to(“.box2", { ... }, "s")
  .to(“.box3", { ... }, "s+=0.8")
  .to(“.box4", { ... }, "s+=0.8”);

See an example here.

With > and < you no longer need to add a label.

From the GreenSock docs:

"Think of them like pointers - "<" points to the start, ">" points to the end (of the most recently-added animation)."

  • "<" references the most recently-added animation's START time
  • ">" references the most recently-added animation's END time

So now a timeline could look more like this:

gsap.timeline()
  .to(“.box1", { ... })
  .to(“.box2", { ... }, "<")
  .to(“.box3", { ... }, "<0.8")
  .to(“.box4", { ... }, "<”);

And you can offset things with numbers like I do in this example:

See the Pen MotionPath GreenSock v3 by Christina Gorton (@cgorton) on CodePen.dark

Stagger all the things

Previously in GSAP to stagger animations you had to define it at the beginning of a tween with either a staggerTo(), staggerFrom(), or staggerFromTo() method. In GSAP 3 this is no longer the case. You can simply define your stagger in the vars object like this:

tl.to(".needle",{
  scale: 1,
  delay:0.5,
  stagger: 0.5 //simple stagger of 0.5 seconds
},"start+=1")

...or for a more advanced stagger you can add extra properties like this:

tl.to(".needle",{
  scale: 1,
  delay:0.5,
  stagger: {
    amount: 0.5, //  the total amount of time (in seconds) that gets split up among all the staggers. 
    from: "center" // the position in the array from which the stagger will emanate
  }
},"start+=1")

This animation uses staggers in several places. like the needles. Check out all the staggers in this pen:

See the Pen Cute Cactus stagger by Christina Gorton (@cgorton) on CodePen.dark

Easier to use with build tools and bundlers

When I have worked on Vue or React projects in the past working with GreenSock could be a little bit tricky depending on the features I wanted to use.

For example in this Codesandbox I had to import in TweenMax, TimelineMax and any ease that I wanted to use.

import { TweenMax, TimelineMax, Elastic, Back} from "gsap";

Now with GSAP 3 my import looks like this:

import gsap from "gsap";

You no longer have to add named imports for each feature since they are now in one simplified API. You may still need to import extra plugins for special animation features like morphing, scrollTo, motion paths, etc.

Keyframes

If you have ever worked with CSS animations then keyframes will be familiar to you.

So what are keyframes for in GreenSock?

In the past if you wanted to animate the same set of targets to different states sequentially (like "move over, then up, then spin"), you would need to create a new tween for each part of the sequence. The new keyframes feature lets us do that in one Tween!

With This property you can pass an array of keyframes in the same vars objects where you typically define properties to animate and the animations will be nicely sequenced. You can also add delays that will either add gaps (positive delay) or overlaps (negative delay).

Check out this example to see the keyframes syntax and the use of delays to overlap and add gaps in the animation.

See the Pen GreenSock Keyframes by Christina Gorton (@cgorton) on CodePen.dark

MotionPath and MotionPath helper plugin

One of the features I am most excited about is MotionPathPlugin and the MotionPathHelper. In the past I used MorphSVGPlugin.pathDataToBezier to animate objects along a path. Here is an example of that plugin:

See the Pen MorphSVGPlugin.pathDataToBezier with StaggerTo and Timeline by Christina Gorton (@cgorton) on CodePen.dark

But the MotionPathPlugin makes it even easier to animate objects along a path. You can create a path for your elements in two ways:

  • With an SVG path you create
  • Or with manual points you define in your JavaScript

The previous Quidditch pen I shared uses MotionPathPlugin in several places. First you need to register it like this:

//register the plugin
gsap.registerPlugin(MotionPathPlugin);

Note: the MotionPathHelper plugin is a premium feature of GreenSock and is available to Club GreenSock members but you can try it out for free on CodePen.

I used an SVG editor to create the paths in the Quidditch animation and then I was able to tweak them directly in the browser with the MotionPathHelper! The code needed to add the MotionPathHelper is this

MotionPathHelper.create(element)

Screen Shot 2019-11-13 at 4.52.09 PM

I then clicked "COPY MOTION PATH" and saved the results in variables that get passed to my animation(s).

Paths created with the MotionPathPlugin helper

const path = "M-493.14983,-113.51116 C-380.07417,-87.16916 -266.9985,-60.82716 -153.92283,-34.48516 -12.11783,-77.91982 129.68717,-121.35449 271.49217,-164.78916 203.45853,-70.96417 186.21594,-72.24109 90.84294,-69.64709   ",
      path2 ="M86.19294,-70.86509 C64.53494,-36.48609 45.53694,-13.87709 -8.66106,-8.17509 -23.66506,-40.23009 -30.84506,-44.94009 -30.21406,-88.73909 6.79594,-123.26109 54.23713,-91.33418 89.94877,-68.52617 83.65113,-3.48218 111.21194,-17.94209 114.05694,18.45191 164.08394,33.81091 172.43213,34.87082 217.26913,22.87582 220.68213,-118.72918 95.09713,-364.56718 98.52813,-506.18118  ",
      path3 = "M-82.69499,-40.08529 C-7.94199,18.80104 66.81101,77.68738 141.56401,136.57371 238.08201,95.81004 334.60001,55.04638 431.11801,14.28271 ",
      path4 = "M126.51311,118.06986 C29.76678,41.59186 -66.97956,-34.88614 -163.72589,-111.36414 -250.07922,-59.10714 -336.43256,-6.85014 -422.78589,45.40686 ";

Example of a path passed in to animation

const hover = (rider, path) => {
  let tl = new gsap.timeline();
  tl.to(rider, {
    duration: 1,
    ease: "rider",
    motionPath:{
      path: path,
    }
  })
  return tl
}

In this timeline I set up arguments for the rider and the path so I could make it reusable. I add which rider and which path I want the rider to follow in my master timeline.

.add(hover("#cho", path3),'start+=0.1')
.add(hover("#harry", path4),'start+=0.1')

If you want to see the paths and play around with the helper plugin you can uncomment the code at the bottom of the JavaScript file in this pen:

See the Pen Quidditch motionPath by Christina Gorton (@cgorton) on CodePen.dark

Or, in this pen you can check out the path the wand is animating on:

See the Pen MotionPath GreenSock v3 by Christina Gorton (@cgorton) on CodePen.dark

Effects

According the the GreenSock Docs:

Effects make it easy for anyone to author custom animation code wrapped in a function (which accepts targets and a config object) and then associate it with a specific name so that it can be called anytime with new targets and configurations

So if you create and register an effect you reuse it throughout your codebase.

In this example I created a simple effect that makes the target "grow". I create the effect once and can now apply it to any element I want to animate. In this case I apply it to all the elements with the class ".box"

See the Pen GreenSock Effects by Christina Gorton (@cgorton) on CodePen.dark

Utility methods

Lastly, I'll cover the utility methods which I have yet to explore extensively but they are touted as a way to help save you time and accomplish various tasks that are common with animation.

For example, you can feed any two similarly-typed values (numbers, colors, complex strings, arrays, even multi-property objects) into the gsap.utils.interpolate() method along with a progress value between 0 and 1 (where 0.5 is halfway) and it'll return the interpolated value accordingly. Or select a random() value within an array or within a specific range, optionally snapping to whatever increment you want.

Most of the 15 utility methods that can be used separately, combined, or plugged directly into animations. Check out the docs for details.

Below I set up one simple example using the distribute() utility which:

Distributes an amount across the elements in an array according to various configuration options. Internally, it’s what advanced staggers use, but you can apply it for any value. It essentially assigns values based on the element’s position in the array (or in a grid)

See the Pen GreenSock Utility Methods by Christina Gorton (@cgorton) on CodePen.dark

For an even more impressive example check out Craig Roblewsky's pen that uses the distribute() and wrap() utility methods along with several other GSAP 3 features like MotionPathPlugin:

See the Pen MotionPath Distribute GSAP 3.0 by Craig Roblewsky (@PointC) on CodePen.dark

That wraps up the features we wanted to cover in this article. For the full list of changes and features check out this page and the GreenSock docs. If you'd like to know what old v2 code isn't compatible with v3, see GreenSock's list. But there's not much as GSAP 3 is surprisingly backward-compatible given all the improvements and changes.

References

All of the Pens from this article can be found in this collection.

For more examples check out GreenSock's Showcase and Featured GSAP 3 Pens collection.

The New Features of GSAP 3 was written by Christina Gorton and published on Codrops.

Awesome Demos Roundup #10

It’s really hard for us to keep up with the incredible pace of web creatives who bring out fantastic demos and experiments. This collection is yet another attempt to showcase what we believe to be the most inspiring demos that were released in the past couple of weeks. With #codevember and the arrival of GSAP 3, there’s lots of wonderful demos we can indulge into. We hope you enjoy this little roundup and pamper the creative coder in you!

Mandelbrot in box-shadow

12_153828

GSAP 3 ETC Variable Font Wave

12_153858

CSS Whack-a-Mole

CSSWhack-a-Mole

react-three-fiber untitled game

react-three-fiberuntitledgame

Bringing text to life v4

Bringingtexttolifev4

A matter of gravity

Amatterofgravity

Web Graphics Experiments 32

WebGraphicsExperiments32

Saturn

Saturn

Credit Card Form

CreditCardForm

Synthwave

Synthwave

Web Graphics Experiments 33

WebGraphicsExperiments33

2 de Noviembre – Día de Muertos

2deNoviembre-DiadeMuertos

Generative Haunts

GenerativeHaunts

Wire Typo

WireTypo

rupee in threejs

rupeeinthreejs

circle packing

circlepacking

Voronoi Malonie

VoronoiMalonie

dune buggy

dunebuggy

seastorm

seastorm

Fast and Slow | Vintage Projector Animation

FastandSlowVintageProjectorAnimation

Inspect This Snake

InspectThisSnake

react-three-fiber demo

react-three-fiberdemo

PureCSS Lace

PureCSSLace

BenDover

BenDover

light

light

Steam spooky house

Steamspookyhouse

OK

OK

CSS Grid: Restaurant Website

RestaurantWebsite

Flocked

Flocked

GLSL STUDY 7

GLSLSTUDY7

Infinity Machine

12_185733

#codevember AI snake!

codevemberAIsnake

DConstruct

DConstruct

Awesome Demos Roundup #10 was written by Mary Lou and published on Codrops.

Collective #564











C564_pagesjs

Paged.js

A blog which advocates for innovative approaches to making books in browsers.

Check it out










C564_frontend

Rethinking the Front-end

Shane Yu provides perspectives around the problems and goals of front-end development and discusses how to think about Component Composition.

Read it


Collective #564 was written by Pedro Botelho and published on Codrops.

Awesome Demos Roundup #8

The past month has been full of creative experimentation including WebGL goodness and lots of exciting animations, variable fonts playfulness and CSS layout magic. There’s much to discover and learn from.

We hope you enjoy this demo collection and get inspired!

Strandbeest walk

Strandbeest-walk

Blurry

Blurry

Call to Action Hype Man

Call-to-Action-Hype-Man

Sphere of Boxes

Sphere-of-Boxes-_-three

Rainbow Animation (RAF + Responsive)

Rainbow-Animation-RAF–Responsive

Fork This Nav

Fork-This-Nav

Day/Night Ambient Light Animation

DayNight-Ambient-Light-Animation

Mitosis

Mitosis

Tunnel

Tunnel

Animated Verbs

Animated-Verbs

Tornado

Tornado

Animated Portrait w/ GSAP 2.0

Animated-Portrait-w-GSAP-20

Color this sofa! – SVG + Blend Mode trick

Color-this-sofa-–-SVG–Blend-Mode-trick

Polygon Tree

Polygon-Tree

Delaunay

Delaunay

Zdog Colour Tunnel

Zdog-Colour-Tunnel

Sorry not Sorry

Sorry-not-Sorry

Sloping heart

Sloping-heart

Stencil

Stencil

Calculating PI Using Raindrops

Calculating-PI-Using-Raindrops

Color Collision

Color-Collision

Sketchpad

Sketchpad

3D Switch animation

3D-Switch-animation

Sunbeams

Sunbeams

Exploding Points

Exploding-Points

Enigma machine

Enigma-machine

Energy

Energy

Animated Verbs II

Animated-Verbs-II

CSS Grid: Magazine Layouts

Screen-Shot-2019-09-11-at-14.47.42

Pixi Sprite Bubbles

Pixi-Sprite-Bubbles

burn

burn

Shaded islands

Shaded-islands

Order confirm animation

Order-confirm-animation

Fix posture

Fix-posture

Dissolve

DissolveShader

Awesome Demos Roundup #8 was written by Mary Lou and published on Codrops.

Collective #543








C543_reactlayout

React Layouts

Grab-and-go layouts for React including code examples for Rebass, Theme UI, or Emotion. By Brent Jackson.

Check it out


C543_ruffle

Ruffle

Ruffle is an Adobe Flash Player emulator written in the Rust programming language. Ruffle targets both the desktop and the web using WebAssembly.

Check it out














C543_svelte

Svelte tutorial

A tutorial that will teach you everything you need to know to build fast, small web applications easily with Svelte.

Check it out


C543_null

Introducing nushell

The introduction of a new shell, written in Rust that draws inspiration from the classic Unix philosophy of pipelines and the structured data approach of PowerShell.

Read it


Collective #543 was written by Pedro Botelho and published on Codrops.

Draggable Image Strip

Today we’d like to share a little draggable experiment with you. The idea is to show a strip of differently sized images that can be dragged. When clicking and holding to drag, a title element appears and the images get scaled. This separates the images and gives the whole thing an interesting look. When a number gets clicked, the same separation happens and then the images fly up. Another larger version of the images slides in from the bottom.

The animations are powered by TweenMax and we use Dave DeSandro’s Draggabilly.

Attention: Note that the demo is experimental and that we use modern CSS properties that might not be supported in older browsers.

The initial view looks as follows:

DraggableImageStrip_01

When we click to drag the image strip, we show the title:

DraggableImageStrip_02

When clicking on a number, we slide the images up and show a larger view with some content:

DraggableImageStrip_03

Here’s a preview of the whole thing in motion:

DraggableImageStrip.2019-06-11 11_54_43

We hope you enjoy this experiment and find it useful!

References and Credits

Draggable Image Strip was written by Mary Lou and published on Codrops.

Pulling Apart SVGs with Reusable WebGL Components Using React-three-fiber

We will be looking at how to pull apart SVGs in 3D space with Three.js and React, using abstractions that allow us to break the scene graph into reusable components.

React and Three.js, what’s the problem?

My background in the past had more to do with front-end work than design, and React has been my preferred tool for a couple of years now. I like it because it pretty much maps the way i think. The ideas in my head are puzzle-pieces, which in React turn to composable components. It makes prototyping faster, and from a visual/design standpoint, it’s even fun, because it allows you to play around without repercussions. If everything is a self-contained lego-brick, you can rip it out, place it here, or there, and observe the result from different angles and perspectives. Especially for visual coding this can make a difference.

The problems that arise when handling programming tasks in an imperative way are always the same. Once we have created a sufficiently complex dependency-graph then things tend to be cobbled together, which causes the whole to be less flexible. Adding, updating or deleting items in sync with state and other operations can get complex. Orchestrating animations makes it even worse, because now you need to await animations to conclude before you continue with other operations and so on. Without a clear component-model it can be a reasonable challenge to keep it all together.

We run into this when working with user interfaces, as well as when creating scenes with Three.js, which can lend to especially unwieldy structures as it forces us to create a ton of objects that we have to track, mutate and manage. But React can solve that, too.

Think of React as a standard that defines what a component is and how it functions. React needs a so called “reconciler” to tell it what to do with these components and how to render them into a host. The browsers dom is a host, hence the react-dom package, which instructs React about the dom. React-native is another one you may be familiar with, but really there are dozens, reaching into all kinds of platforms, from AR, VR, console shells to, you guessed it, Three.js. The reconciler we will be using in this tutorial is called react-three-fiber, it renders components into a Three.js scene graph. Think of it as a portal into Three.js.

Let’s build!

Setting up the scene

Our portal into Three.js will be react-three-fiber’s “Canvas” component. Everything that goes in there will be cast into Three.js-native objects. The following will create a responsive canvas with some lights in it.

function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <spotLight intensity={0.5} position={[300, 300, 4000]} />
    </Canvas>
  )
}

Converting SVGs into shapes

Our goal is to extract SVG paths, once we have that we can display them in all sorts of interesting ways. We will be using fairly simple sketches for that, they won’t create many layers and the effect will be less pronounced.

example

In order to transform SVGs into shape geometries we use Three.js’s SVGLoader. The following will give us a nested array of objects that contains the shapes and colors. We collect the index, too, which we will be using to offset the z-vector.

const svgResource = new Promise(resolve =>
  new loader().load(url, shapes =>
    resolve(
      flatten(
        shapes.map((group, index) =>
          group.toShapes(true).map(shape => ({ shape, color: group.color, index }))
        )
      )
    )
  )
)

Next we define a “Shape” component which renders a single shape. Each shape is offset 50 units by its own index.

function Shape({ shape, position, color, opacity, index }) {
  return (
    <mesh position={[0, 0, index * 50]}>
      <meshPhongMaterial attach="material" color={color} />
      <shapeBufferGeometry attach="geometry" args={[shape]} />
    </mesh>
  )
}

All we are missing now is a component that maps through the shapes we have created. Since the resource we have created is a promise we have to await its resolved state. Once it has loaded, we wrote it into the local component state and forward each shape to the “Shape” component we have just created.

function Scene() {
  const [shapes, set] = useState([])
  useEffect(() => void svgResource.then(set), [])
  return (
    <group>
      {shapes.map(item => <Shape key={item.shape.uuid} {...item} />)}
    </group>
  )
}

This is it, our canvas shows an offset SVG.

Adding animations

If you wanted to animate Three.js you would most likely do it manually and use tools like GSAP. And since we want to animate elements that go in and out you need to have some system in place that orchestrates it, which is not an easy task to pull off.

Here comes the nice part, we are rendering React components and that opens up a lot of possibilities. We can use pretty much everything that exists in the eco system, including animation and transition tools. In this case we use react-spring.

Really all we need to do is convert out shapes into a transition-group. A transition group is something that watches state for changes and helps to retain and transition old state until it can be safely removed. In react-springs case it is called “useTransition”. It takes the original data, shapes in this case, keys in order to identify changes in the data-set, and a couple of lifecycles in which we can define what happens when state is added, removed or changed.

The following takes care of everything. If shapes are added, they will transition into the scene in a trailed motion. If shapes are removed, they will transition out.

const transitions = useTransition(shapes, item => item.shape.uuid, {
  from: { position: [0, 50, -200], opacity: 0 },
  enter: { position: [0, 0, 0], opacity: 1 },
  leave: { position: [0, -50, 10], opacity: 0 },
})

return (
  <group>
    {transitions.map(({ item, key, props }) => <Shape key={key} {...item} {...props} />)}
  </group>
)

useTransition creates an array of objects which contain generated keys, the data items (our shapes) and animated properties. We spread everything over the Shape component. Now we just need to prepare that component to receive animated values and we are done.

react-spring exports a little helper called “animated”, as well as a shortcut called “a”. If you extend any element with it, it will be able to handle these properties. Basically, if you had a div, it would become a.div, if you had a mesh, it now becomes a.mesh.

I hope you had fun! You will find detailed explanations for everything in the respective docs for react-three-fiber and react-spring. The full code for the original demo can be found here.

Pulling Apart SVGs with Reusable WebGL Components Using React-three-fiber was written by Paul Henschel and published on Codrops.

Collective #494








C494_svgicon

Iconsvg

A tool to simplify the process of finding and generating common SVG icons for your project.

Check it out




C494_amino

Amino

A live CSS editor for writing user style sheets. Customize your favorite sites, save and sync your styles.

Check it out










Screen-Shot-2019-02-21-at-16.09.50

An in-depth journey into how Node works. By Jamie Corkhill.

Read it






Collective #494 was written by Pedro Botelho and published on Codrops.