diff --git a/index.html b/index.html
index b21fadb..6a9b176 100644
--- a/index.html
+++ b/index.html
@@ -63,7 +63,27 @@
Notice: {
Enable: true,
Message: (isMobile())? "please drag and drop the video" : "please use your mouse drag and drop the video"
- }
+ },
+ Markers: [
+ {
+ location: {
+ lat: 0,
+ lon: 180
+ },
+ radius: 500,
+ element: "Marker 1",
+ keyPoint: 5000,
+ duration: 10000
+ },
+ {
+ location: {
+ lat: 20,
+ lon: 160
+ },
+ radius: 500,
+ element: "Marker 2",
+ }
+ ]
});
window.player = player;
diff --git a/src/scripts/Components/Marker.js b/src/scripts/Components/Marker.js
index 815f616..aaae5c6 100644
--- a/src/scripts/Components/Marker.js
+++ b/src/scripts/Components/Marker.js
@@ -1,19 +1,92 @@
// @flow
-import type { Player, MarkerSettings } from '../types';
+import type { Player, MarkerSettings, Point } from '../types';
+import THREE from "three";
import Component from './Component';
+import { mergeOptions } from '../utils';
const defaults = {
+ keyPoint: -1,
duration: -1
};
class Marker extends Component{
- constructor(player: Player, options: MarkerSettings){
+ _canvas: Component;
+ _position: THREE.Vector3;
+ _enable: boolean;
+
+ constructor(player: Player, options: MarkerSettings & {
+ el?: HTMLElement;
+ }){
+ let el: HTMLElement;
+
+ let elem = options.element;
+ if(typeof elem === "string"){
+ el = document.createElement('div');
+ el.innerText = elem;
+ }else {
+ el = elem;
+ }
+ el.id = options.id || "";
+ el.className = "vjs-marker";
+
+ options.el = el;
+
super(player, options);
+ this._options = mergeOptions({}, defaults, options);
+
+ this._canvas = player.getComponent("VideoCanvas");
+ let phi = THREE.Math.degToRad( 90 - options.location.lat );
+ let theta = THREE.Math.degToRad( options.location.lon );
+ this._position = new THREE.Vector3(
+ options.radius * Math.sin( phi ) * Math.cos( theta ),
+ options.radius * Math.cos( phi ),
+ options.radius * Math.sin( phi ) * Math.sin( theta ),
+ );
+ if(this.options.keyPoint > 0){
+ let timeupdate;
+ this.player.on("timeupdate", timeupdate = () => {
+ let currentTime = this.player.getVideoEl().currentTime * 1000;
+ if(this.options.duration > 0){
+ (this.options.keyPoint <= currentTime && currentTime < this.options.keyPoint + this.options.duration)?
+ !this._enable && this.attachEvents() : this._enable && this.detachEvents();
+ }else{
+ (this.options.keyPoint <= currentTime)?
+ !this._enable && this.attachEvents() : this._enable && this.detachEvents();
+ }
+ });
+ }else{
+ this.attachEvents();
+ }
+
}
attachEvents(){
+ this._enable = true;
+ this.addClass("vjs-marker--enable");
+ this._canvas.addListener("render", this.render.bind(this));
+ }
+
+ detachEvents(){
+ this._enable = false;
+ this.removeClass("vjs-marker--enable");
+ this._canvas.removeListener("render", this.render.bind(this));
+ }
+ render(){
+ let angle = this._position.angleTo(this._canvas._camera.target);
+ if(angle > Math.PI * 0.4){
+ this.addClass("vjs-marker--backside");
+ }else{
+ this.removeClass("vjs-marker--backside");
+ let vector = this._position.clone().project(this._canvas._camera);
+ let point: Point = {
+ x: (vector.x + 1) / 2 * this._canvas._width,
+ y: - (vector.y - 1) / 2 * this._canvas._height
+ };
+ this.el().style.left = `${point.x}px`;
+ this.el().style.top = `${point.y}px`;
+ }
}
}
diff --git a/src/scripts/Panorama.js b/src/scripts/Panorama.js
index 47fe792..eda5a0a 100644
--- a/src/scripts/Panorama.js
+++ b/src/scripts/Panorama.js
@@ -11,8 +11,8 @@ import ThreeDVideo from './Components/ThreeDVideo';
import Notification from './Components/Notification';
import Thumbnail from './Components/Thumbnail';
import VRButton from './Components/VRButton';
-import { Detector, webGLErrorMessage, crossDomainWarning, transitionEvent, mergeOptions, mobileAndTabletcheck, isIos, isRealIphone } from './utils';
-import { warning } from './utils/index';
+import Marker from './Components/Marker';
+import { Detector, webGLErrorMessage, crossDomainWarning, transitionEvent, mergeOptions, mobileAndTabletcheck, isIos, isRealIphone, warning } from './utils';
const runOnMobile = mobileAndTabletcheck();
@@ -107,6 +107,8 @@ class Panorama extends EventEmitter{
_player: Player;
_videoCanvas: BaseCanvas;
_thumbnailCanvas: BaseCanvas | null;
+ //save total markers enable to generate marker id
+ _totalMarkers: number;
/**
* check legacy option settings and produce warning message if user use legacy options, automatically set it to new options.
@@ -212,6 +214,7 @@ class Panorama extends EventEmitter{
Panorama.checkOptions(options);
this._options = mergeOptions({}, defaults, options);
this._player = player;
+ this._totalMarkers = 0;
this.player.addClass("vjs-panorama");
@@ -314,6 +317,13 @@ class Panorama extends EventEmitter{
this.videoCanvas.startAnimation();
this.videoCanvas.show();
+ //initial markers
+ if(this.options.Markers){
+ this.options.Markers.forEach((markSetting: any)=>{
+ this.addMarker(markSetting);
+ });
+ }
+
//detect black screen
if(window.console && window.console.error){
let originalErrorFunction = window.console.error;
@@ -378,6 +388,18 @@ class Panorama extends EventEmitter{
}
}
+ addMarker(markSetting: any): Marker{
+ this._totalMarkers++;
+ markSetting.id = markSetting.id? markSetting.id : `marker_${this._totalMarkers}`;
+ let marker = new Marker(this.player, markSetting);
+ this.player.addComponent(markSetting.id, marker);
+ return marker;
+ }
+
+ removeMarker(markerId: string): void{
+ this.player.removeComponent(markerId);
+ }
+
get thumbnailCanvas(): BaseCanvas | null{
return this._thumbnailCanvas;
}
diff --git a/src/scripts/tech/BasePlayer.js b/src/scripts/tech/BasePlayer.js
index 167d0e3..aa3c01c 100644
--- a/src/scripts/tech/BasePlayer.js
+++ b/src/scripts/tech/BasePlayer.js
@@ -140,6 +140,10 @@ class BasePlayer implements Player {
ready(fn: Function): void{
throw Error('Not implemented');
}
+
+ get components(): Array{
+ return this._components;
+ }
}
export default BasePlayer;
\ No newline at end of file
diff --git a/src/scripts/types/Settings.js b/src/scripts/types/Settings.js
index fcbbf55..f64745b 100644
--- a/src/scripts/types/Settings.js
+++ b/src/scripts/types/Settings.js
@@ -1,27 +1,29 @@
// @flow
-import { Point } from './Point';
+import { Point, Coordinates } from './Point';
export type VideoTypes = "equirectangular" | "fisheye" | "3dVideo" | "dual_fisheye";
export type MarkerSettings = {
- lat: number;
- lon: number;
+ location: Coordinates;
+
radius: number;
+ id?: string;
+
/**
* use custom dom
*/
- element?: HTMLElement;
+ element: HTMLElement | string;
/**
* timeline when should marker be shown
*/
- keyPoint: number;
+ keyPoint?: number;
/**
* when should marker disappear, set -1 if you don't want it disappear
*/
- duration: number;
+ duration?: number;
/**
* callback function when marker is disappear
diff --git a/src/styles/plugin.scss b/src/styles/plugin.scss
index 0a640a0..42c7795 100644
--- a/src/styles/plugin.scss
+++ b/src/styles/plugin.scss
@@ -132,6 +132,19 @@
-webkit-animation-delay: 0.44s;
animation-delay: 0.44s; }
+ .vjs-marker{
+ position: absolute;
+ display: none;
+
+ &.vjs-marker--enable{
+ display: block!important;
+ }
+
+ &.vjs-marker--backside{
+ display: none!important;
+ }
+ }
+
.vjs-VR-control{
cursor: pointer;