quick and dirty OTE
This commit is contained in:
@@ -85,6 +85,7 @@
|
||||
// 1. Code for the map
|
||||
{{ mapscript | safe }}
|
||||
|
||||
|
||||
// 2. This code loads the IFrame Player API code asynchronously.
|
||||
var tag = document.createElement('script');
|
||||
|
||||
|
||||
335
rowers/templates/embedded_video_ote.html
Normal file
335
rowers/templates/embedded_video_ote.html
Normal file
@@ -0,0 +1,335 @@
|
||||
{% extends "newbase.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load rowerfilters %}
|
||||
{% load i18n %}
|
||||
{% load leaflet_tags %}
|
||||
|
||||
|
||||
|
||||
{% block title %}Workout Video{% endblock %}
|
||||
|
||||
{% block meta %}
|
||||
{% leaflet_js %}
|
||||
{% leaflet_css %}
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<style>
|
||||
.slidecontainer {
|
||||
width: 100%; /* Width of the outside container */
|
||||
}
|
||||
|
||||
/* The slider itself */
|
||||
.slider {
|
||||
-webkit-appearance: none; /* Override default CSS styles */
|
||||
appearance: none;
|
||||
width: 100%; /* Full-width */
|
||||
height: 25px; /* Specified height */
|
||||
background: #d3d3d3; /* Grey background */
|
||||
outline: none; /* Remove outline */
|
||||
opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
|
||||
-webkit-transition: .2s; /* 0.2 seconds transition on hover */
|
||||
transition: opacity .2s;
|
||||
}
|
||||
|
||||
/* Mouse-over effects */
|
||||
.slider:hover {
|
||||
opacity: 1; /* Fully shown on mouse-over */
|
||||
}
|
||||
|
||||
/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none; /* Override default look */
|
||||
appearance: none;
|
||||
width: 25px; /* Set a specific slider handle width */
|
||||
height: 25px; /* Slider handle height */
|
||||
background: #4CAF50; /* Green background */
|
||||
cursor: pointer; /* Cursor on hover */
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 25px; /* Set a specific slider handle width */
|
||||
height: 25px; /* Slider handle height */
|
||||
background: #4CAF50; /* Green background */
|
||||
cursor: pointer; /* Cursor on hover */
|
||||
}
|
||||
</style>
|
||||
|
||||
{% language 'en' %}
|
||||
<h1>Video Analysis for {{ workout.name }}</h1>
|
||||
<ul class="main-content">
|
||||
{% if analysis and user.is_authenticated and user == rower.user and not locked %}
|
||||
<li class="grid_4">
|
||||
<p>Paste link to you tube video below</p>
|
||||
<p>Use the slider to locate start point for video on workout map</p>
|
||||
<p>Playing the video will advance the data in synchonization. Use the regular youtube controls
|
||||
to move around in the video and play it.</p>
|
||||
<p>You can make manual adjustments to the delay to fine tune the alignment.
|
||||
Once you are finished, check "Lock Video and Data" to lock the video and the data.</p>
|
||||
<p>Once you are happy with the alignment, you can save the analysis, and share with other people.</p>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="grid_2">
|
||||
<div style="height:100%" id="theplot" class="flexplot mapdiv">
|
||||
{{ mapdiv | safe}}
|
||||
|
||||
</div>
|
||||
<div class="slidecontainer">
|
||||
<input type="range" min="0" max="{{ maxtime }}" value="{{ analysis.delay }}" class="slider" id="myRange">
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid_2">
|
||||
<div id="player"></div>
|
||||
<script src="https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||
|
||||
|
||||
{{ mapscript | safe }}
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
// 2. This code loads the IFrame Player API code asynchronously.
|
||||
var tag = document.createElement('script');
|
||||
|
||||
tag.src = "https://www.youtube.com/iframe_api";
|
||||
var firstScriptTag = document.getElementsByTagName('script')[0];
|
||||
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
||||
|
||||
// 3. This function creates an <iframe> (and YouTube player)
|
||||
// after the API code downloads.
|
||||
var player;
|
||||
var playing;
|
||||
var videotime = 0;
|
||||
var data = JSON.parse('{{ data|safe }}');
|
||||
{% for id, metric in metrics.items %}
|
||||
var {{ id }}_values = data["{{ id }}"];
|
||||
// console.log("{{ id }}_values",{{ id }}_values);
|
||||
{% endfor %}
|
||||
// var boatspeed = data["boatspeed"];
|
||||
var latitude = data["latitude"];
|
||||
var longitude = data["longitude"];
|
||||
// var spm = data["spm"];
|
||||
// var ctch = data["catch"];
|
||||
|
||||
function onYouTubeIframeAPIReady() {
|
||||
player = new YT.Player('player', {
|
||||
height: '390',
|
||||
width: '640',
|
||||
videoId: '{{ video_id }}',
|
||||
events: {
|
||||
'onReady': onPlayerReady,
|
||||
'onStateChange': onPlayerStateChange
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 4. The API will call this function when the video player is ready.
|
||||
function onPlayerReady(event) {
|
||||
// event.target.playVideo();
|
||||
function updateTime() {
|
||||
var oldTime = videotime;
|
||||
var slider = document.getElementById("myRange");
|
||||
var lock = document.getElementById("lock");
|
||||
if(player && player.getCurrentTime) {
|
||||
videotime = player.getCurrentTime();
|
||||
var delay = document.getElementById("id_delay").value;
|
||||
sliderpos = Math.round(videotime) + Math.round(delay);
|
||||
slider.value = sliderpos;
|
||||
|
||||
var datatime = parseFloat(videotime)+parseFloat(delay);
|
||||
// velo = boatspeed[Math.round(datatime)];
|
||||
lat = latitude[Math.round(datatime)];
|
||||
lon = longitude[Math.round(datatime)];
|
||||
// strokerate = spm[Math.round(datatime)];
|
||||
// catchangle = ctch[Math.round(datatime)];
|
||||
{% for id, metric in metrics.items %}
|
||||
{{ id }}_now = {{ id }}_values[Math.round(datatime)];
|
||||
// console.log(datatime,{{ id }}_now, "{{ metric.name }}")
|
||||
{% endfor %}
|
||||
|
||||
document.getElementById("time").innerHTML = Math.round(videotime);
|
||||
document.getElementById("datatime").innerHTML = Math.round(datatime);
|
||||
// document.getElementById("speed").innerHTML = velo;
|
||||
// document.getElementById("spm").innerHTML = strokerate;
|
||||
// document.getElementById("catch").innerHTML = catchangle;
|
||||
{% for id, metric in metrics.items %}
|
||||
document.getElementById("{{ id }}").innerHTML = {{ id }}_now;
|
||||
{% endfor %}
|
||||
// gauge.set(catch_now);
|
||||
// var newLatLng = new L.LatLng(lat, lon);
|
||||
// marker.setLatLng(newLatLng);
|
||||
}
|
||||
if(videotime !== oldTime) {
|
||||
onProgress(videotime);
|
||||
}
|
||||
}
|
||||
timeupdater = setInterval(updateTime, 1000);
|
||||
}
|
||||
|
||||
// when the time changes, this will be called.
|
||||
function onProgress(currentTime) {
|
||||
var slider = document.getElementById("myRange");
|
||||
var lock = document.getElementById("lock");
|
||||
videotime = player.getCurrentTime();
|
||||
var delay = document.getElementById("id_delay").value;
|
||||
sliderpos = Math.round(videotime) + Math.round(delay);
|
||||
slider.value = sliderpos;
|
||||
}
|
||||
|
||||
function stopVideo() {
|
||||
player.stopVideo();
|
||||
}
|
||||
|
||||
// call this function when player state changes
|
||||
function onPlayerStateChange(event) {
|
||||
if (event.data == YT.PlayerState.PLAYING) {
|
||||
playing = false;
|
||||
} else {
|
||||
playing = true;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</li>
|
||||
{% if analysis and user.is_authenticated and user == rower.user %}
|
||||
<li class="grid_4">
|
||||
<input type="checkbox" name="lock" id="lock" value="Lock">Lock Data and Video
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
Data Time
|
||||
<span id="datatime">
|
||||
</span> seconds
|
||||
</li>
|
||||
<li>
|
||||
Video Time
|
||||
<span id="time">
|
||||
</span> seconds
|
||||
</li>
|
||||
{% for id, metric in metrics.items %}
|
||||
<li>
|
||||
{{ metric.name }}
|
||||
<span id="{{ id }}">
|
||||
</span> {{ metric.unit }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
<!-- <li class="grid_2">
|
||||
<canvas id="angles"></canvas>
|
||||
<script type="text/javascript" src="https://bernii.github.io/gauge.js/dist/gauge.js"></script>
|
||||
<script>
|
||||
|
||||
var opts = {
|
||||
lines: 12,
|
||||
angle: 0.15,
|
||||
lineWidth: 0.44,
|
||||
pointer: {
|
||||
length: 0.9,
|
||||
strokeWidth: 0.035,
|
||||
color: '#000000'
|
||||
},
|
||||
limitMax: 'false',
|
||||
// percentColors: [[0.0, "#a9d70b" ], [0.50, "#a9d70b"], [1.0, "#a9d70b"]], // !!!!
|
||||
strokeColor: '#E0E0E0',
|
||||
generateGradient: true
|
||||
};
|
||||
var target = document.getElementById('angles');
|
||||
var gauge = new Gauge(target).setOptions(opts);
|
||||
gauge.maxValue = 90;
|
||||
gauge.minValue = -90;
|
||||
gauge.animationSpeed = 5;
|
||||
gauge.set(-75);
|
||||
</script>
|
||||
</li> -->
|
||||
</ul>
|
||||
<p> </p>
|
||||
<form enctype="multipart/form-data" action="" method="post">
|
||||
<ul class="main-content">
|
||||
{% if form %}
|
||||
<li class="grid_2">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
</table>
|
||||
{% csrf_token %}
|
||||
{% if not analysis.id %}
|
||||
<input type="submit" name="reload_button" value="Reload">
|
||||
{% endif %}
|
||||
<input type="submit" name="save_button" value="Save">
|
||||
</li>
|
||||
<li class="grid_2">
|
||||
<table>
|
||||
{{ metricsform.as_table }}
|
||||
</table>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
{% if analysis and user.is_authenticated and user == rower.user %}
|
||||
<p>
|
||||
<a href="/rowers/video/{{ analysis.id }}/delete/">Delete Analysis</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
<script>
|
||||
// lock
|
||||
var lock = document.getElementById("lock");
|
||||
{% if locked %}
|
||||
lock.checked = true;
|
||||
{% endif %}
|
||||
|
||||
|
||||
// slider
|
||||
var slider = document.getElementById("myRange");
|
||||
{% if analysis and user.is_authenticated and user == rower.user %}
|
||||
document.getElementById("myRange").style.display = "block";
|
||||
{% else %}
|
||||
document.getElementById("myRange").style.display = "none";
|
||||
{% endif %}
|
||||
var output = document.getElementById("id_delay");
|
||||
try {
|
||||
output.value = Math.round(slider.value)-Math.round(player.getCurrentTime()); // Display the default slider value
|
||||
}
|
||||
catch(err) {
|
||||
output.value = Math.round(slider.value);
|
||||
}
|
||||
// Update the current slider value (each time you drag the slider handle)
|
||||
slider.oninput = function() {
|
||||
if (lock.checked) {
|
||||
if (this.value-output.value > 0) {
|
||||
player.seekTo(this.value-output.value);
|
||||
} else {
|
||||
if (playing) {
|
||||
player.seekTo(0);
|
||||
player.startVideo();
|
||||
}
|
||||
else {
|
||||
player.seekTo(0);
|
||||
player.pauseVideo();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
output.value = this.value-Math.round(player.getCurrentTime());
|
||||
}
|
||||
}
|
||||
|
||||
output.oninput = function() {
|
||||
slider.value = this.value+Math.round(player.getCurrentTime());
|
||||
}
|
||||
|
||||
// lock delay form field if checkbox checked
|
||||
lock.oninput = function() {
|
||||
if (this.checked) {
|
||||
output.disabled = true;
|
||||
} else {
|
||||
output.disabled = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endlanguage %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% include 'menu_workout.html' %}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user