Skip to content
This repository has been archived by the owner on Dec 6, 2018. It is now read-only.

Feature that allows a hotspot to have its own icon through an image #285

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/gallery/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ function loadScene(id) {
vrView.setContent({
image: scenes[id].image,
preview: scenes[id].preview,
is_stereo: scenes[id].is_stereo || false,
is_autopan_off: true
});

Expand Down
6 changes: 5 additions & 1 deletion examples/hotspots/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var scenes = {
dolphins: {
image: 'dolphins.jpg',
preview: 'dolphins-preview.jpg',
is_stereo: true,
hotspots: {
whaleRight: {
pitch: 0,
Expand All @@ -43,6 +44,7 @@ var scenes = {
whaleLeft: {
image: 'whale-left.jpg',
preview: 'whale-left-preview.jpg',
is_stereo: true,
hotspots: {
whaleRight: {
pitch: 0,
Expand All @@ -67,6 +69,7 @@ var scenes = {
whaleRight: {
image: 'whale-right.jpg',
preview: 'whale-right-preview.jpg',
is_stereo: true,
hotspots: {
dolphins: {
pitch: 0,
Expand All @@ -91,6 +94,7 @@ var scenes = {
walrus: {
image: 'walrus.jpg',
preview: 'walrus-preview.jpg',
is_stereo: true,
hotspots: {
whaleLeft: {
pitch: 0,
Expand Down Expand Up @@ -158,7 +162,7 @@ function loadScene(id) {
vrView.setContent({
image: scenes[id].image,
preview: scenes[id].preview,
is_stereo: true,
is_stereo: scenes[id].is_stereo || false,
is_autopan_off: true
});

Expand Down
Binary file added images/hotspot_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/api/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Player.prototype = new EventEmitter();
* @param distance {Number} The distance of the hotspot from camera, specified
* in meters.
* @param hotspotId {String} The ID of the hotspot.
* @param icon {String} The path of a image that will represent the hotspot
*/
Player.prototype.addHotspot = function(hotspotId, params) {
// TODO: Add validation to params.
Expand All @@ -81,6 +82,7 @@ Player.prototype.addHotspot = function(hotspotId, params) {
yaw: params.yaw,
radius: params.radius,
distance: params.distance,
icon: params.icon,
id: hotspotId
};
this.sender.send({type: Message.ADD_HOTSPOT, data: data});
Expand Down
121 changes: 82 additions & 39 deletions src/embed/hotspot-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,24 +93,30 @@ HotspotRenderer.prototype = new EventEmitter();
* in meters.
* @param hotspotId {String} The ID of the hotspot.
*/
HotspotRenderer.prototype.add = function(pitch, yaw, radius, distance, id) {
HotspotRenderer.prototype.add = function(pitch, yaw, radius, distance, id, icon) {
// If a hotspot already exists with this ID, stop.
if (this.hotspots[id]) {
// TODO: Proper error reporting.
console.error('Attempt to add hotspot with existing id %s.', id);
return;
}
var hotspot = this.createHotspot_(radius, distance);
hotspot.name = id;

// Position the hotspot based on the pitch and yaw specified.
var quat = new THREE.Quaternion();
quat.setFromEuler(new THREE.Euler(THREE.Math.degToRad(pitch), THREE.Math.degToRad(yaw), 0, 'ZYX'));
hotspot.position.applyQuaternion(quat);
hotspot.lookAt(new THREE.Vector3());
var hotspotPromise = this.createHotspot_(radius, distance, icon);
var self = this;
hotspotPromise.then(function(hotspot){
hotspot.name = id;

// Position the hotspot based on the pitch and yaw specified.
var quat = new THREE.Quaternion();
quat.setFromEuler(new THREE.Euler(THREE.Math.degToRad(pitch), THREE.Math.degToRad(yaw), 0, 'ZYX'));
hotspot.position.applyQuaternion(quat);
hotspot.lookAt(new THREE.Vector3());
self.hotspotRoot.add(hotspot);
self.hotspots[id] = hotspot;
}).catch(function(err){
self.worldRenderer.emit('error', 'Error while creating the hotspot, check the hotspot image \' ' + icon +'\'');
});

this.hotspotRoot.add(hotspot);
this.hotspots[id] = hotspot;
}

/**
Expand Down Expand Up @@ -282,34 +288,63 @@ HotspotRenderer.prototype.getSize_ = function() {
return this.worldRenderer.renderer.getSize();
};

HotspotRenderer.prototype.createHotspot_ = function(radius, distance) {
var innerGeometry = new THREE.CircleGeometry(radius, 32);

var innerMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff, side: THREE.DoubleSide, transparent: true,
opacity: MAX_INNER_OPACITY, depthTest: false
});

var inner = new THREE.Mesh(innerGeometry, innerMaterial);
inner.name = 'inner';

var outerMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff, side: THREE.DoubleSide, transparent: true,
opacity: MAX_OUTER_OPACITY, depthTest: false
});
var outerGeometry = new THREE.RingGeometry(radius * 0.85, radius, 32);
var outer = new THREE.Mesh(outerGeometry, outerMaterial);
outer.name = 'outer';
HotspotRenderer.prototype.createHotspot_ = function(radius, distance, icon) {

var hotspotPromise;
// Position at the extreme end of the sphere.
var hotspot = new THREE.Object3D();
hotspot.position.z = -distance;
hotspot.scale.copy(NORMAL_SCALE);

hotspot.add(inner);
hotspot.add(outer);
//If no icon path is entered, create a default hotspot
if(!icon){
hotspotPromise = new Promise(function(resolve, reject) {
var innerGeometry = new THREE.CircleGeometry(radius, 32);

var innerMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff, side: THREE.DoubleSide, transparent: true,
opacity: MAX_INNER_OPACITY, depthTest: false
});

var inner = new THREE.Mesh(innerGeometry, innerMaterial);
inner.name = 'inner';

var outerMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff, side: THREE.DoubleSide, transparent: true,
opacity: MAX_OUTER_OPACITY, depthTest: false
});
var outerGeometry = new THREE.RingGeometry(radius * 0.85, radius, 32);
var outer = new THREE.Mesh(outerGeometry, outerMaterial);
outer.name = 'outer';

hotspot.add(inner);
hotspot.add(outer);

resolve(hotspot);
});
}else{
hotspotPromise = new Promise(
function(resolve, reject) {
var txLoader = new THREE.TextureLoader();
txLoader.crossOrigin = 'anonymous';
txLoader.load(icon, function(texture){
var material = new THREE.MeshBasicMaterial({ map: texture, transparent: false,
depthTest: false });
var geometry = new THREE.CircleGeometry(radius, 32);
var mesh = new THREE.Mesh(geometry, material);
mesh.name = 'texture_mesh';

hotspot.add(mesh);

resolve(hotspot);
}, undefined, function(err){
reject(err)
});
}
);
}

return hotspot;
return hotspotPromise;
};

/**
Expand Down Expand Up @@ -353,7 +388,7 @@ HotspotRenderer.prototype.focus_ = function(id) {
this.tween = new TWEEN.Tween(hotspot.scale).to(FOCUS_SCALE, FOCUS_DURATION)
.easing(TWEEN.Easing.Quadratic.InOut)
.start();

if (this.worldRenderer.isVRMode()) {
this.timeForHospotClick = setTimeout(function () {
this.emit('click', id);
Expand All @@ -367,7 +402,7 @@ HotspotRenderer.prototype.blur_ = function(id) {
this.tween = new TWEEN.Tween(hotspot.scale).to(NORMAL_SCALE, FOCUS_DURATION)
.easing(TWEEN.Easing.Quadratic.InOut)
.start();

if (this.timeForHospotClick) {
clearTimeout( this.timeForHospotClick );
}
Expand All @@ -378,26 +413,34 @@ HotspotRenderer.prototype.down_ = function(id) {
var hotspot = this.hotspots[id];
var outer = hotspot.getObjectByName('inner');

this.tween = new TWEEN.Tween(outer.material.color).to(ACTIVE_COLOR, ACTIVE_DURATION)
.start();
if(outer){
this.tween = new TWEEN.Tween(outer.material.color).to(ACTIVE_COLOR, ACTIVE_DURATION)
.start();
}

};

HotspotRenderer.prototype.up_ = function(id) {
// Become inactive.
var hotspot = this.hotspots[id];
var outer = hotspot.getObjectByName('inner');

this.tween = new TWEEN.Tween(outer.material.color).to(INACTIVE_COLOR, ACTIVE_DURATION)
.start();
if(outer){
this.tween = new TWEEN.Tween(outer.material.color).to(INACTIVE_COLOR, ACTIVE_DURATION)
.start();
}

};

HotspotRenderer.prototype.setOpacity_ = function(id, opacity) {
var hotspot = this.hotspots[id];
var outer = hotspot.getObjectByName('outer');
var inner = hotspot.getObjectByName('inner');

outer.material.opacity = opacity * MAX_OUTER_OPACITY;
inner.material.opacity = opacity * MAX_INNER_OPACITY;
if(inner && outer){
outer.material.opacity = opacity * MAX_OUTER_OPACITY;
inner.material.opacity = opacity * MAX_INNER_OPACITY;
}
};

module.exports = HotspotRenderer;
3 changes: 2 additions & 1 deletion src/embed/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ function onAddHotspot(e) {
var radius = parseFloat(e.radius);
var distance = parseFloat(e.distance);
var id = e.id;
worldRenderer.hotspotRenderer.add(pitch, yaw, radius, distance, id);
var icon = e.icon;
worldRenderer.hotspotRenderer.add(pitch, yaw, radius, distance, id, icon);
}

function onSetContent(e) {
Expand Down