I am trying to clone the following site:
https://www.apple.com/mac-pro/
I am still in the prototyping phase and the big ticket item I am trying to figure out is how they are playing their MP4 file backwards when you scroll up the page. If you scroll down the page a few steps and then back up, you will see what I mean.
So far I have tried the following techniques:
- Tweening currentTime property of video element
- Using requestAnimationFrame and using the timestamp in the callback to update the currentTime property to the desired value
Using the requestAnimationFrame technique, I am now getting a partially usable result in every browser other than Chrome. Chrome is ok if you want to rewind maybe .5 seconds, but any more than that and it will get jumpy.
I have also made the following discoveries:
- Chrome hates trying to rewind an MP4 file
- As much as Chrome hates rewinding MP4 files, also make sure that you don't have an audio track on your video file. It will make it even slower.
So I feel I have a pretty good understanding of the options available to me, but the one thing that makes me think I am missing something is that the Apple website functions ok in Chrome.
I have started debugging their code which is located at:
https://images.apple.com/v/mac-pro/home/b/scripts/overview.js
And from what I can tell they seem to be using requestAnimationFrame, but I can't understand why they are getting a better result.. Does anyone have any ideas on how to achieve this effect?
BTW - I understand that videos are not really meant to be played backwards and they will never play predictably backwards. I have even had occasions on the Apple website where the rewinding can be jerky. But they still have good 2-3 second rewind transitions and the result is definitely acceptable.
Here is my relevant javascript and HTML so far..
var envyVideo, currentVideoTrigger = 0,
currentIndicator, startTime, vid, playTimestamp, playTo, playAmount, triggeredTime, rewindInterval;
$(function() {
vid = document.getElementById("envy-video");
$("#play-button").click(function() {
vid.play();
});
$("#rewind-button").click(function() {
vid.pause();
playTo = parseFloat($("#play-to-time").val());
playAmount = playTo - vid.currentTime;
triggeredTime = vid.currentTime;
requestAnimationFrame(rewindToPointInTime);
});
});
function rewindToPointInTime(timestamp) {
if (!playTimestamp) playTimestamp = timestamp;
var timeDifference = (timestamp - playTimestamp) / 1000;
vid.currentTime = triggeredTime + (playAmount * (timeDifference / Math.abs(playAmount)));
if (vid.currentTime > playTo) {
requestAnimationFrame(rewindToPointInTime);
} else {
playTimestamp = null;
playAmount = null;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rhino Envy</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="./js/envy.js"></script>
<link rel="stylesheet" href="./css/envy.css">
</head>
<body;
<div id="envy-video-container">
<video id="envy-video" src="./videos/prototype_animation.mp4"></video>
</div>
<div id="video-controls">
<p id="video-current-time"></p>
<div class="video-control"><button id="rewind-button">rewind to</button><input type="text" id="play-to-time" placeholder="forward time" value="0"></div>
<button id="play-button">play</button>
</div>
<ul id="envy-steps">
<li id="envy-step-indicator-1"></li>
<li id="envy-step-indicator-2"></li>
<li id="envy-step-indicator-3"></li>
</ul>
<section id="envy-full-range">
<div id="envy-1-door-link"></div>
<div id="envy-2-door-link"></div>
<div id="envy-3-door-link"></div>
</section>
</body>
</html>