我建立了一个网站,其中包含左侧的全景查看器(来自谷歌的VrView)和右侧的购物平面图。我不知道点击 json 链接的确切方式,iframe 会更新为另一张全景图片。谁能帮我?
我也不确定 vrviewer 是否是最好的解决方案,或者更好地嵌入 three.js 和全景立方体的代码,它本身也很好。我愿意接受任何建议。谢谢你。
这里是 iframe 版本的代码:
索引.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Pano Map</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<link rel="stylesheet" type="text/css" href="css/map.css">
</head>
<body class="stretched">
<div id="wrap">
<header>
<nav></nav>
</header>
<section id="content">
<!--VrView -->
<div class="col_two_third">
<script type='text/template'>
<iframe class="vrview" scrolling="no" frameborder="0" allowfullscreen="true" width="100%" height="800px" src="http://mypage.com/vrview/index.html?image=http://mypage.com/vrview/image/pano01.jpg"></iframe>
<script>
function DeviceMotionSender(){if(!this.isIOS_()){return}window.addEventListener("devicemotion",this.onDeviceMotion_.bind(this),false);this.iframes=document.querySelectorAll("iframe.vrview")}DeviceMotionSender.prototype.onDeviceMotion_=function(e){var message={type:"DeviceMotion",deviceMotionEvent:this.cloneDeviceMotionEvent_(e)};for(var i=0;i<this.iframes.length;i++){var iframe=this.iframes[i];var iframeWindow=iframe.contentWindow;if(this.isCrossDomainIframe_(iframe)){iframeWindow.postMessage(message,"*")}}};DeviceMotionSender.prototype.cloneDeviceMotionEvent_=function(e){return{acceleration:{x:e.acceleration.x,y:e.acceleration.y,z:e.acceleration.z},accelerationIncludingGravity:{x:e.accelerationIncludingGravity.x,y:e.accelerationIncludingGravity.y,z:e.accelerationIncludingGravity.z},rotationRate:{alpha:e.rotationRate.alpha,beta:e.rotationRate.beta,gamma:e.rotationRate.gamma},interval:e.interval}};DeviceMotionSender.prototype.isIOS_=function(){return/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream};DeviceMotionSender.prototype.isCrossDomainIframe_=function(iframe){var html=null;try{var doc=iframe.contentDocument||iframe.contentWindow.document;html=doc.body.innerHTML}catch(err){}return html===null};var dms=new DeviceMotionSender;
</script>
</script>
</div>
<!--Map -->
<div class="col_one_third col_last clearfix">
<div class="map-container">
<div id="map"></div>
</div>
</div>
</section>
<footer></footer>
</div>
<!-- Scripts -->
<!-- Map Floorplan -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/hammer.min.js"></script>
<script type="text/javascript" src="js/jquery.mousewheel.js"></script>a
<script type="text/javascript" src="js/script.js"></script>
<script type="text/javascript" src="js/magnific-popup.js"></script>
<script type="text/javascript" src="map/map.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var map = $('#map').map({
source: 'maplist.json',
height: 800,
mapfill: true,
maxscale: 1
});
// EVENTS
// Map ready
map.on('mapready', function(e, self) {
console.log('Map is ready!')
// self grants direct access to the map object
// The map will be focused on the washing machine by default
//self.moveTo(0.67, 0.62, 3, 0);
});
// Location opened
map.on('locationopened', function(e, location) {
// location grants full access to the location
console.log(location.title + ' opened.');
});
// Location closed
map.on('locationclosed', function(e) {
console.log('Location closed.');
});
// Level switched
map.on('levelswitched', function(e, level) {
console.log('Switched to ' + level + ' level.');
});
// Position changed
map.on('positionchanged', function(e, self) {
// self grants direct access to the map object
//console.log('Pan or zoom performed, current scale: ' + self.scale);
});
// METHODS
// Getting mapplic object
var self = map.data('map');
map.on('locationclosed', function(e) {
//console.log(self);
});
});
</script>
<!-- VRView code from google-->
<script type='text/javascript'>
//<![CDATA[
var BreakpointHandler = function() {
this.initted = false;
this.isHomePage = false;
this.isMobile = false;
};
BreakpointHandler.prototype.finalizeSummary = function(summaryHtml, lastNode) {
// Use $.trim for IE8 compatibility
summaryHtml = $.trim(summaryHtml).replace(/(<br>|\s)+$/,'');
if (lastNode.nodeType == 3) {
var lastChar = summaryHtml.slice(-1);
if (!lastChar.match(/[.”"?]/)) {
if (!lastChar.match(/[A-Za-z]/)) {
summaryHtml = summaryHtml.slice(0, -1);
}
summaryHtml += ' ...';
}
} else if (lastNode.nodeType == 1 && (lastNode.nodeName == 'I' || lastNode.nodeName == 'A')) {
summaryHtml += ' ...';
}
return summaryHtml;
};
BreakpointHandler.prototype.generateSummaryFromContent = function(content, numWords) {
var seenWords = 0;
var summaryHtml = '';
for (var i=0; i < content.childNodes.length; i++) {
var node = content.childNodes[i];
var nodeText;
if (node.nodeType == 1) {
if (node.hasAttribute('data-about-pullquote')) {
continue;
}
nodeText = node.textContent;
if (nodeText === undefined) {
// innerText for IE8
nodeText = node.innerText;
}
if (node.nodeName == 'DIV' || node.nodeName == 'B') {
// Don't end early if we haven't seen enough words.
if (seenWords < 10) {
continue;
}
if (i > 0) {
summaryHtml = this.finalizeSummary(summaryHtml, content.childNodes[i-1]);
}
break;
}
summaryHtml += node.outerHTML;
} else if (node.nodeType == 3) {
nodeText = node.nodeValue;
summaryHtml += nodeText + ' ';
}
var words = nodeText.match(/\S+\s*/g);
if (!words) {
continue;
}
var remain = numWords - seenWords;
if (words.length >= remain) {
summaryHtml = this.finalizeSummary(summaryHtml, node);
break;
}
seenWords += words.length;
}
return summaryHtml;
};
BreakpointHandler.prototype.detect = function() {
var match,
pl = /\+/g,
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
query = window.location.search.substring(1);
var urlParams = {};
while (match = search.exec(query))
urlParams[decode(match[1])] = decode(match[2]);
this.isListPage = $('html').hasClass('list-page');
this.isMobile = urlParams['m'] === '1';
this.isHomePage = window.location.pathname == '/';
};
BreakpointHandler.prototype.initContent = function() {
var self = this;
$('.post').each(function(index) {
var body = $(this).children('.post-body')[0];
var content = $(body).children('.post-content')[0];
$(content).addClass('post-original');
var data = $(content).children('script').html();
data = self.rewriteForSSL(data);
// If exists, extract specified editor's preview.
var match = data.match(/([\s\S]+?)<div data-is-preview.+?>([\s\S]+)<\/div>/m);
if (match) {
data = match[1];
}
// Prevent big images from loading when they aren't needed.
// This must be done as a pre-injection step, since image loading can't be
// canceled once embedded into the DOM.
if (self.isListPage && self.isMobile) {
data = data.replace(/<(img|iframe) .+?>/g, '');
}
// Insert template to be rendered as nodes.
content.innerHTML = data;
if (self.isListPage) {
var summary = document.createElement('div');
$(summary).addClass('post-content');
$(summary).addClass('post-summary');
body.insertBefore(summary, content);
if (match) {
// Use provided summary.
summary.innerHTML = match[2];
} else {
// Generate a summary.
// Summary generation relies on DOM, so it must occur after content is
// inserted into the page.
summary.innerHTML = self.generateSummaryFromContent(content, 30);
}
// Add read more link to summary.
var titleAnchor = $(this).find('.title a')[0];
var link = titleAnchor.cloneNode(true);
link.innerHTML = 'Read More';
$(link).addClass('read-more');
summary.appendChild(link);
}
});
// Firefox does not allow for proper styling of BR.
if (navigator.userAgent.indexOf('Firefox') > -1) {
$('.post-content br').replaceWith('<span class="space"></span>');
}
$('.loading').removeClass('loading');
};
BreakpointHandler.prototype.process = function() {
if (!this.initted) {
var makeInsecureImageRegex = function(hosts) {
var whitelist = hosts.join('|').replace(/\./g,'\\.');
// Normal image tags, plus input images (yes, this is possible!)
return new RegExp('(<(img|input)[^>]+?src=("|\'))http:\/\/(' + whitelist +')', 'g');
};
this.sslImageRegex = makeInsecureImageRegex(BreakpointHandler.KNOWN_HTTPS_HOSTS);
this.sslImageCurrentDomainRegex = makeInsecureImageRegex([window.location.hostname]);
this.detect();
this.initContent();
this.initted = true;
}
};
BreakpointHandler.KNOWN_HTTPS_HOSTS = [
"www.google.org",
"www.google.com",
"services.google.com",
"blogger.com",
"draft.blogger.com",
"www.blogger.com",
"photos1.blogger.com",
"photos2.blogger.com",
"photos3.blogger.com",
"blogblog.com",
"img1.blogblog.com",
"img2.blogblog.com",
"www.blogblog.com",
"www1.blogblog.com",
"www2.blogblog.com",
"0.bp.blogspot.com",
"1.bp.blogspot.com",
"2.bp.blogspot.com",
"3.bp.blogspot.com",
"4.bp.blogspot.com",
"lh3.googleusercontent.com",
"lh4.googleusercontent.com",
"lh5.googleusercontent.com",
"lh6.googleusercontent.com",
"themes.googleusercontent.com",
];
BreakpointHandler.prototype.rewriteForSSL = function(html) {
// Handle HTTP -> HTTPS source replacement of images, movies, and other embedded content.
return html.replace(this.sslImageRegex, '$1https://$4')
.replace(this.sslImageCurrentDomainRegex, '$1//$4')
.replace(/(<(embed|iframe)[^>]+?src=("|'))http:\/\/([^"']*?(youtube|picasaweb\.google)\.com)/g, '$1https://$4')
// Slideshow SWF takes a image host, so we need to rewrite that parameter.
.replace(/(<embed[^>]+?feed=http(?=[^s]))/g, '$1s');
};
$(document).ready(function() {
var handler = new BreakpointHandler();
handler.process();
function DeviceMotionSender(){if(!this.isIOS_()){return}window.addEventListener("devicemotion",this.onDeviceMotion_.bind(this),false);this.iframes=document.querySelectorAll("iframe.vrview")}DeviceMotionSender.prototype.onDeviceMotion_=function(e){var message={type:"DeviceMotion",deviceMotionEvent:this.cloneDeviceMotionEvent_(e)};for(var i=0;i<this.iframes.length;i++){var iframe=this.iframes[i];var iframeWindow=iframe.contentWindow;if(this.isCrossDomainIframe_(iframe)){iframeWindow.postMessage(message,"*")}}};DeviceMotionSender.prototype.cloneDeviceMotionEvent_=function(e){return{acceleration:{x:e.acceleration.x,y:e.acceleration.y,z:e.acceleration.z},accelerationIncludingGravity:{x:e.accelerationIncludingGravity.x,y:e.accelerationIncludingGravity.y,z:e.accelerationIncludingGravity.z},rotationRate:{alpha:e.rotationRate.alpha,beta:e.rotationRate.beta,gamma:e.rotationRate.gamma},interval:e.interval}};DeviceMotionSender.prototype.isIOS_=function(){return/iPad|iPhone|iPod/.test(navigator.userAgent)&&!window.MSStream};DeviceMotionSender.prototype.isCrossDomainIframe_=function(iframe){var html=null;try{var doc=iframe.contentDocument||iframe.contentWindow.document;html=doc.body.innerHTML}catch(err){}return html===null};var dms=new DeviceMotionSender;
// Top-level navigation.
$(".BlogArchive .tab").click(function(ev) {
ev.preventDefault();
$(this).parent().toggleClass('active');
$(this).siblings().slideToggle(300);
});
$(".Label .tab").click(function(ev) {
ev.preventDefault();
$(this).parent().toggleClass('active');
$(this).siblings().slideToggle(300);
});
// Blog archive year expansion.
$('.BlogArchive .intervalToggle').click(function(ev) {
ev.preventDefault();
if ($(this).parent().hasClass('collapsed')) {
$(this).parent().removeClass('collapsed');
$(this).parent().addClass('expanded');
} else {
$(this).parent().removeClass('expanded');
$(this).parent().addClass('collapsed');
}
});
// Reverse order of months.
$('.BlogArchive .intervalToggle + div').each(function(_, items) {
var year = $(this);
year.children().each(function(_, month) {
year.prepend(month);
});
});
// Set anchors to open in new tab.
$('.post-content img').parent().each(function(_, node) {
if (node.nodeName == 'A') {
$(this).attr('target', '_blank');
}
});
// Process search requests.
$('.searchBox input').on("keypress", function(ev) {
if (ev.which == 13) {
window.location.href = 'https://www.google.com/search?q=site%3A' + window.location.hostname + '%20' + encodeURIComponent ($(this).val());
}
});
});
//]]>
</script>
<script src="vrview/index.js"></script>
</body>
</html>
地图列表.json
{
"mapwidth": "2000",
"mapheight": "4000",
"categories":[
{
"id": "floor",
"title": "1st floor",
"show": "true"
},
{
"id": "roof",
"title": "2nd floor",
"show": "false"
}
],
"levels":[
{
"id":"floor",
"title":"1st floor shops",
"map":"map/images/floorplan.svg",
"minimap": "map/images/floorplan-small.jpg",
"locations":[
{
"id": "floor001",
"title": "Shop A",
"category": "floor",
"link": "<iframe src=\"http://mypage.com/vrview/images/pano01.jpg\">",
"x": "0.4547",
"y": "0.1703"
},
{
"id": "floor002",
"title": "Shop B",
"category": "floor",
"link": "<iframe src=\"http://mypage.com/vrview/images/pano02.jpg\">",
"x": "0.5814",
"y": "0.1703"
},
{
"id": "floor003",
"title": "Shop C",
"category": "floor",
"link": "<iframe src=\"http://mypage.com/vrview/images/pano03.jpg\">",
"x": "0.7176",
"y": "0.1703"
}
]
},
{
"id":"Roof",
"title":"2nd Floor",
"map":"map/images/floorplan.svg",
"minimap": "map/images/floorplan-small.jpg",
"locations":[
{"id": "roof001",
"title": "The Roof",
"description": "on top of this building",
"category": "Roof",
"link": "<iframe src=\"http://mypage.com/vrview/images/pano04.jpg\">",
"x": "0.5547",
"y": "0.3703"
}
]
}
]
}