Skip to content

Commit

Permalink
add animation support.
Browse files Browse the repository at this point in the history
  • Loading branch information
yanwsh committed Jul 9, 2017
1 parent 5cf9726 commit 5808626
Show file tree
Hide file tree
Showing 11 changed files with 353 additions and 38 deletions.
55 changes: 44 additions & 11 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@
top: 0;
left: 0;
}
.vjs-marker{
white-space: normal;
width: 100px;
font-size: 2em;
}
</style>
</head>
<body>
<div class="player_wrapper">
<div class="player_container">
<video id="videojs-panorama-player" class="video-js vjs-default-skin" crossorigin="anonymous" controls>
<video id="videojs-panorama-player" class="video-js vjs-default-skin" poster="assets/poster-360.jpg" crossorigin="anonymous" controls>
<source src="assets/shark.mp4" type='video/mp4'>
</video>
</div>
Expand All @@ -50,11 +55,7 @@
return check;
}
(function(window, videojs) {
var player = window.player = videojs('videojs-panorama-player', {
poster: "assets/poster-360.jpg",
plugins: {
}
});
var player = window.player = videojs('videojs-panorama-player', {});

var panorama = player.panorama({
PanoramaThumbnail: true,
Expand All @@ -72,19 +73,51 @@
lon: 180
},
radius: 500,
element: "Marker 1",
keyPoint: 5000,
duration: 10000
element: "This is text 1 with long text"
},
{
location: {
lat: 20,
lon: 160
},
radius: 500,
element: "Marker 2",
element: "This is text 2 with long text",
onShow: function(){
console.log("text 2 is shown");
},
onHide: function(){
console.log("text 2 is hidden");
}
}
],
Animation: [
{
keyPoint: 0,
from: {
lon: 180,
},
to:{
lon: 540,
},
duration: 8000,
ease: "linear",
onComplete: function () {
console.log("animation 1 is completed");
}
},
{
keyPoint: 0,
from: {
fov: 75,
},
to:{
fov: 90,
},
duration: 5000,
ease: "linear",
}
]
],
VRGapDegree: 0
});

window.player = player;
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "videojs-panorama",
"version": "0.1.6",
"version": "1.0.0",
"description": "a plugin for videojs run a full 360 degree panorama video. ",
"keywords": [
"videojs",
Expand Down Expand Up @@ -69,4 +69,4 @@
"video.js": "global:videojs",
"three": "global:THREE"
}
}
}
169 changes: 169 additions & 0 deletions src/scripts/Components/Animation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// @flow

import type { Player, AnimationSettings } from '../types';
import BaseCanvas from './BaseCanvas';
import { mergeOptions, easeFunctions } from '../utils';

type Timeline = {
active: boolean;
initialized: boolean;
completed: boolean;
startValue: any;
byValue: any;
endValue: any;
ease?: Function;
onComplete?: Function;
keyPoint: number;
duration: number;
beginTime: number;
endTime: number;
from?: any;
to: any;
}

class Animation {
_player: Player;
_options: {
animation: AnimationSettings[];
canvas: BaseCanvas
};
_canvas: BaseCanvas;
_timeline: Timeline[];
_active: boolean;

constructor(player: Player, options: {animation: AnimationSettings[], canvas: BaseCanvas}){
this._player = player;
this._options = mergeOptions({}, this._options);
this._options = mergeOptions(this._options, options);

this._canvas = this._options.canvas;
this._timeline = [];

this._options.animation.forEach((obj: AnimationSettings) =>{
this.addTimeline(obj);
});
}

addTimeline(opt: AnimationSettings){
let timeline: Timeline = {
active: false,
initialized: false,
completed: false,
startValue: {},
byValue: {},
endValue: {},
keyPoint: opt.keyPoint,
duration: opt.duration,
beginTime: Infinity,
endTime: Infinity,
onComplete: opt.onComplete,
from: opt.from,
to: opt.to
};

if(typeof opt.ease === "string"){
timeline.ease = easeFunctions[opt.ease];
}
if(typeof opt.ease === "undefined"){
timeline.ease = easeFunctions.linear;
}

this._timeline.push(timeline);
this.attachEvents();
}

initialTimeline(timeline: Timeline){
for(let key in timeline.to){
if(timeline.to.hasOwnProperty(key)){
let from = timeline.from? (typeof timeline.from[key] !== "undefined"? timeline.from[key] : this._canvas[`_${key}`]) : this._canvas[`_${key}`];
timeline.startValue[key] = from;
timeline.endValue[key] = timeline.to[key];
timeline.byValue[key] = timeline.to[key] - from;
}
}
}

processTimeline(timeline: Timeline, animationTime: number){
for (let key in timeline.to){
if (timeline.to.hasOwnProperty(key)) {
let newVal = timeline.ease && timeline.ease(animationTime, timeline.startValue[key], timeline.byValue[key], timeline.duration);
if(key === "fov"){
this._canvas._camera.fov = newVal;
this._canvas._camera.updateProjectionMatrix();
}else{
this._canvas[`_${key}`] = newVal;
}
}
}
}

attachEvents(){
this._active = true;
this._canvas.addListener("beforeRender", this.renderAnimation.bind(this));
this._player.on("seeked", this.handleVideoSeek.bind(this));
}

detachEvents(){
this._active = false;
this._canvas.controlable = true;
this._canvas.removeListener("beforeRender", this.renderAnimation.bind(this));
}

handleVideoSeek(){
let currentTime = this._player.getVideoEl().currentTime * 1000;
let resetTimeline = 0;
this._timeline.forEach((timeline: Timeline)=>{
let res = timeline.keyPoint >= currentTime || (timeline.keyPoint <= currentTime && (timeline.keyPoint + timeline.duration) >= currentTime);
if(res){
resetTimeline++;
timeline.completed = false;
timeline.initialized = false;
}
});

if(resetTimeline > 0 && !this._active){
this.attachEvents();
}
}

renderAnimation(){
let currentTime = this._player.getVideoEl().currentTime * 1000;
let completeTimeline = 0;
let inActiveTimeline = 0;
this._timeline.filter((timeline: Timeline)=>{
if(timeline.completed) {
completeTimeline++;
return false;
}
let res = timeline.keyPoint <= currentTime && (timeline.keyPoint + timeline.duration) > currentTime;
timeline.active = res;
if(timeline.active === false) inActiveTimeline++;

if(res && !timeline.initialized){
timeline.initialized = true;
timeline.beginTime = timeline.keyPoint;
timeline.endTime = timeline.beginTime + timeline.duration;
this.initialTimeline(timeline);
}
if(timeline.endTime <= currentTime){
timeline.completed = true;
this.processTimeline(timeline, timeline.duration);
if(timeline.onComplete){
timeline.onComplete.call(this);
}
}
return res;
}).forEach((timeline: Timeline)=>{
let animationTime = currentTime - timeline.beginTime;
this.processTimeline(timeline, animationTime);
});

this._canvas.controlable = inActiveTimeline === this._timeline.length;

if(completeTimeline === this._timeline.length){
this.detachEvents();
}
}
}

export default Animation;
47 changes: 30 additions & 17 deletions src/scripts/Components/BaseCanvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class BaseCanvas extends Component{
/**
* Interaction
*/
_controlable: boolean;
_VRMode: boolean;
_mouseDown: boolean;
_mouseDownPointer: Point;
Expand Down Expand Up @@ -68,6 +69,7 @@ class BaseCanvas extends Component{
this._isUserInteracting = false;
this._runOnMobile = mobileAndTabletcheck();
this._VRMode = false;
this._controlable = true;

this._mouseDownPointer = {
x: 0,
Expand Down Expand Up @@ -363,24 +365,27 @@ class BaseCanvas extends Component{
}

render(){
if(!this._isUserInteracting){
let symbolLat = (this._lat > this.options.initLat)? -1 : 1;
let symbolLon = (this._lon > this.options.initLon)? -1 : 1;
if(this.options.backToInitLat){
this._lat = (
this._lat > (this.options.initLat - Math.abs(this.options.returnLatSpeed)) &&
this._lat < (this.options.initLat + Math.abs(this.options.returnLatSpeed))
)? this.options.initLat : this._lat + this.options.returnLatSpeed * symbolLat;
}
if(this.options.backToInitLon){
this._lon = (
this._lon > (this.options.initLon - Math.abs(this.options.returnLonSpeed)) &&
this._lon < (this.options.initLon + Math.abs(this.options.returnLonSpeed))
)? this.options.initLon : this._lon + this.options.returnLonSpeed * symbolLon;
this.trigger("beforeRender");
if(this._controlable){
if(!this._isUserInteracting){
let symbolLat = (this._lat > this.options.initLat)? -1 : 1;
let symbolLon = (this._lon > this.options.initLon)? -1 : 1;
if(this.options.backToInitLat){
this._lat = (
this._lat > (this.options.initLat - Math.abs(this.options.returnLatSpeed)) &&
this._lat < (this.options.initLat + Math.abs(this.options.returnLatSpeed))
)? this.options.initLat : this._lat + this.options.returnLatSpeed * symbolLat;
}
if(this.options.backToInitLon){
this._lon = (
this._lon > (this.options.initLon - Math.abs(this.options.returnLonSpeed)) &&
this._lon < (this.options.initLon + Math.abs(this.options.returnLonSpeed))
)? this.options.initLon : this._lon + this.options.returnLonSpeed * symbolLon;
}
}else if(this._accelector.x !== 0 && this._accelector.y !== 0){
this._lat += this._accelector.y;
this._lon += this._accelector.x;
}
}else if(this._accelector.x !== 0 && this._accelector.y !== 0){
this._lat += this._accelector.y;
this._lon += this._accelector.x;
}

if(this._options.minLon === 0 && this._options.maxLon === 360){
Expand All @@ -406,6 +411,14 @@ class BaseCanvas extends Component{
get VRMode(): boolean{
return this._VRMode;
}

get controlable(): boolean{
return this._controlable;
}

set controlable(val: boolean): void{
this._controlable = val;
}
}

export default BaseCanvas;
6 changes: 6 additions & 0 deletions src/scripts/Components/Marker.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,17 @@ class Marker extends Component{
enableMarker(){
this._enable = true;
this.addClass("vjs-marker--enable");
if(this.options.onShow){
this.options.onShow.call(null);
}
}

disableMarker(){
this._enable = false;
this.removeClass("vjs-marker--enable");
if(this.options.onHide){
this.options.onHide.call(null);
}
}

render(canvas: BaseCanvas, camera: THREE.PerspectiveCamera){
Expand Down
10 changes: 9 additions & 1 deletion src/scripts/Components/MarkerContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import BaseCanvas from './BaseCanvas';
import Component from './Component';
import MarkerGroup from './MarkerGroup';
import { mergeOptions } from '../utils';
import type { Player, MarkerSettings } from '../types';

class MarkerContainer extends Component{
Expand All @@ -24,10 +25,17 @@ class MarkerContainer extends Component{
markers: this.options.markers,
camera: this._canvas._camera
});

let markersSettings = this.options.markers.map((marker: MarkerSettings)=>{
let newMarker = mergeOptions({}, marker);
newMarker.onShow = undefined;
newMarker.onHide = undefined;
return newMarker;
});
let rightMarkerGroup = new MarkerGroup(this.player, {
id: "right_group",
canvas: this._canvas,
markers: this.options.markers,
markers: markersSettings,
camera: this._canvas._camera
});
this.addChild("leftMarkerGroup", leftMarkerGroup);
Expand Down
Loading

0 comments on commit 5808626

Please sign in to comment.