Chamoy Creative is a marketing agency that is located in Texas. Chamoy, which is where the name of the agency came from, refers to a variety of savory sauces and condiments in Mexican cuisine made from pickled fruit. Eating fruit or candy dipped in gooey Chamoy sauce is a Mexican tradition.
For the visual of the brand, I created a gooey sauce effect for the website.
How I built it
1. Used Canvas Graphic
At first, I used an HTML5 Canvas drawing to make the drop shape. I wrote this code on a flight to Korea for a conference presentation I was giving. There aren’t many things to do on a flight, so it was great to focus on coding.
I put the coordinates of a random sized droplet on the screen and programmed it to drop down. I coded the shape of the sticky part and the shape of the falling drop.
The visual was not bad and the next step was the gooey effect. Since the sauce is sticky, I started to make this visual effect using code.
The easiest way to make a gooey effect is by using SVG filter. The advantage of SVG filter is that you can use HTML5 Canvas Graphic which is easy to use for drawing. The disadvantages are that it only works with some specific browsers and the performance is not that great.
It looked cool but not with all browsers. So I decided to use WebGL for better performance and compatibility with all browsers.
2. Changed to WebGL
For the 2d WebGL drawing, I used PIXI.js which supports advanced features such as batch rendering and filters.
First, I drew 500+ objects; then, I applied a blur effect to the entire screen; after that, I divided the screen into a portion to be drawn and not to be drawn according to the threshold value; this created a sticky area between the objects. In computer graphics, these are called Metaballs.
Although, PIXI doesn’t support ThresholdFilter, we can easily build code to support the filter.
Here is the Metaballs code for PIXI.js.
Now, all the problems have been solved. I think this is a good example of what I do: creating visual effects, interactions and animations with code, testing performance and finding the best way to solve problems.
The drops are actually made up of circles, a lot of circles. PIXI supports batch rendering, so the performance for drawing over 500 circles is 60fps. I placed large circles at regular intervals to create a wave at the top; then I randomly put a group of smaller circles in the wave to make the shape of a drop.
Initially, the circles in the group are clumped together; then, they slowly start dropping down one after the other. When the first circle drops down to a certain length, the group of circles is divided into a falling part and a rising part to create a feeling of stickiness.
Eating snacks dipped in gooey Chamoy sauce is an important concept of the brand. So I created this user interaction.
Users can grab a snack on the bottom of the screen, and cover it in sauce by sticking it under the sauce at the top of the screen, and/or dragging it under a drop.
If users do nothing, the sauce slowly drops and covers the logo in the middle of the screen.
For the splotch of sauce, I created an area on the snack (see the yellow circles); then, when this yellow area touches the sauce, a circle which represents the splotch of sauce is drawn at that position.
The size of the circle depends on the length of time the area touches the sauce - the longer the time, the larger the size of the circle/splotch.
5. Drop movements
I applied a physics law, inertia, to the gooey effect to show realistic movement. When the stain area touches the drop, the drop follows the snack, and after a certain distance, it swings back to its place. The stretched part of the drop swings a little also.
6. Mobile environment
This website works well on both desktop and mobile devices. Normally, the performance is not great on mobile, because of hardware spec. However, because WebGL now works on mobile, the performance has improved. In addition, I spent a lot of time optimizing my code for the best performance. For example, I used Bit Shift Operator instead of Math whenever possible, compared getElementById() to querySelector() and used the fastest one, and tested it on as many devices as possible, etc.