add large timeline to video
This commit is contained in:
parent
e60ac585d4
commit
e10ab53030
3 changed files with 295 additions and 11 deletions
|
@ -85,7 +85,10 @@ Ox.load('UI', {
|
||||||
enableVolume: true,
|
enableVolume: true,
|
||||||
externalControls: true,
|
externalControls: true,
|
||||||
height: 192,
|
height: 192,
|
||||||
'in': 3128.725,
|
'in': 3128.725,
|
||||||
|
largeTimeline: function(i) {
|
||||||
|
return 'http://next.0xdb.org/' + id + '/timelines/timeline.64.' + i + '.png';
|
||||||
|
},
|
||||||
out: 3130.725,
|
out: 3130.725,
|
||||||
paused: true,
|
paused: true,
|
||||||
showMilliseconds: 2,
|
showMilliseconds: 2,
|
||||||
|
|
232
source/Ox.UI/js/Video/Ox.LargeVideoTimeline.js
Normal file
232
source/Ox.UI/js/Video/Ox.LargeVideoTimeline.js
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
// vim: et:ts=4:sw=4:sts=4:ft=js
|
||||||
|
|
||||||
|
/*@
|
||||||
|
Ox.LargeVideoTimeline <f:Ox.Element> LargeTimeline Object
|
||||||
|
() -> <f> LargeTimeline Object
|
||||||
|
(options) -> <f> LargeTimeline Object
|
||||||
|
(options, self) -> <f> LargeTimeline Object
|
||||||
|
options <o> Options object
|
||||||
|
self <o> shared private variable
|
||||||
|
@*/
|
||||||
|
|
||||||
|
Ox.LargeVideoTimeline = function(options, self) {
|
||||||
|
|
||||||
|
var self = self || {},
|
||||||
|
that = new Ox.Element({}, self)
|
||||||
|
.defaults({
|
||||||
|
cuts: [],
|
||||||
|
duration: 0,
|
||||||
|
find: '',
|
||||||
|
getImageURL: null,
|
||||||
|
'in': 0,
|
||||||
|
matches: [],
|
||||||
|
out: 0,
|
||||||
|
position: 0,
|
||||||
|
style: 'default', // fixme: there are no different styles yet
|
||||||
|
subtitles: [],
|
||||||
|
type: 'player',
|
||||||
|
width: 0
|
||||||
|
})
|
||||||
|
.options(options || {})
|
||||||
|
.addClass('OxTimelineLarge')
|
||||||
|
.mouseleave(mouseleave)
|
||||||
|
.mousemove(mousemove)
|
||||||
|
.bindEvent({
|
||||||
|
anyclick: click,
|
||||||
|
dragstart: dragstart,
|
||||||
|
drag: drag
|
||||||
|
});
|
||||||
|
|
||||||
|
$.extend(self, {
|
||||||
|
$cuts: [],
|
||||||
|
$markerPoint: {},
|
||||||
|
$tiles: {},
|
||||||
|
$tooltip: new Ox.Tooltip({
|
||||||
|
animate: false
|
||||||
|
}),
|
||||||
|
center: parseInt(self.options.width / 2),
|
||||||
|
element: that.$element[0],
|
||||||
|
fps: 25,
|
||||||
|
height: 64,
|
||||||
|
tileWidth: 1500
|
||||||
|
});
|
||||||
|
self.tiles = self.options.duration * self.fps / self.tileWidth;
|
||||||
|
|
||||||
|
self.$timeline = $('<div>')
|
||||||
|
.css({
|
||||||
|
left: self.center + 'px'
|
||||||
|
})
|
||||||
|
.appendTo(that.$element)
|
||||||
|
|
||||||
|
setSubtitles();
|
||||||
|
|
||||||
|
self.options.cuts.forEach(function(v, i) {
|
||||||
|
self.$cuts[i] = $('<img>')
|
||||||
|
.addClass('OxCut')
|
||||||
|
.attr({
|
||||||
|
src: Ox.UI.PATH + 'png/videoMarkerCut.png'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
left: (v * self.fps) + 'px'
|
||||||
|
})
|
||||||
|
.appendTo(self.$timeline)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.$markerPosition = $('<img>')
|
||||||
|
.addClass('OxMarkerPosition')
|
||||||
|
.attr({
|
||||||
|
src: Ox.UI.PATH + 'png/videoMarkerPlay.png'
|
||||||
|
})
|
||||||
|
.appendTo(that.$element);
|
||||||
|
setMarker();
|
||||||
|
|
||||||
|
['in', 'out'].forEach(function(point) {
|
||||||
|
var titlecase = Ox.toTitleCase(point);
|
||||||
|
self.$markerPoint[point] = $('<img>')
|
||||||
|
.addClass('OxMarkerPoint' + titlecase)
|
||||||
|
.attr({
|
||||||
|
src: Ox.UI.PATH + 'png/videoMarker' + titlecase + '.png'
|
||||||
|
})
|
||||||
|
.appendTo(self.$timeline);
|
||||||
|
setMarkerPoint(point);
|
||||||
|
});
|
||||||
|
|
||||||
|
setWidth();
|
||||||
|
setPosition();
|
||||||
|
|
||||||
|
function click(event, e) {
|
||||||
|
self.options.position = Ox.limit(
|
||||||
|
getPosition(e), 0, self.options.duration
|
||||||
|
);
|
||||||
|
setPosition();
|
||||||
|
triggerPositionEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragstart(event, e) {
|
||||||
|
self.drag = {x: e.clientX};
|
||||||
|
}
|
||||||
|
|
||||||
|
function drag(event, e) {
|
||||||
|
self.options.position = Ox.limit(
|
||||||
|
self.options.position + (self.drag.x - e.clientX) / self.fps,
|
||||||
|
0, self.options.duration
|
||||||
|
);
|
||||||
|
self.drag.x = e.clientX;
|
||||||
|
setPosition();
|
||||||
|
triggerPositionEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPosition(e) {
|
||||||
|
return self.options.position + (e.clientX - that.offset().left - self.center - 1) / self.fps
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseleave(e) {
|
||||||
|
self.clientX = 0;
|
||||||
|
self.clientY = 0;
|
||||||
|
self.$tooltip.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function mousemove(e) {
|
||||||
|
self.clientX = e.clientX;
|
||||||
|
self.clientY = e.clientY;
|
||||||
|
updateTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMarkerPoint(point) {
|
||||||
|
self.$markerPoint[point].css({
|
||||||
|
left: (self.options[point] * self.fps) + 'px'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMarker() {
|
||||||
|
self.$markerPosition.css({
|
||||||
|
left: (self.center - 4) + 'px',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPosition() {
|
||||||
|
self.tile = parseInt(self.options.position * self.fps / self.tileWidth);
|
||||||
|
self.$timeline.css({
|
||||||
|
marginLeft: (-self.options.position * self.fps) + 'px'
|
||||||
|
});
|
||||||
|
Ox.loop(
|
||||||
|
Math.max(self.tile - 1, 0),
|
||||||
|
Math.min(self.tile + 2, self.tiles),
|
||||||
|
function(i) {
|
||||||
|
if (!self.$tiles[i]) {
|
||||||
|
self.$tiles[i] = $('<img>')
|
||||||
|
.attr({
|
||||||
|
src: self.options.getImageURL(i)
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
left: (i * self.tileWidth) + 'px'
|
||||||
|
})
|
||||||
|
.appendTo(self.$timeline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (self.clientX && self.clientY) {
|
||||||
|
updateTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSubtitles() {
|
||||||
|
self.$subtitles = [];
|
||||||
|
self.options.subtitles.forEach(function(subtitle, i) {
|
||||||
|
self.$subtitles[i] = $('<div>')
|
||||||
|
.addClass('OxSubtitle' + (self.options.matches.indexOf(i) > -1 ? ' OxHighlight' : ''))
|
||||||
|
.css({
|
||||||
|
left: (subtitle['in'] * self.fps) + 'px',
|
||||||
|
width: (((subtitle.out - subtitle['in']) * self.fps) - 2) + 'px'
|
||||||
|
})
|
||||||
|
.html(Ox.highlight(subtitle.text, self.options.find, 'OxHighlight'))
|
||||||
|
.appendTo(self.$timeline)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setWidth() {
|
||||||
|
self.center = parseInt(self.options.width / 2);
|
||||||
|
that.css({
|
||||||
|
width: self.options.width + 'px'
|
||||||
|
});
|
||||||
|
self.$timeline.css({
|
||||||
|
left: self.center + 'px'
|
||||||
|
});
|
||||||
|
setMarker();
|
||||||
|
}
|
||||||
|
|
||||||
|
function triggerPositionEvent() {
|
||||||
|
that.triggerEvent('position', {
|
||||||
|
position: self.options.position
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTooltip() {
|
||||||
|
var position = getPosition(self);
|
||||||
|
if (position >= 0 && position <= self.options.duration) {
|
||||||
|
self.$tooltip
|
||||||
|
.options({
|
||||||
|
title: Ox.formatDuration(position, 3)
|
||||||
|
})
|
||||||
|
.show(self.clientX, self.clientY);
|
||||||
|
} else {
|
||||||
|
self.$tooltip.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setOption = function(key, value) {
|
||||||
|
if (key == 'points') {
|
||||||
|
setMarkerPoint('in');
|
||||||
|
setMarkerPoint('out');
|
||||||
|
} else if (key == 'position') {
|
||||||
|
setPosition();
|
||||||
|
} else if (key == 'subtitles') {
|
||||||
|
|
||||||
|
} else if (key == 'width') {
|
||||||
|
setWidth();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return that;
|
||||||
|
|
||||||
|
};
|
|
@ -85,6 +85,7 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
keepIconVisible: false,
|
keepIconVisible: false,
|
||||||
keepLargeTimelineVisible: false,
|
keepLargeTimelineVisible: false,
|
||||||
keepLogoVisible: false,
|
keepLogoVisible: false,
|
||||||
|
largeTimeline: false,
|
||||||
logo: '',
|
logo: '',
|
||||||
logoLink: '',
|
logoLink: '',
|
||||||
logoTitle: '',
|
logoTitle: '',
|
||||||
|
@ -220,12 +221,14 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
self.results = find(self.options.find);
|
self.results = find(self.options.find);
|
||||||
Ox.print('--setting results--', self.$timeline)
|
Ox.print('--setting results--', self.$timeline)
|
||||||
if (self.options.duration) {
|
if (self.options.duration) {
|
||||||
|
// video has loaded
|
||||||
self.$timeline && self.$timeline.options({
|
self.$timeline && self.$timeline.options({
|
||||||
results: self.results,
|
results: self.results,
|
||||||
subtitles: self.options.subtitles
|
subtitles: self.options.subtitles
|
||||||
});
|
});
|
||||||
} else {
|
self.$largeTimeline && self.$largeTimeline.options({
|
||||||
|
subtitles: self.options.subtitles
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.options.subtitles = [];
|
self.options.subtitles = [];
|
||||||
|
@ -864,6 +867,20 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self.options.largeTimeline) {
|
||||||
|
|
||||||
|
if (self.options.duration) {
|
||||||
|
self.$largeTimeline = getLargeTimeline()
|
||||||
|
} else {
|
||||||
|
self.$largeTimeline = Ox.Element()
|
||||||
|
.css({
|
||||||
|
float: 'left'
|
||||||
|
})
|
||||||
|
.html(' ');
|
||||||
|
}
|
||||||
|
self.$largeTimeline.appendTo(that);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
setSizes();
|
setSizes();
|
||||||
|
|
||||||
|
@ -1092,6 +1109,31 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
return subtitle;
|
return subtitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLargeTimeline() {
|
||||||
|
var $timeline = Ox.LargeVideoTimeline({
|
||||||
|
duration: self.options.duration,
|
||||||
|
find: self.options.find,
|
||||||
|
getImageURL: self.options.largeTimeline,
|
||||||
|
'in': self.options['in'],
|
||||||
|
out: self.options.out,
|
||||||
|
position: self.options.position,
|
||||||
|
subtitles: self.options.subtitles,
|
||||||
|
type: 'player',
|
||||||
|
width: self.options.width
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '12px',
|
||||||
|
marginLeft: 0,
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
position: function(data) {
|
||||||
|
setPosition(data.position, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return $timeline;
|
||||||
|
}
|
||||||
|
|
||||||
function getTimeline() {
|
function getTimeline() {
|
||||||
var $timeline = Ox.SmallVideoTimeline({
|
var $timeline = Ox.SmallVideoTimeline({
|
||||||
_offset: getTimelineLeft(),
|
_offset: getTimelineLeft(),
|
||||||
|
@ -1239,13 +1281,13 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.$timeline) {
|
if (!hadDuration) {
|
||||||
if (!hadDuration) {
|
self.$timeline && self.$timeline.replaceWith(
|
||||||
self.$timeline.replaceWith(self.$timeline = getTimeline());
|
self.$timeline = getTimeline()
|
||||||
}
|
);
|
||||||
self.$timeline.options({
|
self.$largeTimeline && self.$largeTimeline.replaceWith(
|
||||||
duration: self.options.duration
|
self.$largeTimeline = getLargeTimeline()
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.options.enableKeyboard && self.options.focus == 'load') {
|
if (self.options.enableKeyboard && self.options.focus == 'load') {
|
||||||
|
@ -1338,9 +1380,13 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
self.posterIsVisible = false;
|
self.posterIsVisible = false;
|
||||||
}
|
}
|
||||||
self.$subtitle && setSubtitle();
|
self.$subtitle && setSubtitle();
|
||||||
|
// fixme: setPosition may have been called from these timelines
|
||||||
self.$timeline && self.$timeline.options({
|
self.$timeline && self.$timeline.options({
|
||||||
position: self.options.position
|
position: self.options.position
|
||||||
});
|
});
|
||||||
|
self.$largeTimeline && self.$largeTimeline.options({
|
||||||
|
position: self.options.position
|
||||||
|
});
|
||||||
self.$position && self.$position.html(formatPosition());
|
self.$position && self.$position.html(formatPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1392,9 +1438,12 @@ Ox.VideoPlayer = function(options, self) {
|
||||||
if (self.$volume) {
|
if (self.$volume) {
|
||||||
self.$volume.animate(getCSS('volume'), ms);
|
self.$volume.animate(getCSS('volume'), ms);
|
||||||
self.$volumeInput.options({
|
self.$volumeInput.options({
|
||||||
size: Math.min(128, self.width - 56)
|
size: Math.min(128, self.width - 56) // fixme: should be width in Ox.Range
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
self.$largeTimeline && self.$largeTimeline.options({
|
||||||
|
width: self.width
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSubtitle() {
|
function setSubtitle() {
|
||||||
|
|
Loading…
Reference in a new issue