update timeline panel and timeline player
This commit is contained in:
parent
675257febe
commit
0e8bfd1348
2 changed files with 288 additions and 57 deletions
|
@ -21,6 +21,9 @@ Ox.VideoTimelinePanel = function(options, self) {
|
|||
clickLink: null,
|
||||
cuts: [],
|
||||
duration: 0,
|
||||
followPlayer: false,
|
||||
getFrameURL: null,
|
||||
getTimelineImageURL: null,
|
||||
height: 0,
|
||||
layers: [],
|
||||
loop: false, // fixme: used?
|
||||
|
@ -36,6 +39,9 @@ Ox.VideoTimelinePanel = function(options, self) {
|
|||
showLayers: {},
|
||||
showUsers: false,
|
||||
subtitles: [],
|
||||
timeline: '',
|
||||
timelineImageURL: '',
|
||||
timelines: [],
|
||||
video: '',
|
||||
volume: 1,
|
||||
width: 0
|
||||
|
@ -60,12 +66,23 @@ Ox.VideoTimelinePanel = function(options, self) {
|
|||
self.$player = Ox.VideoTimelinePlayer({
|
||||
censored: self.options.censored,
|
||||
cuts: self.options.cuts,
|
||||
duration: self.options.durations,
|
||||
duration: self.options.duration,
|
||||
followPlayer: self.options.followPlayer,
|
||||
getFrameURL: self.options.getFrameURL,
|
||||
getTimelineImageURL: self.options.getTimelineImageURL,
|
||||
height: self.options.height,
|
||||
muted: self.options.muted,
|
||||
paused: true,
|
||||
position: self.options.position,
|
||||
resolution: self.options.resolution,
|
||||
volume: self.options.volume
|
||||
subtitles: self.options.subtitles,
|
||||
timeline: self.options.timeline,
|
||||
timelineImageURL: self.options.timelineImageURL,
|
||||
timelines: self.options.timelines,
|
||||
video: self.options.video,
|
||||
videoRatio: self.options.videoRatio,
|
||||
volume: self.options.volume,
|
||||
width: getPlayerWidth()
|
||||
})
|
||||
.bindEvent({
|
||||
muted: function(data) {
|
||||
|
@ -85,6 +102,69 @@ Ox.VideoTimelinePanel = function(options, self) {
|
|||
}
|
||||
});
|
||||
|
||||
self.$annotationPanel = Ox.AnnotationPanel({
|
||||
calendarSize: self.options.annotationsCalendarSize,
|
||||
clickLink: self.options.clickLink,
|
||||
editable: false,
|
||||
font: self.options.annotationsFont,
|
||||
highlight: self.options.find,
|
||||
'in': self.options['in'],
|
||||
layers: self.options.layers,
|
||||
mapSize: self.options.annotationsMapSize,
|
||||
out: self.options.out,
|
||||
position: self.options.position,
|
||||
range: self.options.annotationsRange,
|
||||
selected: self.options.selected,
|
||||
showCalendar: self.options.showAnnotationsCalendar,
|
||||
showFonts: true,
|
||||
showLayers: Ox.clone(self.options.showLayers),
|
||||
showMap: self.options.showAnnotationsMap,
|
||||
showUsers: self.options.showUsers,
|
||||
sort: self.options.annotationsSort,
|
||||
width: self.options.annotationsSize
|
||||
})
|
||||
.bindEvent({
|
||||
annotationsfont: function(data) {
|
||||
self.options.annotationsFont = data.font;
|
||||
that.triggerEvent('annotationsfont', data);
|
||||
},
|
||||
annotationsrange: function(data) {
|
||||
self.options.annotationsRange = data.range;
|
||||
that.triggerEvent('annotationsrange', data);
|
||||
},
|
||||
annotationssort: function(data) {
|
||||
self.options.annotationsSort = data.sort;
|
||||
that.triggerEvent('annotationssort', data);
|
||||
},
|
||||
open: function() {
|
||||
setPosition(self.options['in']);
|
||||
},
|
||||
resize: resizeAnnotations,
|
||||
resizeend: resizeendAnnotations,
|
||||
resizecalendar: function(data) {
|
||||
that.triggerEvent('resizecalendar', data);
|
||||
},
|
||||
resizemap: function(data) {
|
||||
that.triggerEvent('resizemap', data);
|
||||
},
|
||||
select: selectAnnotation,
|
||||
toggle: toggleAnnotations,
|
||||
togglecalendar: function(data) {
|
||||
self.options.showAnnotationsCalendar = !data.collapsed;
|
||||
that.triggerEvent('togglecalendar', data);
|
||||
},
|
||||
togglelayer: function(data) {
|
||||
that.triggerEvent('togglelayer', {
|
||||
collapsed: data.collapsed,
|
||||
layer: data.layer
|
||||
});
|
||||
},
|
||||
togglemap: function(data) {
|
||||
self.options.showAnnotationsMap = !data.collapsed;
|
||||
that.triggerEvent('togglemap', data);
|
||||
}
|
||||
});
|
||||
|
||||
that.setElement(
|
||||
Ox.SplitPanel({
|
||||
elements: [
|
||||
|
@ -174,6 +254,14 @@ Ox.VideoTimelinePanel = function(options, self) {
|
|||
});
|
||||
}
|
||||
|
||||
self.setOption = function(key, value) {
|
||||
if (key == 'showAnnotations') {
|
||||
that.$element.toggle(1);
|
||||
} else if (key == 'width') {
|
||||
self.$player.options({width: value});
|
||||
}
|
||||
};
|
||||
|
||||
that.toggleAnnotations = function() {
|
||||
that.$element.toggle(1);
|
||||
};
|
||||
|
|
|
@ -10,8 +10,9 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
cuts: [],
|
||||
duration: 0,
|
||||
find: '',
|
||||
followPlayer: false,
|
||||
getFrameURL: null,
|
||||
getImageURL: null,
|
||||
getTimelineImageURL: null,
|
||||
height: 0,
|
||||
'in': 0,
|
||||
matches: [],
|
||||
|
@ -19,14 +20,17 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
out: 0,
|
||||
paused: false,
|
||||
position: 0,
|
||||
showMilliseconds: false,
|
||||
subtitles: [],
|
||||
timelineURL: '',
|
||||
timeline: '',
|
||||
timelineImageURL: '',
|
||||
timelines: [],
|
||||
video: '',
|
||||
videoRatio: 1,
|
||||
volume: 1,
|
||||
width: 0
|
||||
})
|
||||
.options(options || {})
|
||||
.addClass('OxVideoTimelinePlayer');
|
||||
.options(options || {});
|
||||
|
||||
self.fps = 25;
|
||||
self.frame = self.options.position * self.fps;
|
||||
|
@ -36,12 +40,53 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
self.margin = 8;
|
||||
self.contentWidth = self.options.width - 2 * self.margin - Ox.UI.SCROLLBAR_SIZE;
|
||||
self.contentHeight = self.options.height - 32;
|
||||
self.positionWidth = 48
|
||||
+ !!self.options.showMilliseconds * 2
|
||||
+ self.options.showMilliseconds * 6;
|
||||
self.tiles = Math.ceil(self.frames / self.tileWidth);
|
||||
self.videoWidth = Math.round(self.tileHeight * self.options.videoRatio);
|
||||
self.videoLines = getVideoLines();
|
||||
self.lines = getLines();
|
||||
|
||||
self.$topBar = Ox.Bar({size: 16});
|
||||
self.$menubar = Ox.Bar({size: 16});
|
||||
|
||||
self.$menuButton = Ox.MenuButton({
|
||||
items: [
|
||||
{id: 'timelines', title: 'Timeline', disabled: true},
|
||||
{group: 'timeline', min: 1, max: 1, items: Ox.map(
|
||||
self.options.timelines,
|
||||
function(timeline) {
|
||||
return Ox.extend({
|
||||
checked: timeline.id == self.options.timeline,
|
||||
disabled: true
|
||||
}, timeline);
|
||||
}
|
||||
)},
|
||||
{},
|
||||
{
|
||||
id: 'followPlayer',
|
||||
title: 'Follow Player While Playing',
|
||||
checked: self.options.followPlayer
|
||||
}
|
||||
],
|
||||
style: 'square',
|
||||
title: 'set',
|
||||
tooltip: 'Options',
|
||||
type: 'image'
|
||||
})
|
||||
.css({float: 'left'})
|
||||
.bindEvent({
|
||||
change: function(data) {
|
||||
var id = data.id;
|
||||
if (id == 'timeline') {
|
||||
// ...
|
||||
} else if (id == 'followPlayer') {
|
||||
// ...
|
||||
}
|
||||
Ox.print('DATA:::::::::', data);
|
||||
}
|
||||
})
|
||||
.appendTo(self.$menubar);
|
||||
|
||||
self.$content = Ox.Element()
|
||||
.addClass('OxVideoTimelinePlayer')
|
||||
|
@ -58,10 +103,14 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
mousedown: function() {
|
||||
this.gainFocus();
|
||||
},
|
||||
key_0: toggleMuted,
|
||||
key_down: function() {
|
||||
self.options.position += self.contentWidth / self.fps;
|
||||
setPosition();
|
||||
},
|
||||
key_equal: function() {
|
||||
changeVolume(0.1);
|
||||
},
|
||||
key_enter: function() {
|
||||
scrollToPosition();
|
||||
},
|
||||
|
@ -69,6 +118,9 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
self.options.position -= self.videoWidth / self.fps;
|
||||
setPosition();
|
||||
},
|
||||
key_minus: function() {
|
||||
changeVolume(-0.1);
|
||||
},
|
||||
key_right: function() {
|
||||
self.options.position += self.videoWidth / self.fps;
|
||||
setPosition();
|
||||
|
@ -91,7 +143,8 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
|
||||
});
|
||||
|
||||
self.$bottomBar = Ox.Bar({size: 16});
|
||||
self.$playerbar = Ox.Bar({size: 16});
|
||||
|
||||
self.$playButton = Ox.Button({
|
||||
style: 'symbol',
|
||||
title: 'play',
|
||||
|
@ -105,65 +158,75 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
togglePaused();
|
||||
}
|
||||
})
|
||||
.appendTo(self.$bottomBar);
|
||||
.appendTo(self.$playerbar);
|
||||
|
||||
self.$muteButton = Ox.Button({
|
||||
style: 'symbol',
|
||||
title: 'mute',
|
||||
type: 'image'
|
||||
})
|
||||
.css({
|
||||
float: 'left'
|
||||
})
|
||||
.css({float: 'left'})
|
||||
.bindEvent({
|
||||
click: toggleMuted
|
||||
})
|
||||
.appendTo(self.$playerbar);
|
||||
|
||||
})
|
||||
.appendTo(self.$bottomBar);
|
||||
self.$smallTimeline = $('<div>')
|
||||
self.$smallTimeline = getSmallTimeline().appendTo(self.$playerbar);
|
||||
|
||||
self.$position = Ox.Element()
|
||||
.addClass('OxPosition')
|
||||
.css({
|
||||
float: 'left',
|
||||
width: self.options.width - 80 + 'px',
|
||||
height: '16px',
|
||||
borderRadius: '8px',
|
||||
background: 'rgb(0, 0, 0)'
|
||||
width: self.positionWidth - 4 + 'px',
|
||||
})
|
||||
.appendTo(self.$bottomBar);
|
||||
self.$smallTimelineImage = $('<img>')
|
||||
.attr({
|
||||
src: self.options.timelineURL
|
||||
.html(formatPosition())
|
||||
.bind({
|
||||
click: function() {
|
||||
if (!self.options.paused) {
|
||||
self.playOnSubmit = true;
|
||||
togglePaused();
|
||||
}
|
||||
self.$position.hide();
|
||||
self.$positionInput
|
||||
.value(formatPosition())
|
||||
.show()
|
||||
.focusInput(false);
|
||||
}
|
||||
})
|
||||
.css({
|
||||
width: self.options.width - 96 + 'px',
|
||||
height: '16px',
|
||||
margin: '0 8px 0 8px'
|
||||
.appendTo(self.$playerbar);
|
||||
|
||||
self.$positionInput = Ox.Input({
|
||||
value: formatPosition(),
|
||||
width: self.positionWidth
|
||||
})
|
||||
.appendTo(self.$smallTimeline);
|
||||
self.$position = $('<div>')
|
||||
.css({
|
||||
float: 'left',
|
||||
width: '40px',
|
||||
height: '12px',
|
||||
padding: '2px 4px 2px 4px',
|
||||
.addClass('OxPositionInput')
|
||||
.bindEvent({
|
||||
blur: submitPositionInput,
|
||||
submit: submitPositionInput
|
||||
})
|
||||
.appendTo(self.$playerbar);
|
||||
|
||||
self.$positionInput.children('input').css({
|
||||
width: (self.positionWidth - 6) + 'px',
|
||||
fontSize: '9px'
|
||||
})
|
||||
.html(Ox.formatDuration(self.options.position))
|
||||
.appendTo(self.$bottomBar);
|
||||
});
|
||||
|
||||
self.$panel = Ox.SplitPanel({
|
||||
elements: [
|
||||
{
|
||||
element: self.$topBar,
|
||||
element: self.$menubar,
|
||||
size: 16
|
||||
},
|
||||
{
|
||||
element: self.$content
|
||||
},
|
||||
{
|
||||
element: self.$bottomBar,
|
||||
element: self.$playerbar,
|
||||
size: 16
|
||||
}
|
||||
],
|
||||
orientation: 'vertical'
|
||||
});
|
||||
})
|
||||
.addClass('OxVideoTimelinePlayer');
|
||||
|
||||
that.setElement(self.$panel);
|
||||
|
||||
|
@ -189,6 +252,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
background: 'rgb(0, 0, 0)'
|
||||
})
|
||||
.appendTo(self.$timelines[self.videoLines[1]][0]);
|
||||
|
||||
self.$frame = $('<img>')
|
||||
.attr({
|
||||
src: self.options.getFrameURL(self.options.position)
|
||||
|
@ -198,6 +262,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
height: self.tileHeight + 'px',
|
||||
})
|
||||
.appendTo(self.$frameBox)
|
||||
|
||||
$('<div>')
|
||||
.addClass('OxFrameInterface')
|
||||
.css({
|
||||
|
@ -222,13 +287,14 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
zIndex: 5
|
||||
})
|
||||
.appendTo(self.$timelines[self.videoLines[0]][0]);
|
||||
|
||||
self.$video = Ox.VideoPlayer({
|
||||
duration: self.options.duration,
|
||||
height: self.tileHeight,
|
||||
paused: self.options.paused,
|
||||
position: self.options.position,
|
||||
scaleToFill: true,
|
||||
video: self.options.videoURL,
|
||||
video: self.options.video,
|
||||
width: self.videoWidth
|
||||
})
|
||||
.bindEvent({
|
||||
|
@ -241,6 +307,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
}
|
||||
})
|
||||
.appendTo(self.$videoBox);
|
||||
|
||||
$('<div>')
|
||||
.addClass('OxFrameInterface OxVideoInterface')
|
||||
.css({
|
||||
|
@ -291,6 +358,16 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
|
||||
}
|
||||
|
||||
function changeVolume(num) {
|
||||
self.options.volume = Ox.limit(self.options.volume + num, 0, 1);
|
||||
setVolume();
|
||||
}
|
||||
|
||||
function formatPosition(position) {
|
||||
position = Ox.isUndefined(position) ? self.options.position : position;
|
||||
return Ox.formatDuration(position, self.options.showMilliseconds);
|
||||
}
|
||||
|
||||
function getLines() {
|
||||
return Math.ceil((self.frames - 1 + self.videoWidth) / self.contentWidth)
|
||||
}
|
||||
|
@ -302,6 +379,38 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
) / self.fps;
|
||||
}
|
||||
|
||||
function getSmallTimeline() {
|
||||
var $timeline = Ox.SmallVideoTimeline({
|
||||
duration: self.options.duration,
|
||||
paused: self.options.paused,
|
||||
position: self.options.position,
|
||||
showMilliseconds: self.options.showMilliseconds,
|
||||
timeline: self.options.timelineImageURL,
|
||||
type: 'player',
|
||||
width: getSmallTimelineWidth()
|
||||
})
|
||||
.css({float: 'left'})
|
||||
.css({background: '-moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5))'})
|
||||
.css({background: '-o-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5))'})
|
||||
.css({background: '-webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(64, 64, 64, 0.5))'})
|
||||
.bindEvent({
|
||||
position: function(data) {
|
||||
self.options.position = data.position;
|
||||
setPosition();
|
||||
that.triggerEvent('position', {
|
||||
position: self.options.position
|
||||
});
|
||||
}
|
||||
});
|
||||
$timeline.children().css({marginLeft: '32px'});
|
||||
$timeline.find('.OxInterface').css({marginLeft: '32px'});
|
||||
return $timeline;
|
||||
}
|
||||
|
||||
function getSmallTimelineWidth() {
|
||||
return self.options.width - 32 - self.positionWidth;
|
||||
}
|
||||
|
||||
function getSubtitle(position) {
|
||||
var subtitle = '';
|
||||
Ox.forEach(self.options.subtitles, function(v) {
|
||||
|
@ -394,7 +503,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
Ox.loop(self.tiles, function(i) {
|
||||
$('<img>')
|
||||
.attr({
|
||||
src: self.options.getImageURL(i)
|
||||
src: self.options.getTimelineImageURL(i)
|
||||
})
|
||||
.css({
|
||||
position: 'absolute',
|
||||
|
@ -471,7 +580,8 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
});
|
||||
scrollToPosition();
|
||||
}
|
||||
self.$position.html(Ox.formatDuration(self.options.position))
|
||||
self.$smallTimeline.options({position: self.options.position});
|
||||
self.$position.html(formatPosition())
|
||||
}
|
||||
|
||||
function setSubtitles() {
|
||||
|
@ -492,6 +602,13 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
});
|
||||
}
|
||||
|
||||
function setVolume() {
|
||||
self.$video.options({volume: self.options.volume});
|
||||
that.triggerEvent('volume', {
|
||||
volume: self.options.volume
|
||||
});
|
||||
}
|
||||
|
||||
function setWidth() {
|
||||
self.contentWidth = self.options.width - 2 * self.margin - Ox.UI.SCROLLBAR_SIZE;
|
||||
self.lines = getLines();
|
||||
|
@ -515,6 +632,32 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
self.$lines.pop();
|
||||
self.$timelines.pop();
|
||||
}
|
||||
self.$smallTimeline.options({width: getSmallTimelineWidth()})
|
||||
}
|
||||
|
||||
function submitPositionInput() {
|
||||
self.$positionInput.hide();
|
||||
self.$position.html('').show();
|
||||
self.options.position = Ox.parseDuration(self.$positionInput.value());
|
||||
setPosition();
|
||||
if (self.playOnSubmit) {
|
||||
togglePaused();
|
||||
self.playOnSubmit = false;
|
||||
}
|
||||
that.triggerEvent('position', {
|
||||
position: self.options.position
|
||||
});
|
||||
}
|
||||
|
||||
function toggleMuted() {
|
||||
self.options.muted = !self.options.muted;
|
||||
self.$video.options({muted: self.options.muted});
|
||||
self.$muteButton.options({
|
||||
title: self.options.muted ? 'unmute' : 'mute'
|
||||
});
|
||||
that.triggerEvent('muted', {
|
||||
muted: self.options.muted
|
||||
});
|
||||
}
|
||||
|
||||
function togglePaused(fromVideo) {
|
||||
|
@ -523,7 +666,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
|
|||
paused: self.options.paused
|
||||
});
|
||||
self.$playButton.options({
|
||||
title: !self.options.paused ? 'pause' : 'play'
|
||||
title: self.options.paused ? 'play' : 'pause'
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue