The Stop Motion carousel presents products dynamically and attractively, introducing a unique movement to the images without the burden of using videos. The application offers a versatile framework that can be effortlessly customized by business users using a simple data object.
Following years of the consistent "Jean Guide" appearance, AEO sought a change. Through collaboration with the design team, I developed a dynamic and scalable solution applied across various product categories. A notable achievement was eliminating the requirement for engineering resources to facilitate new instances or modifications.
Each model was filmed executing a simple movement, such as shifting their weight or moving their hands or legs. Ten frames were then chosen to serve as a repeatable and reversible motion.
Only one frame of the sprite is visible, with the rest being masked. The sprite is moved both up and down, creating the illusion of a moving image, similar to a GIF. Ensuring natural-looking movement in reverse enables us to derive two animations from a single sprite.
A requirement is that each sprite has a uniform width and height. Moreover, the overall height of the sprite is incorporated, enabling the code to animate through the total number of frames unique to each sprite. These values can be easily adjusted within the code to accommodate a variety of ratios. While the sprites are not responsive, they are adaptive. Depending on the adjustable viewport, the number of visible sprites will adapt to accommodate any device width. Similarly, the draggable preview window will adjust and toggle visibility based on the viewport.
By setting several properties, the user can decide the following:
{ 'speed': 100, 'minInterval': 0, 'maxInterval': 2.5, 'preview': 30, 'intro': true, 'scrollbar': false, 'bounce': false, 'fade': false, 'imgWidth': 144, 'imgHeight': 365, 'linkTo': false, 'sprites': [ { "copy": "Sky High Jegging", "catId": "cat7010082", "imgSrc": "/projects/stop-motion/images/skyhighjegging.jpg", "imgHeight": 3650 }, ... ] }
Each sprite is coded as a data object in the application. The system tracks the position and direction of the current sprite animation. Furthermore, it ensures that each sprite within the viewport completes one animation cycle before any sprite is animated for a second time.
for (var i = 0; i < animationCount; i++) { animations[i].leftPosition = Math.round($(animations[i]).position().left); animations[i].rightPosition = Math.round(animations[i].leftPosition + parseInt(animationOuterWidth, 10)); animations[i].sprite = $(animations[i]).find('img'); animations[i].frame_count = Math.round($(animations[i].sprite).attr('height') / animationHeight); animations[i].top_pos = 0; animations[i].hasPlayed = 0; animations[i].loopCount = 1; }
To provide a more organic feel to the guide, two aspects have been randomized. Firstly, the timing between sprite animations is set with minimum and maximum values. A randomized value within this range is selected each time to prevent the user from becoming accustomed to a specific pace. Additionally, the order in which the sprites animate is also randomized.
//Create Random Delay Between Animations function randomizeInterval() { randomized = true; var randomInterval = Math.floor(Math.random() * (animationData.maxInterval * 10 - animationData.minInterval * 10) + animationData.minInterval * 10) * 100; animationDelay = setTimeout(function() { randomizeNumber(); }, randomInterval); }
//Create Random Number for Animated Element function randomizeNumber(){ activeAnimation = Math.floor((Math.random() * animationCount)); checkNum(); }