Gooey FramerJS

Not too long ago Lucas Bebber wrote a blog post about using SVG filters for shape blobbing. His post was in response to this post, by Chris Coyier, which used CSS filters. The term shape blobbing, as used here, is really just talking about the gooey effect where two shapes kind of gooey-morph into a larger combined shape. As Chris said, think droplets of mercury on a surface.

example of effect

image from http://css-tricks.com/shape-blobbing-css/

It's a pretty interesting effect, and one that isn't quite as ubiquitous enough yet on the web to have become clich├ęd, but arguably in heavy use for native mobile interfaces. This gooey effect was one that I thought would be fun to play with after having just completed a FramerJS workshop with Jay Stakelon.

svg approach

Lucas points out several drawbacks with using CSS filters for the gooey effect, however when using Framer Studio there is one game-ending drawback with SVG filters: no support in Safari. Framer Studio uses an embedded Safari browser in its IDE (stated simply for brevity). While this effect does degrade well, the point of doing it is to see the effect.

css approach

CSS filters are supported pretty much in all browsers... Chrome, Firefox, iOS, Android, and most importantly for us while using Framer Studio, Safari.

Chris explains the workings of the effect very well so I won't reproduce that here. What we need to talk about is how to get this into Framer.

Style

The layer.style property in Framer is what we'll be using to apply the css filter.

Just like in the codepen experiment, we need our dot layers inside a container.

We'll create our container layer first

# create the container
container = new Layer
    width: 800
    height: 800
    backgroundColor: "#fff"
    
container.center()

# apply the css filter
container.style = {"-webkit-filter":"contrast(90)"}

Notice that we're only using the vendor prefix -webkit for filter. Since we're inside of Framer Studio and only worried about seeing it in the IDE we don't have need to specify more.

Now let's build our dot layers

# create our circle layer
dot1 = new Layer
    width: 100
    height: 100
    backgroundColor: "#f00f0f"
    borderRadius: "100%"

# copy the layer
dot2 = dot1.copy()

# place the dots into the container
dot1.superLayer = container
dot2.superLayer = container
dot1.center()
dot2.center()

# apply the css filter
dot1.style = {"-webkit-filter":"blur(15px)"}
dot2.style = {"-webkit-filter":"blur(15px)"}

Again, notice we're only applying the vendor prefixed version.

That's it, we're done.

animate it

We'll need to animate the dots to see the effect though.

dot1.draggable.enabled = true

That's it, now we're done.

Now you can drag one dot around, playing with the gooey effect.

The entire file is here if you just want to copy and paste it into Framer Studio

Framer.Defaults.Animation =
  time: 1
  curve: "spring(100,10,0)"

dotStyle = {"-webkit-filter":"blur(15px)"}
containerStyle = {"-webkit-filter":"contrast(90)"}

container = new Layer
  width: 800
  height: 800
  backgroundColor: "#fff"

container.style = containerStyle
container.center()

dot1 = new Layer
  width: 100
  height: 100
  backgroundColor: "#f00f0f"
  borderRadius: "100%"
  opacity: 1

dot2 = dot1.copy()
dot1.superLayer = container
dot2.superLayer = container

dot1.style = dotStyle
dot2.style = dotStyle

dot1.center()
dot2.center()

dot1.originalFrame = dot1.frame
dot1.draggable.enabled = true

dot1.on Events.DragEnd, ->
  @animate
    properties:
      x: @originalFrame.x
      y: @originalFrame.y

That's it, now we're really done.

wrap up

While this is a fun effect to play with, the practical applications on the web might be questioned. Using CSS filters setting the colors exactly is a difficult affair (play with it, try it).

But it is fun, and if you're prototyping native mobile apps with Framer, it's a technique you might want to keep in your toolbox.

update

March 28, 2015
I added this code to a github repo which should make it more available to everyone. The coffeescript code has been converted (albeit quickly and therefore poorly) to vanilla Javascript and the example can be run in a Safari browser. Take a look here.