update timeline panel and timeline player

This commit is contained in:
rlx 2012-04-17 12:01:24 +00:00
parent 675257febe
commit 0e8bfd1348
2 changed files with 288 additions and 57 deletions

View file

@ -21,6 +21,9 @@ Ox.VideoTimelinePanel = function(options, self) {
clickLink: null, clickLink: null,
cuts: [], cuts: [],
duration: 0, duration: 0,
followPlayer: false,
getFrameURL: null,
getTimelineImageURL: null,
height: 0, height: 0,
layers: [], layers: [],
loop: false, // fixme: used? loop: false, // fixme: used?
@ -36,6 +39,9 @@ Ox.VideoTimelinePanel = function(options, self) {
showLayers: {}, showLayers: {},
showUsers: false, showUsers: false,
subtitles: [], subtitles: [],
timeline: '',
timelineImageURL: '',
timelines: [],
video: '', video: '',
volume: 1, volume: 1,
width: 0 width: 0
@ -60,12 +66,23 @@ Ox.VideoTimelinePanel = function(options, self) {
self.$player = Ox.VideoTimelinePlayer({ self.$player = Ox.VideoTimelinePlayer({
censored: self.options.censored, censored: self.options.censored,
cuts: self.options.cuts, 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, muted: self.options.muted,
paused: true, paused: true,
position: self.options.position, position: self.options.position,
resolution: self.options.resolution, 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({ .bindEvent({
muted: function(data) { 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( that.setElement(
Ox.SplitPanel({ Ox.SplitPanel({
elements: [ 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.toggleAnnotations = function() {
that.$element.toggle(1); that.$element.toggle(1);
}; };

View file

@ -10,8 +10,9 @@ Ox.VideoTimelinePlayer = function(options, self) {
cuts: [], cuts: [],
duration: 0, duration: 0,
find: '', find: '',
followPlayer: false,
getFrameURL: null, getFrameURL: null,
getImageURL: null, getTimelineImageURL: null,
height: 0, height: 0,
'in': 0, 'in': 0,
matches: [], matches: [],
@ -19,14 +20,17 @@ Ox.VideoTimelinePlayer = function(options, self) {
out: 0, out: 0,
paused: false, paused: false,
position: 0, position: 0,
showMilliseconds: false,
subtitles: [], subtitles: [],
timelineURL: '', timeline: '',
timelineImageURL: '',
timelines: [],
video: '',
videoRatio: 1, videoRatio: 1,
volume: 1, volume: 1,
width: 0 width: 0
}) })
.options(options || {}) .options(options || {});
.addClass('OxVideoTimelinePlayer');
self.fps = 25; self.fps = 25;
self.frame = self.options.position * self.fps; self.frame = self.options.position * self.fps;
@ -36,12 +40,53 @@ Ox.VideoTimelinePlayer = function(options, self) {
self.margin = 8; self.margin = 8;
self.contentWidth = self.options.width - 2 * self.margin - Ox.UI.SCROLLBAR_SIZE; self.contentWidth = self.options.width - 2 * self.margin - Ox.UI.SCROLLBAR_SIZE;
self.contentHeight = self.options.height - 32; 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.tiles = Math.ceil(self.frames / self.tileWidth);
self.videoWidth = Math.round(self.tileHeight * self.options.videoRatio); self.videoWidth = Math.round(self.tileHeight * self.options.videoRatio);
self.videoLines = getVideoLines(); self.videoLines = getVideoLines();
self.lines = getLines(); 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() self.$content = Ox.Element()
.addClass('OxVideoTimelinePlayer') .addClass('OxVideoTimelinePlayer')
@ -58,10 +103,14 @@ Ox.VideoTimelinePlayer = function(options, self) {
mousedown: function() { mousedown: function() {
this.gainFocus(); this.gainFocus();
}, },
key_0: toggleMuted,
key_down: function() { key_down: function() {
self.options.position += self.contentWidth / self.fps; self.options.position += self.contentWidth / self.fps;
setPosition(); setPosition();
}, },
key_equal: function() {
changeVolume(0.1);
},
key_enter: function() { key_enter: function() {
scrollToPosition(); scrollToPosition();
}, },
@ -69,6 +118,9 @@ Ox.VideoTimelinePlayer = function(options, self) {
self.options.position -= self.videoWidth / self.fps; self.options.position -= self.videoWidth / self.fps;
setPosition(); setPosition();
}, },
key_minus: function() {
changeVolume(-0.1);
},
key_right: function() { key_right: function() {
self.options.position += self.videoWidth / self.fps; self.options.position += self.videoWidth / self.fps;
setPosition(); 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({ self.$playButton = Ox.Button({
style: 'symbol', style: 'symbol',
title: 'play', title: 'play',
@ -105,65 +158,75 @@ Ox.VideoTimelinePlayer = function(options, self) {
togglePaused(); togglePaused();
} }
}) })
.appendTo(self.$bottomBar); .appendTo(self.$playerbar);
self.$muteButton = Ox.Button({ self.$muteButton = Ox.Button({
style: 'symbol', style: 'symbol',
title: 'mute', title: 'mute',
type: 'image' type: 'image'
}) })
.css({ .css({float: 'left'})
float: 'left'
})
.bindEvent({ .bindEvent({
click: toggleMuted
})
.appendTo(self.$playerbar);
}) self.$smallTimeline = getSmallTimeline().appendTo(self.$playerbar);
.appendTo(self.$bottomBar);
self.$smallTimeline = $('<div>') self.$position = Ox.Element()
.addClass('OxPosition')
.css({ .css({
float: 'left', width: self.positionWidth - 4 + 'px',
width: self.options.width - 80 + 'px',
height: '16px',
borderRadius: '8px',
background: 'rgb(0, 0, 0)'
}) })
.appendTo(self.$bottomBar); .html(formatPosition())
self.$smallTimelineImage = $('<img>') .bind({
.attr({ click: function() {
src: self.options.timelineURL if (!self.options.paused) {
self.playOnSubmit = true;
togglePaused();
}
self.$position.hide();
self.$positionInput
.value(formatPosition())
.show()
.focusInput(false);
}
}) })
.css({ .appendTo(self.$playerbar);
width: self.options.width - 96 + 'px',
height: '16px', self.$positionInput = Ox.Input({
margin: '0 8px 0 8px' value: formatPosition(),
width: self.positionWidth
}) })
.appendTo(self.$smallTimeline); .addClass('OxPositionInput')
self.$position = $('<div>') .bindEvent({
.css({ blur: submitPositionInput,
float: 'left', submit: submitPositionInput
width: '40px', })
height: '12px', .appendTo(self.$playerbar);
padding: '2px 4px 2px 4px',
self.$positionInput.children('input').css({
width: (self.positionWidth - 6) + 'px',
fontSize: '9px' fontSize: '9px'
}) });
.html(Ox.formatDuration(self.options.position))
.appendTo(self.$bottomBar);
self.$panel = Ox.SplitPanel({ self.$panel = Ox.SplitPanel({
elements: [ elements: [
{ {
element: self.$topBar, element: self.$menubar,
size: 16 size: 16
}, },
{ {
element: self.$content element: self.$content
}, },
{ {
element: self.$bottomBar, element: self.$playerbar,
size: 16 size: 16
} }
], ],
orientation: 'vertical' orientation: 'vertical'
}); })
.addClass('OxVideoTimelinePlayer');
that.setElement(self.$panel); that.setElement(self.$panel);
@ -189,6 +252,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
background: 'rgb(0, 0, 0)' background: 'rgb(0, 0, 0)'
}) })
.appendTo(self.$timelines[self.videoLines[1]][0]); .appendTo(self.$timelines[self.videoLines[1]][0]);
self.$frame = $('<img>') self.$frame = $('<img>')
.attr({ .attr({
src: self.options.getFrameURL(self.options.position) src: self.options.getFrameURL(self.options.position)
@ -198,6 +262,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
height: self.tileHeight + 'px', height: self.tileHeight + 'px',
}) })
.appendTo(self.$frameBox) .appendTo(self.$frameBox)
$('<div>') $('<div>')
.addClass('OxFrameInterface') .addClass('OxFrameInterface')
.css({ .css({
@ -222,13 +287,14 @@ Ox.VideoTimelinePlayer = function(options, self) {
zIndex: 5 zIndex: 5
}) })
.appendTo(self.$timelines[self.videoLines[0]][0]); .appendTo(self.$timelines[self.videoLines[0]][0]);
self.$video = Ox.VideoPlayer({ self.$video = Ox.VideoPlayer({
duration: self.options.duration, duration: self.options.duration,
height: self.tileHeight, height: self.tileHeight,
paused: self.options.paused, paused: self.options.paused,
position: self.options.position, position: self.options.position,
scaleToFill: true, scaleToFill: true,
video: self.options.videoURL, video: self.options.video,
width: self.videoWidth width: self.videoWidth
}) })
.bindEvent({ .bindEvent({
@ -241,6 +307,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
} }
}) })
.appendTo(self.$videoBox); .appendTo(self.$videoBox);
$('<div>') $('<div>')
.addClass('OxFrameInterface OxVideoInterface') .addClass('OxFrameInterface OxVideoInterface')
.css({ .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() { function getLines() {
return Math.ceil((self.frames - 1 + self.videoWidth) / self.contentWidth) return Math.ceil((self.frames - 1 + self.videoWidth) / self.contentWidth)
} }
@ -302,6 +379,38 @@ Ox.VideoTimelinePlayer = function(options, self) {
) / self.fps; ) / 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) { function getSubtitle(position) {
var subtitle = ''; var subtitle = '';
Ox.forEach(self.options.subtitles, function(v) { Ox.forEach(self.options.subtitles, function(v) {
@ -394,7 +503,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
Ox.loop(self.tiles, function(i) { Ox.loop(self.tiles, function(i) {
$('<img>') $('<img>')
.attr({ .attr({
src: self.options.getImageURL(i) src: self.options.getTimelineImageURL(i)
}) })
.css({ .css({
position: 'absolute', position: 'absolute',
@ -471,7 +580,8 @@ Ox.VideoTimelinePlayer = function(options, self) {
}); });
scrollToPosition(); scrollToPosition();
} }
self.$position.html(Ox.formatDuration(self.options.position)) self.$smallTimeline.options({position: self.options.position});
self.$position.html(formatPosition())
} }
function setSubtitles() { 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() { function setWidth() {
self.contentWidth = self.options.width - 2 * self.margin - Ox.UI.SCROLLBAR_SIZE; self.contentWidth = self.options.width - 2 * self.margin - Ox.UI.SCROLLBAR_SIZE;
self.lines = getLines(); self.lines = getLines();
@ -515,6 +632,32 @@ Ox.VideoTimelinePlayer = function(options, self) {
self.$lines.pop(); self.$lines.pop();
self.$timelines.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) { function togglePaused(fromVideo) {
@ -523,7 +666,7 @@ Ox.VideoTimelinePlayer = function(options, self) {
paused: self.options.paused paused: self.options.paused
}); });
self.$playButton.options({ self.$playButton.options({
title: !self.options.paused ? 'pause' : 'play' title: self.options.paused ? 'play' : 'pause'
}); });
} }