• May 20, 2021

    Interactive Livestream

    Interactive Livestream

    Realtime Interactive Text-to-Speech YouTube Livestream, built with node.js, and Max/MSP

  • March 1, 2020

    Lux Gatherings – Web App

    Lux Gatherings – Web App

    • Skills

      Development, Branding, Design, Team Leadership

    • Year

      2015

    Challenge

    Lux Gatherings was a startup company that had come to my agency to help with their branding, web app design and development. They were looking to create a product of connecting party hosts with luxury food and servers.

    Solution

    Through regular, cyclical design, development, and prototyping sessions. We worked to develop a web app from the ground up to act as the “Uber” of dinner party planning.

    Creation

    • Marketing website built with WordPress for rapid updates.
    • Web app built with Ruby on Rails for a quicker ready to market and to maintain an agile framework
    • Custom user registration with multiple account levels
    • Custom chat service with specialized profanity filtering
    • A unified booking system, anywhere you create or edit a party looks the same so you always know where you are
    • Creative, easy-to-use filtering
  • March 1, 2020

    Ral-ly 3D Website

    Ral-ly 3D Website

    • Skills

      Development, Branding, Design

    • Year

      2014

    Challenge

    Ral-ly was a Sports drink start up company that wanted a website that could make them stand out from other competitors. They wanted to leave an imprint on their audience and that the best way to do that was to have something that was unlike anything on the web.

    Solution

    To accomplish this, we contracted with a 3D modeler to model their sports drink bottle in three flavors. We then animated the bottle to act as a quirky and fun transition while you navigate through their website.

  • May 15, 2018

    Lux Gatherings – Physics Light String

    Interested in this project?

    Lux Gatherings – Physics Light String

    • Skills

      Development, Branding, Design

    • Year

      2015

    Challenge

    A new startup that my agency had been working with since the beginning, looking to build an online portal for hiring servers and catering for luxury home parties was looking for a way to announce their new brand, and build hype. Their whole brand experience was based around; being an internet company (so we knew we had to have something somewhat advanced), and catering to a higher end client (thus the name “Lux Gatherings”).

    Solution

    So I took to building a beautifully minimalistic landing page to help communicate those two ideas. I worked with our designer to put together a simple layout, with a slight gradient, and this beautiful string light effect.

    With the initial design in place I knew exactly what I wanted to do; animate the string lights. But not a static animation, I wanted them to be interactive.

    So I settled on creating a physics based string lights effect. I found a great little 2D rigid-body physics engine in vanilla Javascript. This allowed me to create a rigid chain of small circular bodies, the small bodies would be set to not render. Meaning, it was a rigid line, connected to an invisible circle, then to another rigid line, and so on. Then at each invisible circle, I create a new, larger circle, connected (via a constraint, visualized as a thicker black line) to the invisible circle. Then I randomly positioned those larger, visible circles so that when the page was loaded, it would have a nice, falling effect.

      function initString() {
        var groupId = Body.nextGroupId();
    
        var stack = Composites.stack(0, -10, 10, 1, 0, 0, function(x, y, column, row) {
          var isStatic = false;
    
          x = ((column/9) * $string.width());
          y = (column/9) * 200;
    
          if (column == 0) {
            x = 50;
            y = -10;
    
            isStatic = true;
          }
    
          if (column == 9) {
    
            isStatic = true;
          }
    
          return Bodies.circle(x, y, 5, {
            groupId: groupId,
            isStatic: isStatic,
            frictionAir: 0.3,
            render: {
              visible: false,
            }
          });
        });
    
        string = Composites.chain(stack, 0, 0, 0, 0, {
          groupId: groupId,
          stiffness: 0.9,
          render: {
            strokeStyle: "#231f20",
            lineWidth: 3
          }
        });
    
        // add string
        World.add(engine.world, string);
      }

    Now. I could have created more points along the chain, giving the rope a more fluid feel, but I hedged away from this, due to the fact that in my cross browser testing, I noticed that some browsers would slow down dramatically due to the added physics calculations.

    Now I wanted to give the user a hint that they could interact with it. I came up with the idea of doing a wind effect. The problem was Matter did not have any sort of additional force effects. So I decided to shift gravity. At a random interval (between 0 and 3 seconds), and at a random duration (between 0 and 3 seconds), and at a random intensity (between 0.25 and 0.5), and at a random duration (between 10 and 20 frames), and in a random direction (half the length), I would ease the gravity from straight down, to the chosen direction, imitating a gust of wind.

      function initWind() {
        wind = window.setTimeout(function() { 
          gust();
        }, 2000);
    
        function gust() {
          var gravity = 0;
          var i = 0;
    
          var intensity = 0.25 - (Math.random() * 0.5);
          var length = Math.ceil(Math.random() * 20) + 10;
          var halflength = length/2;
    
          guster = window.setInterval(function() {
            if (i <= halflength) {
              gravity = ease(i, 0, intensity*halflength, halflength);
            } else {
              gravity = ease(i - halflength, intensity*halflength, 0 - intensity*halflength, halflength);
            }
    
            if (i == length) {
              window.clearInterval(guster);
    
              wind = window.setTimeout(function() {
                gust();
              }, Math.random() * 3000);
            }
    
            i++;
    
            engine.world.gravity.x = gravity;
          }, 100);
        }
      }

    Then the last part, creating interaction. For desktop I created an invisible circle that would simply track with the mouse, and repel other circles.

    function initMouse() {
      var mouser = Matter.MouseConstraint.create(engine, {
        constraint: {
          render: {
            visible: false
          }
        }
      });
    
      var groupId2 = Body.nextGroupId();
      var mover = Bodies.circle(0, 0, 10, {
        groupId: groupId2,
        isStatic: true,
        render: {
          visible: false,
        }
      });
    
      var mover2 = Bodies.circle(0, 0, 20, {
        groupId: groupId2,
        isStatic: false,
        render: {
          visible: false,
        }
      });
    
      var mouseConstraint = Constraint.create({
        bodyA: mover,
        bodyB: mover2,
        length: 0,
        render: {
          visible: false,
        }
      });
    
      Matter.Events.on(engine, 'mousemove', function(event) {
        mover.position = {x: event.mouse.position.x, y: event.mouse.position.y};
      });
    
      World.add(engine.world, [mouser, mover, mover2, mouseConstraint]);
    }

    And for Mobile I removed the wind, and instead opted to shift the gravity in the direction the user tilted their phone.

    function initMobile() {
      $("#string").css("pointer-events", "none");
    
      window.addEventListener('deviceorientation', updateGravity, true);
    
      function updateGravity() {
        oldorient = orientation;
        orientation = window.orientation,
        gravity = engine.world.gravity;
    
        if (orientation != oldorient)
          resize();
    
        if (orientation === 0) {
          gravity.x = Common.clamp(event.gamma, -90, 90) / 90;
          gravity.y = Common.clamp(event.beta, -90, 90) / 90;
        } else if (orientation === 180) {
          gravity.x = Common.clamp(event.gamma, -90, 90) / 90;
          gravity.y = Common.clamp(-event.beta, -90, 90) / 90;
        } else if (orientation === 90) {
          gravity.x = Common.clamp(event.beta, -90, 90) / 90;
          gravity.y = Common.clamp(-event.gamma, -90, 90) / 90;
        } else if (orientation === -90) {
          gravity.x = Common.clamp(-event.beta, -90, 90) / 90;
          gravity.y = Common.clamp(event.gamma, -90, 90) / 90;
        }
      };
    }

    Creation

    All In all, I created a very simplistic, beautiful way to grasp peoples attention, instigate interaction, and increase their likelihood of signing up to be a member of their mailing list. Thus increasing the companies likelihood of launch success.

  • March 1, 2020

    O’Connor’s Catholic Supply

    O’Connor’s Catholic Supply

    • Skills

      Development, Branding, Design, Team Leadership

    • Year

      2017

    Challenge

    O’Connor’s Catholic Supply store has been around for 80 years and had moved to a location that was bigger in Mission Valley. They contacted my agency to help and shift the way the community saw them as they moved into a new era.

    Solution

    With research we focused on the three tenants of the brand “Faith, Family, & Community,” and I made their new e-commerce website to match the brand with a robust, simple and easily navigable site.

    Creation

    With a custom mobile friendly navigation system, an attractive and approachable design, and 80 years of history behind them; the new website saw conversions increase and paved the way for new generations of O’Connor’s.