Tutorials

How to Make a Video Player Prototype

Learn how to make an TikTok-inspired video player prototype with a scrubber, using formulas and variables.

Leah Han
Leah Han, Head of Customer LearningJuly 6, 2021
How to make a video player prototype thumbnail
video player prototype made by ProtoPie

We've divided this step-by-step guide into 6 sections:

  • Part 1: Play/Pause a video on scroll
  • Part 2: Tap a video card to make an expanding transition
  • Part 3: Seek video by tapping the progress bar
  • Part 4: Seek video by dragging the progress bar
  • Part 5: Display the video's current playtime
  • Part 6: Open and close the comment section while the video is playing

Make sure you're using version 5.5 or above!

Part 1: Play/Pause a video on scroll

Play and or pause a video on scroll

1. In the scene Profile, create a Scroll Container the same size as your scene (834 x 1194) and put all layers into this.

Creating a Scroll Container in the scene profile

2. Store Scroll Container's scroll value in a variable dynamically.

  • Create a new For This Scene variable Scroll
  • Select Number
  • Check Use as Formula (only works for For This Scene variables)
  • Enter 'Scroll'.scrollOffset
  • Click on the debug icon next to the variable name

At all times, you keep track of Scroll Container scroll value. You don't need the Detect trigger and Assign response this way.

storing scroll container's scroll value in a variable dynamically

3. Play or Pause a video based on the scroll value.

  • Add two Range triggers, both assigned to the variable Scroll
    • For one, set the range as 210 ≤ Scroll
    • For the other, set the range as Scroll ≤ 209
  • Add two Playback responses, both assigned to video 1, one for each Range trigger
    • For the first Range (210 ≤ Scroll), select Play and check Looping in Playback
    • For the second Range (Scroll ≤ 209), select Pause in Playback
how to play or pause a video based on the scroll value

Part 2: Tap a video card to make an expanding transition

Tapping a video card to expand

1. Make a video expand and display in fullscreen.

  • Add a Tap trigger, assigned to Video 1, the container video 1 is in
  • Add a Scale response, assigned to Video 1, scaling to 834 x 1194

2. Move the video to the correct relative position upon Tap.

  • Add a Move response under Tap, moving to toLayerX("Scroll",0,0) for X and toLayerY("Scroll",0,0) for Y
Adding a Move response under Tap

As Video 1 is inside Scroll Container, its position is relative to Scroll Container. Instead, Video 1 should move to (0, 0) relative to the screen, regardless of the scroll value. This is why you need the toLayerX and toLayerY functions.

Returning the y-coordinate relative to a container or component
Returning the x-coordinate relative to a container or component
Meaning of toLayer and toScreen

💡 toLayerX: Return the x-coordinate relative to a container or component. Layers in a container or component follow the coordinates relative to the container or component they are in.

  • toLayerX(containerName: LAYER, x: NUMBER, y: NUMBER) → NUMBER

💡 toLayerY: Return the y-coordinate relative to a container or component. Layers in a container follow the coordinates relative to the container or component they are in.

  • toLayerY(containerName: LAYER, x: NUMBER, y: NUMBER) → NUMBER

3. Bring the video to the front before jumping to the next scene.

  • Add a Radius response, assigned to Video 1, to reset the radius to 0
  • Add a Reorder response, assigned to Video 1, to bring Video 1 to the front
  • Add a Jump response to the scene Video with a 0.2-second delay

Part 3: Seek video by tapping the progress bar

Video player prototype's scrubber image being animated

1. Make the video play automatically and loop at all times.

  • In the second scene Video, check both “Play Automatically” and Looping in the video layer Video its property panel

2. Make the scrubber and play head progress while playing the video.

  • Add a Chain trigger, assigned to Video and its Time property
  • Add a Move response, assigned to Dot, mapping the video length with the distance Dot needs to move
  • Add a Scale response, assigned to Progress, mapping the video length with the width Progress needs to scale to
how to make the scrubber and play head progress while playing the video

3. Make the video seek a specific timestamp based on where you tap on the scrubber.

  • Add a Tap trigger, assigned to the container Progress bar
  • Add a Move response, assigned to Dot, moving to the x-coordinate toLayerX('Progress bar', $touchX, 8)

With the predefined variable $touchX, retrieve the x-coordinate of a touch. As you need to turn this value into an x-coordinate relative to the Progress bar, use the toLayerX function. As Dot its initial position is (0, 8), use 8 as the third parameter.

  • Add a Playback response, assigned to Video
  • Seek the video to 17 * toLayerX(Progress bar, $touchX , 8) / 618
    • 17: Video total duration. 618: Progress bar width
    • Video current playtime = Video duration*Dot current position/Progress bar width

The scrubber Progress would scale along as it's chained to Video time property already. Hence, no need for an additional Scale response.

Part 4: Seek video by dragging the progress bar

Drag the video player prototype's progress bar to seek specific timestamps

1. Make a working scrubber with a draggable play head.

  • Add a Drag trigger, assigned to Dot
  • Add a Move response and assign it to Dot. Set the direction and select Limit to Container, so that Dot can only move within the Progress bar
Adding a drag trigger and a move response in ProtoPie Studio

2. Make the video seek to the timestamp matching the x position of Dot on the progress bar.

  • Use a Detect trigger to keep track of Dot's x position
  • Add a Playback response (Seek) and assign it to Video
Making the video seek to the timestamp

Why are we using Detect instead of Chain?

ProtoPie doesn't support Playback in Chain yet. Detect is the only solution currently available.

3. You'll notice a problem at this point: the video freezes while playing.

The video player prototype's video freezing while playing

It's due to a conflict between the triggers Drag, Chain, and Tap assigned to Progress bar.

To solve the problem, you need to help ProtoPie distinguish between tapping and dragging Progress bar.

How are they different in ProtoPie?

  • Drag:when the finger drags Dot, its x position affects the current playtime of Video. If the finger is lifted, Dot starts progressing together with Video
  • Tap:the responses under Tap execute as soon as the finger is lifted

How can you distinguish between these two actions in ProtoPie? with Variables!

  • Create a variable (for this scene) and assign the numeric value 0 to it
  • Add a Touch Down trigger and Touch Up trigger with one Assign response each:
    • If touchdown, variable = 0
    • If touchup, variable = 1
dotState view in ProtoPie Studio
assigning a response in ProtoPie Studio
Set up Touch Up and Touch Down
  • Trigger the Playback response only if variable = 1 by adding a Condition under Detect

Part 5: Display video's current playtime

video player's current playtime

1. Show video current playtime and duration:

  • Add a Detect trigger assigned to Video Time
  • Add two Text responses with formula floor(Video.currentTime) in Content

💡 currentTime: The current playtime of a video, audio, or Lottie layer. The default format is seconds and milliseconds.

  • Floor or Round allow to round playtime values (we want to display minutes and seconds only). We chose to use Floor for better accuracy

💡 Floor: Returns the largest integer value smaller than or equal to a number. e.g.floor(1.5) -> 1

💡 Round: Returns the rounded value of a number. e.g.round(1.5)-> 2

  • Add a Condition under each Text response:
    • If play time < 10 sec, add 0:0 before floor(Video.currentTime)
    • If play time ≥ 10 sec, add 0: before floor(Video.currentTime)
adding a condition under each text response

Part 6: Show/Close Comments

Show/close comments in video player prototype

1. Resize Video to make room for Comments:

  • Add a Tap trigger and assign it to Comments
  • Add a Scale response and assign it to Video:
    • Use the parent formula parent(Video).height in Height to scale Video to match the height of its parent Video contents

💡 parent: refers to the parent layer, e.g. a container or component, or returns its layer property. Example: parent(Rectangle 1).x → x-coordinate of Rectangle 1 its parent layer

  • In Width, use formula Video.width/Video.height*parent(Video).height to keep the same ratio
use a formula for video width for high fidelity prototyping

2. Move Comments to a y position matching the height of Video Contents:

  • Add a Move response with the formula 'Container'.height under Y

Why did we make Video Contents smaller than the video's actual size?

Because this way you can simply use a parent formula to dynamically update the video's height. No need to readjust Scale values if the height of Video Contents changes (see image below) Quite a time saver.

video content resizing for video player

3. Reset the scene to its initial state when tapping the Close button

  • Add a Tap trigger and assign it to the Close button
  • Add two Reset responses to reset Comments and Profile
  • Add a Scale response and assign it to Video. Why not Reset? To avoid Progress bar resetting at the same time
  • Use formulas initial(Video,"width") and initial(Video,"height") in Scale to avoid having to recalculate values in case you later change the video's size

💡 Initial: Return the initial value (before any interactions) of a specific layer property. Example: initial(Oval 1, "opacity") → Initial opacity of Oval 1

  • Add a Move response and assign it to Progress bar:
    • Use the formula initial(Progress bar component,"y") in Y, to move Progress bar back to its initial position
Tips

For an even more realistic result, you can add a video thumbnail Fill to Video Contents!

adding a video thumbnail fill to video contents

Summary

In this tutorial, we've learned how to make a very realistic video player.

If you're still at a beginner stage, some of the steps above were probably quite difficult to grasp, especially those involving logic and formulas.

Here's a list of the formulas we used in this tutorial:

  • $touchX
  • toLayerX(containerName, x, y)
  • 'Layername'.currentTime
  • floor(Number)
  • parent(LayerName).property
  • initial(LayerName, "Property")

For more details, check out our formulas documentation.

If you'd love to better understand how this video player interaction was made, join our ProtoPie 5.5 Launch event! Our team will show you step-by-step how to make it and answer any questions you may have!