Added slider and improved behavior of video analysis
This commit is contained in:
@@ -1899,6 +1899,9 @@ def leaflet_chart_video(lat,lon,name=""):
|
||||
"Nautical": nautical,
|
||||
}},{{
|
||||
"Navionics":navionics,
|
||||
}},
|
||||
{{
|
||||
position:'topleft'
|
||||
}}).addTo(mymap);
|
||||
|
||||
var marker = L.marker([{latbegin}, {longbegin}]).addTo(mymap);
|
||||
|
||||
@@ -15,15 +15,54 @@
|
||||
|
||||
{% 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">
|
||||
<li class="grid_4">
|
||||
<div style="height:100%" id="theplot" class="flexplot mapdiv">
|
||||
{{ mapdiv | safe}}
|
||||
|
||||
</div>
|
||||
<li>
|
||||
Data Time
|
||||
<span id="datatime">
|
||||
</span> seconds
|
||||
</li>
|
||||
<li>
|
||||
Video Time
|
||||
@@ -40,11 +79,21 @@
|
||||
<span id="speed">
|
||||
</span> m/s
|
||||
</li>
|
||||
<li class="grid_4">
|
||||
<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>
|
||||
// 1. Code for the map
|
||||
{{ mapscript | safe }}
|
||||
|
||||
// 2. This code loads the IFrame Player API code asynchronously.
|
||||
var tag = document.createElement('script');
|
||||
|
||||
@@ -75,16 +124,20 @@
|
||||
|
||||
// 4. The API will call this function when the video player is ready.
|
||||
function onPlayerReady(event) {
|
||||
event.target.playVideo();
|
||||
// event.target.playVideo();
|
||||
function updateTime() {
|
||||
var oldTime = videotime;
|
||||
if(player && player.getCurrentTime) {
|
||||
videotime = player.getCurrentTime();
|
||||
velo = boatspeed[Math.round(videotime)];
|
||||
lat = latitude[Math.round(videotime)];
|
||||
lon = longitude[Math.round(videotime)];
|
||||
strokerate = spm[Math.round(videotime)];
|
||||
var delay = document.getElementById("myRange").value;
|
||||
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)];
|
||||
|
||||
document.getElementById("time").innerHTML = Math.round(videotime);
|
||||
document.getElementById("datatime").innerHTML = Math.round(datatime);
|
||||
document.getElementById("speed").innerHTML = velo;
|
||||
document.getElementById("spm").innerHTML = strokerate;
|
||||
var newLatLng = new L.LatLng(lat, lon);
|
||||
@@ -99,9 +152,6 @@
|
||||
|
||||
// when the time changes, this will be called.
|
||||
function onProgress(currentTime) {
|
||||
if(currentTime > 20) {
|
||||
console.log("the video reached 20 seconds!");
|
||||
}
|
||||
}
|
||||
|
||||
function stopVideo() {
|
||||
@@ -143,6 +193,26 @@
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
<script>
|
||||
// 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");
|
||||
output.value = slider.value; // Display the default slider value
|
||||
|
||||
// Update the current slider value (each time you drag the slider handle)
|
||||
slider.oninput = function() {
|
||||
output.value = this.value;
|
||||
}
|
||||
|
||||
output.oninput = function() {
|
||||
slider.value = this.value;
|
||||
}
|
||||
</script>
|
||||
{% endlanguage %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -45,6 +45,11 @@
|
||||
<i class="fas fa-balance-scale fa-fw"></i> Compare
|
||||
</a>
|
||||
</li>
|
||||
<li id="video-analysis">
|
||||
<a href="/rowers/workout/{{ workout.id|encode }}/video/">
|
||||
<i class="fas fa-video-plus fa-fw"></i> Video Analysis
|
||||
</a>
|
||||
</li>
|
||||
{% if user.is_authenticated and workout|may_edit:request %}
|
||||
<li id="chart-image">
|
||||
<a href="/rowers/workout/{{ workout.id|encode }}/image/">
|
||||
@@ -74,11 +79,6 @@
|
||||
<i class="fas fa-map-marked-alt fa-fw"></i> Map
|
||||
</a>
|
||||
</li>
|
||||
<li id="video-analysis">
|
||||
<a href="/rowers/workout/{{ workout.id|encode }}/video/">
|
||||
<i class="fas fa-video-plus fa-fw"></i> Video Analysis
|
||||
</a>
|
||||
</li>
|
||||
<li id="chart-empower">
|
||||
<a href="/rowers/workout/{{ workout.id|encode }}/forcecurve/">
|
||||
<i class="fas fa-dumbbell fa-fw"></i> Force Curve
|
||||
|
||||
@@ -173,6 +173,7 @@ $('#id_workouttype').change();
|
||||
{% endfor %}
|
||||
{% for video in videos %}
|
||||
<li>
|
||||
<div>{{ video.name }}</div>
|
||||
<a href="/rowers/video/{{ video.id|encode }}/">
|
||||
<img src="https://img.youtube.com/vi/{{ video.video_id }}/hqdefault.jpg"/>
|
||||
</a>
|
||||
|
||||
@@ -69,6 +69,10 @@ def workout_video_view(request,id=''):
|
||||
form = VideoAnalysisCreateForm(request.POST)
|
||||
if form.is_valid():
|
||||
video_id = form.cleaned_data['url']
|
||||
try:
|
||||
video_id = get_video_id(form.cleaned_data['url'])
|
||||
except (TypeError,ValueError):
|
||||
pass
|
||||
delay = form.cleaned_data['delay']
|
||||
if 'save_button' in request.POST:
|
||||
analysis.name = form.cleaned_data['name']
|
||||
@@ -101,8 +105,8 @@ def workout_video_view(request,id=''):
|
||||
df2 = df.resample('1s').mean().interpolate()
|
||||
|
||||
|
||||
mask = df2['time'] < delay
|
||||
df2 = df2.mask(mask).dropna()
|
||||
#mask = df2['time'] < delay
|
||||
#df2 = df2.mask(mask).dropna()
|
||||
df2['time'] = (df2['time']-df2['time'].min())
|
||||
|
||||
boatspeed = (100*df2['velo']).astype(int)/100.
|
||||
@@ -112,8 +116,8 @@ def workout_video_view(request,id=''):
|
||||
|
||||
coordinates.set_index(pd.to_timedelta(coordinates['time'],unit='s'),inplace=True)
|
||||
coordinates = coordinates.resample('1s').mean().interpolate()
|
||||
mask = coordinates['time'] < delay
|
||||
coordinates = coordinates.mask(mask).dropna()
|
||||
#mask = coordinates['time'] < delay
|
||||
#coordinates = coordinates.mask(mask).dropna()
|
||||
coordinates['time'] = coordinates['time']-coordinates['time'].min()
|
||||
latitude = coordinates['latitude']
|
||||
longitude = coordinates['longitude']
|
||||
@@ -158,6 +162,7 @@ def workout_video_view(request,id=''):
|
||||
'form':form,
|
||||
'breadcrumbs':breadcrumbs,
|
||||
'analysis':analysis,
|
||||
'maxtime':coordinates['time'].max(),
|
||||
})
|
||||
|
||||
|
||||
@@ -206,8 +211,8 @@ def workout_video_create_view(request,id=0):
|
||||
df2 = df.resample('1s').mean().interpolate()
|
||||
|
||||
|
||||
mask = df2['time'] < delay
|
||||
df2 = df2.mask(mask).dropna()
|
||||
#mask = df2['time'] < delay
|
||||
#df2 = df2.mask(mask).dropna()
|
||||
df2['time'] = (df2['time']-df2['time'].min())
|
||||
|
||||
boatspeed = (100*df2['velo']).astype(int)/100.
|
||||
@@ -217,8 +222,8 @@ def workout_video_create_view(request,id=0):
|
||||
|
||||
coordinates.set_index(pd.to_timedelta(coordinates['time'],unit='s'),inplace=True)
|
||||
coordinates = coordinates.resample('1s').mean().interpolate()
|
||||
mask = coordinates['time'] < delay
|
||||
coordinates = coordinates.mask(mask).dropna()
|
||||
#mask = coordinates['time'] < delay
|
||||
#coordinates = coordinates.mask(mask).dropna()
|
||||
coordinates['time'] = coordinates['time']-coordinates['time'].min()
|
||||
latitude = coordinates['latitude']
|
||||
longitude = coordinates['longitude']
|
||||
@@ -251,6 +256,8 @@ def workout_video_create_view(request,id=0):
|
||||
|
||||
]
|
||||
|
||||
analysis = {'delay':delay}
|
||||
|
||||
return render(request,
|
||||
'embedded_video.html',
|
||||
{
|
||||
@@ -261,7 +268,9 @@ def workout_video_create_view(request,id=0):
|
||||
'mapdiv': mapdiv,
|
||||
'video_id': video_id,
|
||||
'form':form,
|
||||
'analysis':analysis,
|
||||
'breadcrumbs':breadcrumbs,
|
||||
'maxtime':coordinates['time'].max()
|
||||
})
|
||||
|
||||
# Show the EMpower Oarlock generated Stroke Profile
|
||||
|
||||
Reference in New Issue
Block a user