文档章节

Krpano 二维全景图项目开发记录

华山猛男
 华山猛男
发布于 2017/09/11 11:32
字数 8824
阅读 103
收藏 0
点赞 1
评论 3

Krpano是一款全景开发插件,废话就不多说了,这篇文章用于记录Krpano后台集成开发,即将该插件应用到后台系统中,上传全景图片后,可自动生成全景,同时可以在场景编辑器中自定义路线、语音等,简化了全景开发的复杂性。

官方网站

  • https://krpano.com

参考案例

  • http://www.krpano.tech/

 

Krpano 二维全景图项目开发记录

全景图嵌入式开发

服务器端数据处理

全景图场景编辑器

全景图数据文件生成

全景图数据文件回显-涉及添加多个全景(*重要)

 

Tour代码模块

动态统一代码模板(tour.xml.jsp)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<krpano version="1.19" title="Virtual Tour">
  <include url="%SWFPATH%/skin/vtourskin.xml?v=1.3" />
  <action name="startup" autorun="onstart">
  	if(startscene === null OR !scene[get(startscene)], copy(startscene,scene[0].name); );
  	loadscene(get(startscene), null, MERGE);
  	playsound(bgsnd, '', 0);
  	if(startactions !== null, startactions() );
  	js('onready');
  </action>
  
  <c:forEach items="${param.tourUrlIds}" var="UUID">
	  <scene name="${UUID}" title="${UUID}" onstart="" thumburl="panos/${UUID}/thumb.jpg" lat="" lng="" heading="">
			<view hlookat="0" vlookat="0" fovtype="MFOV" fov="90" fovmin="5" fovmax="120" vlookatmin="-90" vlookatmax="90" limitview="lookat"/>
			<preview url="panos/${UUID}/preview.jpg" />
			<image>
				<cube url="panos/${UUID}/pano_%s.jpg" />
			</image>
	  </scene>
  </c:forEach>
  
</krpano>

Java代码模块

全景图Tour.xml文件代码生成及保存

全景图Tour.xml文件代码回显二次生成保存

全景图多图选择

/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.thinkgem.jeesite.modules.hnly.web;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.junit.runners.Parameterized.Parameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.mapper.JsonMapper;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.utils.FileUtils;
import com.thinkgem.jeesite.common.utils.IdGen;
import com.thinkgem.jeesite.common.utils.KrpanoUtils;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.web.BaseController;
import com.thinkgem.jeesite.modules.hnly.entity.KrpanoHotspots;
import com.thinkgem.jeesite.modules.hnly.entity.KrpanoView;
import com.thinkgem.jeesite.modules.hnly.entity.Panoramic;
import com.thinkgem.jeesite.modules.hnly.entity.PanoramicMaterialPic;
import com.thinkgem.jeesite.modules.hnly.entity.PanoramicPicHotspots;
import com.thinkgem.jeesite.modules.hnly.entity.PanoramicPicMusic;
import com.thinkgem.jeesite.modules.hnly.entity.PanoramicPicView;
import com.thinkgem.jeesite.modules.hnly.service.PanoramicMaterialPicService;
import com.thinkgem.jeesite.modules.hnly.service.PanoramicPicHotspotsService;
import com.thinkgem.jeesite.modules.hnly.service.PanoramicPicMusicService;
import com.thinkgem.jeesite.modules.hnly.service.PanoramicPicViewService;
import com.thinkgem.jeesite.modules.hnly.service.PanoramicService;

/**
 * 全景图管理Controller
 * @author WenC
 * @version 2017-08-15
 */
@Controller
@RequestMapping(value = "${adminPath}/hnly/panoramic")
public class PanoramicController extends BaseController {

	@Autowired
	private PanoramicService panoramicService;
	@Autowired
	private PanoramicMaterialPicService panoramicMaterialPicService;
	@Autowired
	private PanoramicPicViewService panoramicPicViewService;
	@Autowired
	private PanoramicPicHotspotsService panoramicPicHotspotsService;
	@Autowired
	private PanoramicPicMusicService panoramicPicMusicService;
	
	Map<String, String> iMap = new HashMap<String, String>();
	
	@ModelAttribute
	public Panoramic get(@RequestParam(required=false) String id) {
		Panoramic entity = null;
		if (StringUtils.isNotBlank(id)){
			entity = panoramicService.get(id);
		}
		if (entity == null){
			entity = new Panoramic();
		}
		return entity;
	}
	
	@RequiresPermissions("hnly:panoramic:view")
	@RequestMapping(value = {"list", ""})
	public String list(Panoramic panoramic, HttpServletRequest request, HttpServletResponse response, Model model) {
		Page<Panoramic> page = panoramicService.findPage(new Page<Panoramic>(request, response), panoramic); 
		model.addAttribute("page", page);
		return "modules/hnly/panoramicList";
	}

	@RequiresPermissions("hnly:panoramic:view")
	@RequestMapping(value = "form")
	public String form(Panoramic panoramic, Model model) {
		model.addAttribute("panoramic", panoramic);
		return "modules/hnly/panoramicForm";
	}

	@RequiresPermissions("hnly:panoramic:edit")
	@RequestMapping(value = "save")
	public String save(Panoramic panoramic, Model model, @RequestParam("imagesUrl") MultipartFile file, HttpServletRequest request, RedirectAttributes redirectAttributes) {
		if (!beanValidator(model, panoramic)){
			return form(panoramic, model);
		}
		if(!file.isEmpty()){
			String uuid = IdGen.uuidAtoZ();
			String path = request.getSession().getServletContext().getRealPath("krpano/panos");  
	        String fileName = file.getOriginalFilename();
	        String uuidFileName = uuid + fileName.substring(fileName.lastIndexOf("."));
	        File dir = new File(path,uuidFileName);          
	        if(!dir.exists()){  
	            dir.mkdirs();  
	        }  
	        //MultipartFile自带的解析方法  
	        try {
				file.transferTo(dir);
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	        String allPath = request.getContextPath() + "/krpano/panos/" + uuidFileName;
	        panoramic.setUrl(allPath);
		}
		panoramicService.save(panoramic);
		addMessage(redirectAttributes, "保存全景图成功");
		return "redirect:"+Global.getAdminPath()+"/hnly/panoramic/?repage";
	}
	
	@RequiresPermissions("hnly:panoramic:edit")
	@RequestMapping(value = "delete")
	public String delete(Panoramic panoramic, RedirectAttributes redirectAttributes) {
		panoramicService.delete(panoramic);
		addMessage(redirectAttributes, "删除全景图成功");
		return "redirect:"+Global.getAdminPath()+"/hnly/panoramic/?repage";
	}
	
	@RequiresPermissions("hnly:panoramic:edit")
	@RequestMapping(value = "vtourGenerate")
	public String vtourGenerate(Panoramic panoramic, RedirectAttributes redirectAttributes){
		String tempThumbUrl = KrpanoUtils.krpanoVtourMultires(KrpanoUtils.VNP, panoramic.getUrl());
		panoramic.setThumbUrl(tempThumbUrl);
		panoramic.setTourUrl(KrpanoUtils.getTourUrl(panoramic.getUrl()));
		panoramicService.save(panoramic);
		addMessage(redirectAttributes, "生成全景图成功");
		return "redirect:"+Global.getAdminPath()+"/hnly/panoramic/?repage";
	}
	
	@RequiresPermissions("hnly:panoramic:edit")
	@RequestMapping(value = "multiSelect")
	public String multiSelect(Panoramic panoramic, HttpServletRequest request, HttpServletResponse response, Model model) {
//		System.out.println(panoramic.getPanoramicMaterialPicIdList());
		model.addAttribute("panoramic", panoramic);
		model.addAttribute("AllPanoramicMaterialPic", panoramicMaterialPicService.findList(null));
		return "modules/hnly/panoramicMultiSelect";
	}
	
	/**
	 * 全景图更新
	 * @param panoramic
	 * @param request
	 * @param response
	 * @param model
	 */
	@RequiresPermissions("hnly:panoramic:edit")
	@RequestMapping(value = "multiSelectSave")
	public void multiSelectSave(Panoramic panoramic, HttpServletRequest request, HttpServletResponse response, Model model) {
		// 更新全景关联要素图片数据
		String[] cpmpil = request.getParameterValues("panoramicMaterialPicIdList");
//		System.out.println(cpmpil);
//		if(null != cpmpil){
//			for(String s : cpmpil){
//				System.out.println(s);
//			}
//		}
//		System.out.println(panoramic.getPanoramicMaterialPicIdList());
		if(null == cpmpil){ //如果为NULL,证明只选择了主场景,没有选择其他场景联动
			panoramic.setPanoramicMaterialPicList(null);
		}
		panoramicService.updatePanoramicPic(panoramic);
		panoramic = panoramicService.get(panoramic.getId());
		String tourUrls = panoramic.getTourUrl();
//		String panoramicMaterialPicIds = "";
		for(int i=0;i<panoramic.getPanoramicMaterialPicList().size();i++){
			PanoramicMaterialPic pmp = panoramic.getPanoramicMaterialPicList().get(i);
			tourUrls = tourUrls + "," + pmp.getTourUrl();
//			panoramicMaterialPicIds = panoramicMaterialPicIds + pmp.getId() + ",";
//			if((i+1)==panoramic.getPanoramicMaterialPicList().size()){
//				panoramicMaterialPicIds = panoramicMaterialPicIds.substring(0, panoramicMaterialPicIds.length()-1);
//			}
		}
		String[] tourUrlsTemp = tourUrls.split(","); //页面选中的场景数组数据
		List<PanoramicPicView> panoramicPicViewList = panoramicPicViewService.findListByPanoramicId(panoramic.getId());
		// ===== 存在代码修改数据,检查有无新增数据,有则添加codeView代码原始模块
		if(null != panoramicPicViewList && panoramicPicViewList.size()>0){ 
			String[] tourUrlsExist = new String[panoramicPicViewList.size()];
			for(int i=0;i<panoramicPicViewList.size();i++){
				tourUrlsExist[i] = panoramicPicViewList.get(i).getTourUrl();
			}
			List<String> delList = compare(tourUrlsTemp,tourUrlsExist);  
	        for (String str : delList) {  
//	            System.out.println(str);
	        	iMap.clear();
	        	iMap.put("panoramicId", panoramic.getId());
	        	iMap.put("tourUrl", str);
	        	panoramicPicViewService.delByPanoramicIdAndTourUrl(iMap);
	        }
	        List<String> addList = compare(tourUrlsExist,tourUrlsTemp);  
	        for (String str : addList) {  
//	            System.out.println(str);
	        	PanoramicPicView panoramicPicView = new PanoramicPicView();
				panoramicPicView.setTourUrl(str);
				panoramicPicView.setPanoramic(panoramic);
				panoramicPicView.setCode("<view hlookat=\"0\" vlookat=\"0\" fovtype=\"MFOV\" fov=\"90\" fovmin=\"5\" fovmax=\"120\" vlookatmin=\"-90\" vlookatmax=\"90\" limitview=\"auto\"/>\r\n");
				panoramicPicViewService.save(panoramicPicView);
	        }
		} else {
			for(String str : tourUrlsTemp){
				PanoramicPicView panoramicPicView = new PanoramicPicView();
				panoramicPicView.setTourUrl(str);
				panoramicPicView.setPanoramic(panoramic);
				panoramicPicView.setCode("<view hlookat=\"0\" vlookat=\"0\" fovtype=\"MFOV\" fov=\"90\" fovmin=\"5\" fovmax=\"120\" vlookatmin=\"-90\" vlookatmax=\"90\" limitview=\"auto\"/>\r\n");
				panoramicPicViewService.save(panoramicPicView);
			}
		}
		// ===== 存在代码修改数据,检查有无新增数据,新增加场景中去除原有场景则去除codeHotspots代码模块,在此不执行热点原始代码模块,因为是一对多的关系
		List<PanoramicPicHotspots> panoramicPicHotspotsList = panoramicPicHotspotsService.findListByPanoramicId(panoramic.getId());
		if(null != panoramicPicHotspotsList && panoramicPicHotspotsList.size()>0){
			String[] tourUrlsExist = new String[panoramicPicHotspotsList.size()];
			for(int i=0;i<panoramicPicHotspotsList.size();i++){
				tourUrlsExist[i] = panoramicPicHotspotsList.get(i).getTourUrl();
			}
			List<String> delList = compare(tourUrlsTemp,tourUrlsExist); 
			for (String str : delList) {  
	            System.out.println(str);
				iMap.clear();
				iMap.put("panoramicId", panoramic.getId());
				iMap.put("tourUrl", str);
	        	panoramicPicHotspotsService.delByPanoramicIdAndTourUrl(iMap);
	        }
		}
		// ===== 获取语音数据回显
		List<PanoramicPicMusic> panoramicPicMusicList = panoramicPicMusicService.findListByPanoramicId(panoramic.getId());
		// ===== 配置文件回显操作,重新生成配置文件
		if(null != panoramic && "1".equals(panoramic.getTourFlag())){
			panoramicPicViewList = panoramicPicViewService.findListByPanoramicId(panoramic.getId());
			StringBuffer sb = new StringBuffer();
			sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n");
			sb.append("<krpano version=\"1.19\" title=\"Virtual Tour\">\r\n");
			sb.append("<include url=\"%SWFPATH%/skin/vtourskin.xml?v=1.3\" />\r\n");
//			sb.append("<skin_settings maps=\"false\" maps_type=\"google\" maps_bing_api_key=\"\" maps_google_api_key=\"\" maps_zoombuttons=\"false\" gyro=\"true\" webvr=\"true\" webvr_gyro_keeplookingdirection=\"false\" webvr_prev_next_hotspots=\"true\" littleplanetintro=\"true\" title=\"true\" thumbs=\"true\" thumbs_width=\"120\" thumbs_height=\"80\" thumbs_padding=\"10\" thumbs_crop=\"0|40|240|160\" thumbs_opened=\"false\" thumbs_text=\"false\" thumbs_dragging=\"true\" thumbs_onhoverscrolling=\"false\" thumbs_scrollbuttons=\"false\" thumbs_scrollindicator=\"false\" thumbs_loop=\"false\" tooltips_buttons=\"false\" tooltips_thumbs=\"false\" tooltips_hotspots=\"false\" tooltips_mapspots=\"false\" deeplinking=\"false\" loadscene_flags=\"MERGE\" loadscene_blend=\"OPENBLEND(0.5, 0.0, 0.75, 0.05, linear)\" loadscene_blend_prev=\"SLIDEBLEND(0.5, 180, 0.75, linear)\" loadscene_blend_next=\"SLIDEBLEND(0.5,   0, 0.75, linear)\" loadingtext=\"loading...\" layout_width=\"100%\" layout_maxwidth=\"814\" controlbar_width=\"-24\" controlbar_height=\"40\" controlbar_offset=\"20\" controlbar_offset_closed=\"-40\" controlbar_overlap.no-fractionalscaling=\"10\" controlbar_overlap.fractionalscaling=\"0\" design_skin_images=\"vtourskin.png\" design_bgcolor=\"0x2D3E50\" design_bgalpha=\"0.8\" design_bgborder=\"0\" design_bgroundedge=\"1\" design_bgshadow=\"0 4 10 0x000000 0.3\" design_thumbborder_bgborder=\"3 0xFFFFFF 1.0\" design_thumbborder_padding=\"2\" design_thumbborder_bgroundedge=\"0\" design_text_css=\"color:#FFFFFF; font-family:Arial;\" design_text_shadow=\"1\"/>");
			
			sb.append("<action name=\"startup\" autorun=\"onstart\">\r\n");
			sb.append("if(startscene === null OR !scene[get(startscene)], copy(startscene,scene[0].name); );loadscene(get(startscene), null, MERGE);playsound(bgsnd, '', 0);if(startactions !== null, startactions() );js('onready');\r\n");
			sb.append("</action>\r\n");
			for(int i=0;i<panoramicPicViewList.size();i++){
				PanoramicPicView panoramicPicView = panoramicPicViewList.get(i);
				String sceneName = panoramicPicView.getTourUrl();
				String codeView = panoramicPicView.getCode();
				sb.append("<scene name=\"" + sceneName + "\" title=\"" + sceneName + "\" onstart=\"\" thumburl=\"panos/" + sceneName + "/thumb.jpg\" ");
				for(int j=0;j<panoramicPicMusicList.size();j++){
					PanoramicPicMusic panoramicPicMusic = panoramicPicMusicList.get(j);
					if(sceneName.equals(panoramicPicMusic.getTourUrl())){
						sb.append(panoramicPicMusic.getCode() +  " ");
						break;
					}
				}
				sb.append("lat=\"\" lng=\"\" heading=\"\">\r\n");
				sb.append(codeView);
				sb.append("<preview url=\"panos/" + sceneName + "/preview.jpg\" />\r\n");
				sb.append("<image>\r\n");
				sb.append("<cube url=\"panos/" + sceneName + "/pano_%s.jpg\" />\r\n");
				sb.append("</image>\r\n");
				iMap.clear();
				iMap.put("panoramicId", panoramic.getId());
				iMap.put("tourUrl", sceneName);
				panoramicPicHotspotsList = panoramicPicHotspotsService.findListByPanoramicIdAndTourUrl(iMap);
				for(int j=0;j<panoramicPicHotspotsList.size();j++){
					PanoramicPicHotspots hotspots = panoramicPicHotspotsList.get(j);
					sb.append(hotspots.getCode());
					System.out.println(hotspots.getCode());
				}
				sb.append("</scene>\r\n");
			}
//			sb.append("<action name=\"add_all_the_time_tooltip_for_VR\">\r\n");
//			sb.append("txtadd(tooltipname, 'vrtooltip_', get(name));addhotspot(get(tooltipname)); set(hotspot[get(tooltipname)].type,text);copy(hotspot[get(tooltipname)].edge,hotspot[get(name)].edge);copy(hotspot[get(tooltipname)].distorted,hotspot[get(name)].distorted);copy(hotspot[get(tooltipname)].ath,hotspot[get(name)].ath);copy(hotspot[get(tooltipname)].atv,hotspot[get(name)].atv);set(hotspot[get(tooltipname)].oy,-50);set(hotspot[get(tooltipname)].ox,0);set(hotspot[get(tooltipname)].vcenter,false);set(hotspot[get(tooltipname)].padding,10);set(hotspot[get(tooltipname)].bg,true);set(hotspot[get(tooltipname)].bgcolor,0x000000);set(hotspot[get(tooltipname)].bgroundedge,5);set(hotspot[get(tooltipname)].bgalpha,0.65);set(hotspot[get(tooltipname)].bgborder,0);set(hotspot[get(tooltipname)].bgshadow,'0 0 0 0x000000 0');set(hotspot[get(tooltipname)].css,'text-align:left; color:#FFFFFF; font-family:MicrosoftYahei; font-size:24px;');if(device.mobile,set(hotspot[get(tooltipname)].css,'text-align:center; color:#FFFFFF; font-family:MicrosoftYahei; font-weight:bold; font-size:24px;'););set(hotspot[get(tooltipname)].txtshadow,'0 0 0 0x000000 0');if(text == '' OR text === null,copy(hotspot[get(tooltipname)].html,scene[get(linkedscene)].title),copy(hotspot[get(tooltipname)].html,text);); set(hotspot[get(tooltipname)].enabled,false); if(lp_running == false,set(hotspot[get(tooltipname)].visible,true); , 	if(!webvr.isenabled,if(lp_running == true,set(hotspot[get(tooltipname)].visible,false); set(hotspot[get(tooltipname)].mark2,true););););if(hotspot[get(name)].normal == false, set(hotspot[get(tooltipname)].normal,false);set(hotspot[get(tooltipname)].onloaded,if(webvr.isenabled,set(visible,false);,	if(lp_running == false OR lp_running == null OR lp_running === null,  set(visible,true);););););\r\n");
//			sb.append("</action>\r\n");
			sb.append("</krpano>\r\n");
			String path = request.getSession().getServletContext().getRealPath("krpano");
			String pathAll = path + "\\tour" +  panoramic.getTourUrl() + ".xml.jsp";
			FileUtils.createFile(pathAll);
			File f = new File(pathAll);
			try {  
			    FileOutputStream fos = new FileOutputStream(pathAll);  
			    //设置bom头
			    fos.write(new byte[]{(byte)0xEF, (byte)0xBB, (byte)0xBF});  
			    OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");  
			    BufferedWriter bw = new BufferedWriter(osw);  
			    bw.close();  
			} catch (IOException e) {  
			    System.out.println(e.toString());  
			}
			try {
				// 第四个属性必须要设置true,对存在的文件执行追加操作,否则上面设置的bom头会被覆盖掉
				FileUtils.writeStringToFile(f, sb.toString(), "UTF-8", true);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		try {
			response.sendRedirect(request.getContextPath() + "/krpano/tour_editor_custom.jsp" 
					+ "?panoramicId=" + panoramic.getId() 
					+ "&tourUrl=" + panoramic.getTourUrl() 
					+ "&tourFlag=" + panoramic.getTourFlag()
//					+ "&panoramicMaterialPicIds=" + panoramicMaterialPicIds
					+ "&tourUrlIds=" + tourUrls);
			System.out.println(request.getContextPath() + "/krpano/tour_editor_custom.jsp" 
					+ "?panoramicId=" + panoramic.getId() 
					+ "&tourUrl=" + panoramic.getTourUrl() 
					+ "&tourFlag=" + panoramic.getTourFlag()
//					+ "&panoramicMaterialPicIds=" + panoramicMaterialPicIds
					+ "&tourUrlIds=" + tourUrls);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 全景图保存
	 * @param panoramic
	 * @param request
	 * @param response
	 * @param data
	 * @throws IOException
	 */
	@RequiresPermissions("hnly:panoramic:edit")
	@RequestMapping(value = "vtourSave")
	public void vtourSave(Panoramic panoramic, HttpServletRequest request, HttpServletResponse response, @RequestBody String data) throws IOException{
//		data = URLDecoder.decode(URLDecoder.decode( data, "UTF-8"), "UTF-8");
		System.out.println(data);
		System.out.println(request.getParameter("panoramicId"));
		String panoramicId = request.getParameter("panoramicId");
		panoramic = panoramicService.get(panoramicId);
		System.out.println(request.getParameter("tourUrlIds"));
		String tourUrlIds = request.getParameter("tourUrlIds");
		String[] tourUrlIdsData = tourUrlIds.split(",");
//		System.out.println(request.getParameter("panoramicMaterialPicIds"));
//		String panoramicMaterialPicIds = request.getParameter("panoramicMaterialPicIds");
//		String[] panoramicMaterialPicIdsData = panoramicMaterialPicIds.split(",");
		
//		JSONObject obj = new JSONObject(data.substring(1, data.length()-1));
//		System.out.println(obj.getString("index"));
		JsonMapper ji = JsonMapper.getInstance();
		List<KrpanoView> krpanoViewList = (List<KrpanoView>)ji.fromJson(data, ji.createCollectionType(ArrayList.class, KrpanoView.class));
//		for(KrpanoView kv : krpanoViewList){
//			System.out.println(kv.getName());
//		}
//		KrpanoView kv = (KrpanoView) JsonMapper.fromJsonString(data.substring(1, data.length()-1), KrpanoView.class);
//		System.out.println(kv.getName() + kv.getInitH() + kv.getInitV());
		
		StringBuffer sb = new StringBuffer();
		String viewCode = "";
		sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n");
		sb.append("<krpano version=\"1.19\" title=\"Virtual Tour\">\r\n");
		sb.append("<include url=\"%SWFPATH%/skin/vtourskin.xml?v=1.3\" />\r\n");
		//sb.append("<skin_settings maps=\"false\" maps_type=\"google\" maps_bing_api_key=\"\" maps_google_api_key=\"\" maps_zoombuttons=\"false\" gyro=\"true\" webvr=\"true\" webvr_gyro_keeplookingdirection=\"false\" webvr_prev_next_hotspots=\"true\" littleplanetintro=\"true\" title=\"true\" thumbs=\"true\" thumbs_width=\"120\" thumbs_height=\"80\" thumbs_padding=\"10\" thumbs_crop=\"0|40|240|160\" thumbs_opened=\"false\" thumbs_text=\"false\" thumbs_dragging=\"true\" thumbs_onhoverscrolling=\"false\" thumbs_scrollbuttons=\"false\" thumbs_scrollindicator=\"false\" thumbs_loop=\"false\" tooltips_buttons=\"false\" tooltips_thumbs=\"false\" tooltips_hotspots=\"false\" tooltips_mapspots=\"false\" deeplinking=\"false\" loadscene_flags=\"MERGE\" loadscene_blend=\"OPENBLEND(0.5, 0.0, 0.75, 0.05, linear)\" loadscene_blend_prev=\"SLIDEBLEND(0.5, 180, 0.75, linear)\" loadscene_blend_next=\"SLIDEBLEND(0.5,   0, 0.75, linear)\" loadingtext=\"loading...\" layout_width=\"100%\" layout_maxwidth=\"814\" controlbar_width=\"-24\" controlbar_height=\"40\" controlbar_offset=\"20\" controlbar_offset_closed=\"-40\" controlbar_overlap.no-fractionalscaling=\"10\" controlbar_overlap.fractionalscaling=\"0\" design_skin_images=\"vtourskin.png\" design_bgcolor=\"0x2D3E50\" design_bgalpha=\"0.8\" design_bgborder=\"0\" design_bgroundedge=\"1\" design_bgshadow=\"0 4 10 0x000000 0.3\" design_thumbborder_bgborder=\"3 0xFFFFFF 1.0\" design_thumbborder_padding=\"2\" design_thumbborder_bgroundedge=\"0\" design_text_css=\"color:#FFFFFF; font-family:Arial;\" design_text_shadow=\"1\"/>");
		
		sb.append("<action name=\"startup\" autorun=\"onstart\">\r\n");
		sb.append("if(startscene === null OR !scene[get(startscene)], copy(startscene,scene[0].name); );loadscene(get(startscene), null, MERGE);playsound(bgsnd, '', 0);if(startactions !== null, startactions() );js('onready');\r\n");
		sb.append("</action>\r\n");
		for(int i=0;i<tourUrlIdsData.length;i++){
			String sceneName = tourUrlIdsData[i];
			sb.append("<scene name=\"" + sceneName + "\" title=\"" + sceneName + "\" onstart=\"\" thumburl=\"panos/" + sceneName + "/thumb.jpg\" ");
			for(int j=0;j<krpanoViewList.size();j++){
				KrpanoView kv = krpanoViewList.get(j);
				if(kv.getName().equals(sceneName) && null != kv.getBgmusic()){
					String codeMusic = "bgmusic=\"" + kv.getBgmusic() + "\" ";
					sb.append(codeMusic);
					iMap.clear();
					iMap.put("panoramicId", panoramic.getId());
					iMap.put("tourUrl", sceneName);
					PanoramicPicMusic panoramicPicMusic = panoramicPicMusicService.findByPanoramicIdAndTourUrl(iMap);
					if(null == panoramicPicMusic){
						panoramicPicMusic = new PanoramicPicMusic();
						panoramicPicMusic.setPanoramic(panoramic);
						panoramicPicMusic.setTourUrl(sceneName);
					}
					panoramicPicMusic.setCode(codeMusic);
					panoramicPicMusicService.save(panoramicPicMusic);
					break;
				}
			}
			sb.append("lat=\"\" lng=\"\" heading=\"\">\r\n");
			for(int j=0;j<krpanoViewList.size();j++){
				KrpanoView kv = krpanoViewList.get(j);
//				System.out.println(kv.getName());
				
				if(kv.getName().equals(sceneName)){
					if(null != kv.getInitH() && null != kv.getInitV() && null != kv.getFov()){
						viewCode = "<view hlookat=\"" + kv.getInitH() + "\" vlookat=\"" + kv.getInitV() + "\" fovtype=\"MFOV\" fov=\"" + kv.getFov() + "\" fovmin=\"5\" fovmax=\"120\" vlookatmin=\"-90\" vlookatmax=\"90\" limitview=\"auto\"/>\r\n";
						iMap.clear();
						iMap.put("panoramicId", panoramic.getId());
						iMap.put("tourUrl", sceneName);
						PanoramicPicView panoramicPicView = panoramicPicViewService.findByPanoramicIdAndTourUrl(iMap);
						panoramicPicView.setCode(viewCode);
						panoramicPicViewService.save(panoramicPicView);
					} else {
						viewCode = "<view hlookat=\"0\" vlookat=\"0\" fovtype=\"MFOV\" fov=\"90\" fovmin=\"5\" fovmax=\"120\" vlookatmin=\"-90\" vlookatmax=\"90\" limitview=\"auto\"/>\r\n";
					}
					sb.append(viewCode);
					break;
				}
				// 根据实际测试,场景中有多少个图片会传多少个参数,这个暂时隐藏,如出现意外情况,再加上
//				if((j+1)==krpanoViewList.size()){
//					viewCode = "<view hlookat=\"0\" vlookat=\"0\" fovtype=\"MFOV\" fov=\"90\" fovmin=\"5\" fovmax=\"120\" vlookatmin=\"-90\" vlookatmax=\"90\" limitview=\"auto\"/>\r\n";
//					sb.append(viewCode);
//				}
			}
			
			sb.append("<preview url=\"panos/" + sceneName + "/preview.jpg\" />\r\n");
			sb.append("<image>\r\n");
			sb.append("<cube url=\"panos/" + sceneName + "/pano_%s.jpg\" />\r\n");
			sb.append("</image>\r\n");
			for(int j=0;j<krpanoViewList.size();j++){
				KrpanoView kv = krpanoViewList.get(j);
				if(kv.getName().equals(sceneName)){
					for(KrpanoHotspots hotspots : kv.getHotSpots()){
						if(hotspots.getName().indexOf("vrtooltip") != -1) continue;
						String codeHotspots = "<hotspot text=\"" + hotspots.getText() + "\" ath=\"" + hotspots.getAth() + "\" atv=\"" + hotspots.getAtv() + "\" linkedscene=\"" + hotspots.getLinkedscene() + "\" name=\"" + hotspots.getName() + "\" style=\"" + hotspots.getStyle() + "\" dive=\"" + hotspots.isDive() + "\" onloaded=\"add_all_the_time_tooltip_for_VR()\"/>\r\n";
						//sb.append(codeHotspots);
						iMap.clear();
						iMap.put("panoramicId", panoramic.getId());
						iMap.put("tourUrl", sceneName);
						iMap.put("name", hotspots.getName());
						System.out.println(hotspots.getName());
						PanoramicPicHotspots panoramicPicHotspots = panoramicPicHotspotsService.findByPanoramicIdAndTourUrlAndName(iMap);
						if(null == panoramicPicHotspots){
							panoramicPicHotspots = new PanoramicPicHotspots();
							panoramicPicHotspots.setPanoramic(panoramic);
							panoramicPicHotspots.setTourUrl(sceneName);
							panoramicPicHotspots.setName(hotspots.getName());
							panoramicPicHotspots.setLinkedscene(hotspots.getLinkedscene());
						}
						panoramicPicHotspots.setCode(codeHotspots);
						panoramicPicHotspotsService.save(panoramicPicHotspots);
					}
					iMap.clear();
					iMap.put("panoramicId", panoramic.getId());
					iMap.put("tourUrl", sceneName);
					List<PanoramicPicHotspots> panoramicPicHotspotsList = panoramicPicHotspotsService.findListByPanoramicIdAndTourUrl(iMap);
					for(int k=0;k<panoramicPicHotspotsList.size();k++){
						PanoramicPicHotspots hotspots = panoramicPicHotspotsList.get(k);
						sb.append(hotspots.getCode());
						System.out.println(hotspots.getCode());
					}
				}
			}
			sb.append("</scene>\r\n");
		}
		//sb.append("<action name=\"add_all_the_time_tooltip_for_VR\">\r\n");
		//sb.append("txtadd(tooltipname, 'vrtooltip_', get(name));addhotspot(get(tooltipname)); set(hotspot[get(tooltipname)].type,text);copy(hotspot[get(tooltipname)].edge,hotspot[get(name)].edge);copy(hotspot[get(tooltipname)].distorted,hotspot[get(name)].distorted);copy(hotspot[get(tooltipname)].ath,hotspot[get(name)].ath);copy(hotspot[get(tooltipname)].atv,hotspot[get(name)].atv);set(hotspot[get(tooltipname)].oy,-50);set(hotspot[get(tooltipname)].ox,0);set(hotspot[get(tooltipname)].vcenter,false);set(hotspot[get(tooltipname)].padding,10);set(hotspot[get(tooltipname)].bg,true);set(hotspot[get(tooltipname)].bgcolor,0x000000);set(hotspot[get(tooltipname)].bgroundedge,5);set(hotspot[get(tooltipname)].bgalpha,0.65);set(hotspot[get(tooltipname)].bgborder,0);set(hotspot[get(tooltipname)].bgshadow,'0 0 0 0x000000 0');set(hotspot[get(tooltipname)].css,'text-align:left; color:#FFFFFF; font-family:MicrosoftYahei; font-size:24px;');if(device.mobile,set(hotspot[get(tooltipname)].css,'text-align:center; color:#FFFFFF; font-family:MicrosoftYahei; font-weight:bold; font-size:24px;'););set(hotspot[get(tooltipname)].txtshadow,'0 0 0 0x000000 0');if(text == '' OR text === null,copy(hotspot[get(tooltipname)].html,scene[get(linkedscene)].title),copy(hotspot[get(tooltipname)].html,text);); set(hotspot[get(tooltipname)].enabled,false); if(lp_running == false,set(hotspot[get(tooltipname)].visible,true); , 	if(!webvr.isenabled,if(lp_running == true,set(hotspot[get(tooltipname)].visible,false); set(hotspot[get(tooltipname)].mark2,true););););if(hotspot[get(name)].normal == false, set(hotspot[get(tooltipname)].normal,false);set(hotspot[get(tooltipname)].onloaded,if(webvr.isenabled,set(visible,false);,	if(lp_running == false OR lp_running == null OR lp_running === null,  set(visible,true);););););\r\n");
		//sb.append("</action>\r\n");
		sb.append("</krpano>\r\n");
		
		String path = request.getSession().getServletContext().getRealPath("krpano");
		String pathAll = path + "\\tour" +  panoramic.getTourUrl() + ".xml.jsp";
		FileUtils.createFile(pathAll);
		File f = new File(pathAll);
//		if(!f.exists()){  
//            f.mkdirs();  
//        } 
		try {  
		    FileOutputStream fos = new FileOutputStream(pathAll);  
		    //设置bom头
		    fos.write(new byte[]{(byte)0xEF, (byte)0xBB, (byte)0xBF});  
		    OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");  
		    BufferedWriter bw = new BufferedWriter(osw);  
		    bw.close();  
		} catch (IOException e) {  
		    System.out.println(e.toString());  
		}
		// 第四个属性必须要设置true,对存在的文件执行追加操作,否则上面设置的bom头会被覆盖掉
		FileUtils.writeStringToFile(f, sb.toString(), "UTF-8", true);
		
		panoramic = panoramicService.get(panoramicId);
		panoramic.setTourFlag("1");
		panoramicService.save(panoramic);
		
    	response.setContentType("text/html;charset=utf-8");
    	PrintWriter pw = response.getWriter();
    	String mess = "保存成功";
		pw.write(URLDecoder.decode(mess, "utf-8"));
		pw.flush();
		pw.close();
	}
	
	public static <T> List<T> compare(T[] t1, T[] t2) {    
	      List<T> list1 = Arrays.asList(t1);    
	      List<T> list2 = new ArrayList<T>();    
	      for (T t : t2) {    
	          if (!list1.contains(t)) {    
	              list2.add(t);    
	          }    
	      }    
	      return list2;    
	  }  
}

全景编辑器

tour_editor_custom.jsp

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/WEB-INF/views/include/taglib.jsp"%>

<!DOCTYPE html>
<html>
<head>
    <title>全景高级编辑DEMO</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"/>
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <meta http-equiv="x-ua-compatible" content="IE=edge"/>
    <link rel="stylesheet" href="./style/krpano.editor.css">
    <style>
        @-ms-viewport {
            width: device-width;
        }

        @media only screen and (min-device-width: 800px) {
            html {
                overflow: hidden;
            }
        }

        html {
            height: 100%;
        }

        body {
            height: 100%;
            overflow: hidden;
            margin: 0;
            padding: 0;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px;
            color: #FFFFFF;
            background-color: #000000;
        }
        .sureBtn {
        	background-color: #00a3d8;
			border-bottom-color: #00a3d8;
			border-bottom-left-radius: 0px;
			border-bottom-right-radius: 0px;
			border-bottom-style: solid;
			border-bottom-width: 1px;
			border-image-outset: 0;
			border-image-repeat: stretch stretch;
			border-image-slice: 100%;
			border-image-source: none;
			border-image-width: 1;
			border-left-color: #00a3d8;
			border-left-style: solid;
			border-left-width: 1px;
			border-right-color: #00a3d8;
			border-right-style: solid;
			border-right-width: 1px;
			border-top-color: #00a3d8;
			border-top-left-radius: 0px;
			border-top-right-radius: 0px;
			border-top-style: solid;
			border-top-width: 1px;
			box-sizing: border-box;
			color: rgb(255, 255, 255);
			cursor: pointer;
			display: inline-block;
			font-family: "microsoft yahei",Arial,Helvetica,sans-serif;
			font-feature-settings: normal;
			font-kerning: auto;
			font-language-override: normal;
			font-size: 13px;
			font-size-adjust: none;
			font-stretch: normal;
			font-style: normal;
			font-variant: normal;
			font-variant-alternates: normal;
			font-variant-caps: normal;
			font-variant-east-asian: normal;
			font-variant-ligatures: normal;
			font-variant-numeric: normal;
			font-variant-position: normal;
			font-weight: 400;
			line-height: 20px;
			list-style-image: none;
			list-style-position: outside;
			list-style-type: none;
			margin-bottom: 0px;
			margin-left: 0px;
			margin-right: 0px;
			margin-top: 0px;
			padding-bottom: 5px;
			padding-left: 12px;
			padding-right: 12px;
			padding-top: 5px;
			text-align: center;
			text-shadow: rgba(0, 0, 0, 0.2) 0px -1px 0px;
			text-transform: none;
			transition-delay: 0s;
			transition-duration: 0.4s;
			transition-property: all;
			transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1);
			vertical-align: middle;
			white-space: nowrap;
			-moz-border-bottom-colors: none;
			-moz-border-left-colors: none;
			-moz-border-right-colors: none;
			-moz-border-top-colors: none;
			-moz-user-select: none;
        }
    </style>
</head>
<body>

<script src="tour.js"></script>

<div id="pano" style="width:100%;height:100%;">
    <noscript>
        <table style="width:100%;height:100%;">
            <tr style="vertical-align:middle;">
                <td>
                    <div style="text-align:center;">ERROR:<br/><br/>Javascript not activated<br/><br/></div>
                </td>
            </tr>
        </table>
    </noscript>
    <script>
    	//alert("${param.prefixUrl}");
    	//touFlag为1,为回显编辑模式,调用对应生成的XML文件,否则使用默认的模板文件
        embedpano({
            swf: "tour.swf",
            xml: "tour${param.tourFlag eq '1' ? param.tourUrl : ''}.xml.jsp?tourUrlIds=${param.tourUrlIds}",
            target: "pano",
            html5: "auto",
            mobilescale: 1.0,
            passQueryParameters: true
        });
    </script>
</div>

<input type="hidden" name="panoramicId" id="panoramicId" value="${param.panoramicId}"/>
<!-- 
<input type="hidden" name="panoramicMaterialPicIds" id="panoramicMaterialPicIds" value="${param.panoramicMaterialPicIds}"/> -->
<input type="hidden" name="tourUrlIds" id="tourUrlIds" value="${param.tourUrlIds}"/>

<div class="frame" name="#viewFrame">
    <button onclick="setAsDefaultView()" class="btn btn-blue">设为初始视角</button>
    <div class="frame-line frame-line-top"></div>
    <div class="frame-line frame-line-right"></div>
    <div class="frame-line frame-line-bottom"></div>
    <div class="frame-line frame-line-left"></div>
    <span class="angle angle-tl"><i class="angle-a"></i><i class="angle-b"></i></span>
    <span class="angle angle-tr"><i class="angle-a"></i><i class="angle-b"></i></span>
    <span class="angle angle-bl"><i class="angle-a"></i><i class="angle-b"></i></span>
    <span class="angle angle-br"><i class="angle-a"></i><i class="angle-b"></i></span>
</div>
<div class="overlay overlay-right">
    <div class="save-wrap">
        <button onclick="save()" id="isEdited" class="btn btn-blue">保存</button>
    </div>
    <div class="tool-panel">
        <ul class="tool-btn-lst">
            <li>
                <span class="btn J-tool-btn btn-blue" data-target="#viewFrame">视角</span>
                <div class="tool-main" style="display: block" name="#viewFrame">
                    <section class="tool-section">
                        <div style="margin: 5px;">
                            <label style="padding-right: 5px;vertical-align: middle;" for="autoSpin">自动旋转</label>
                            <input type="checkbox" name="autoSpin" id="autoSpin" style="vertical-align: middle;"
                                   onclick="autoSpinClick()"/>
                        </div>
                        <div id="waitTimeInput" style="display: none;margin: 5px;">
                            <label style="padding-right: 5px;vertical-align: middle;" for="waitTime">等待时间</label>
                            <input type="text" class="wait-time-input" id="waitTime" onblur="autoSpinClick()"/>
                            <label style="padding-left: 5px">秒</label>
                        </div>
                        <div style="margin: 5px;">
                            <label>(默认应用于所有场景)</label>
                        </div>
                    </section>
                    <section class="tool-section">
                        <div style="margin: 5px;">
                            <label>初始fov
                                <input type="text" class="fov-input" id="initFov" onblur="updateFov()"/>
                            </label>
                        </div>
                        <section id="sample-pb">
                            <article>
                                <div class="number-pb">
                                    <div class="number-pb-shown" style="display: none">
                                        <div class="triangle triangle-up-left" style="float: left;"></div>
                                        <div class="triangle triangle-down"></div>
                                        <div class="triangle triangle-up-right" style="float: right;"></div>
                                    </div>
                                    <div class="number-pb-num" style="left: 70%;">
                                    </div>
                                </div>
                            </article>
                        </section>
                        <div style="margin: 5px;">
                            <label>最小fov
                                <input type="text" class="fov-input" id="initFovMin" onblur="updateFov()"/>
                            </label>
                        </div>
                        <div style="margin: 5px;">
                            <label>最大fov
                                <input type="text" class="fov-input" id="initFovMax" onblur="updateFov()"/>
                            </label>
                        </div>
                        <div style="margin: 5px;">
                            <input type="button" style="vertical-align: middle;" value="应用于所有场景" class="btn btn-blue"
                                   onclick="fovForAll()"/>
                        </div>
                    </section>
                </div>
            </li>
            <li>
                <span class="btn J-tool-btn" data-target="#toolHot">热点</span>
                <div class="tool-main" name="#toolHot" id="hotToolButton">
                    <section class="tool-section">
                        <h3 style="margin-bottom: 5px;">热点类型</h3>
                        <button class="btn btn-blue">场景切换</button>
                    </section>
                    <section class="tool-section">
                        <h3 style="margin-bottom: 5px;">热点列表</h3>
                        <ul>
                            <div id="hotSpotList"></div>
                            <script id="tplHotSpotList" type="text/html">
                                {{each list as eachSpot}}
                                <div class="hot-spot-list" name="{{eachSpot.name}}Hover">
                                    <div class="hot-spot-img" style="background-image: url('{{eachSpot.url}}')"
                                         spot-style="{{eachSpot.style}}"></div>
                                    <div class="hot-spot-text">{{eachSpot.linkedscene}}</div>
                                    <div class="hot-spot-del" onclick="removeHotSpot('{{eachSpot.name}}')">-</div>
                                </div>
                                {{/each}}
                            </script>
                        </ul>
                        <button class="hot-spot-button" onclick="showAddHotSpot()">+</button>
                    </section>
                </div>
            </li>
            <li>
                <span class="btn J-tool-btn" data-target="#toolVoice">音乐</span>
                <div class="tool-main" name="#toolVoice" id="toolVoiceButton">
                    <section class="tool-section">
                        <h3 style="margin-bottom: 5px;">音乐类型</h3>
                        <button class="btn btn-blue">语音播报</button>
                        <button class="btn btn-blue">背景音乐</button>
                    </section>
                    <section class="tool-section">
                        <h3 style="margin-bottom: 5px;">音乐列表</h3>
                        <ul>
                            <div id="bgMusicList"></div>
                            <script id="tplBgMusicList" type="text/html">
                                {{each list as eachMusic}}
                                <div class="hot-spot-list" name="{{eachMusic.name}}Hover">   
                                    <div class="hot-spot-text">{{eachMusic.name}}</div>
                                    <div class="hot-spot-del" onclick="removeBgMusic('{{eachMusic.name}}')">-</div>
                                </div>
                                {{/each}}
                            </script>
                        </ul>
                        <button class="hot-spot-button" onclick="showAddVoice()">+</button>
                    </section>
                </div>
            </li>
        </ul>
    </div>
</div>
<div class="left-column">
    <div class="scene-select">
        <div class="blue-banner"></div>
        <div class="select_scene_text">
            <p class="p_title">场景选择</p>
        </div>
        <div class="blue-banner"></div>
        <ul style="margin: 0;padding: 0;">
            <div id="sceneList"></div>
            <script id="tplSceneList" type="text/html">
                {{each list as scene}}
                <li key="{{scene.index}}" name="{{scene.name}}" class="li-scene">
                    <div class="thumbs-img-scene-list"
                         style='background-image: url("panos/{{scene.name}}/thumb.jpg")'></div>
                    <div class="li-scene-span" onclick="changeScene({{scene.index}})">{{scene.name}}</div>
                    <input type="hidden" value="{{scene.name}}" class="li-scene-input" onblur="doRename($(this))"/>
                    <input type="button" class="scene-li-button" onclick="rename($(this).prev())"/>
                    <div class="circle" onclick="selectWelcomeScene({{scene.index}})"></div>
                </li>
                {{/each}}
            </script>
        </ul>
    </div>
</div>
<div class="add-hot-pot" style="display: none" name="#toolHot">
    <div class="add-hot-banner">添加全景切换热点<a class="div-close" onclick="hideAddHotSpot()">×</a></div>
    <div class="progress-banner">
        <div class="progress-title progress-title-on" id="selectStyleTitle"><span style="line-height: 30px">选择样式</span>
        </div>
        <div class="progress-title" id="goToSceneTitle"><span style="line-height: 30px">选择目标场景</span></div>
        <div class="progress-title" id="writeTitleTitle"><span style="line-height: 30px">填写title</span></div>
    </div>
    <div>
        <div class="dive-text">俯冲效果:</div>
        <div class="my-open-out">
            <div class="my-open-in my-open-in-open"></div>
        </div>
    </div>
    <div id="selectStyle" class="add-hot-content">
        <div class="add-hot-bottom-div">
            <div class="hot-style"
                 style="background-image: url('./skin/vtourskin_hotspot.png')"
                 name="skin_hotspotstyle"></div>
        </div>
        <div class="add-hot-button" onclick="nextToSelectTargetScene()">下一步</div>
    </div>
    <div id="goToScene" class="add-hot-content" style="display: none">
        <div class="add-hot-bottom-div">
            <div id="targetScene"></div>
            <script id="tplTargetScene" type="text/html">
                {{each list as each}}
                <div class="select-scene-div" name="{{each.name}}">
                    {{each.name}}
                    <div class="thumbs-img" style='background-image: url("panos/{{each.name}}/thumb.jpg")'></div>
                </div>
                {{/each}}
            </script>
        </div>
        <div class="add-hot-button" onclick="nextToWriteTitle()">下一步</div>
    </div>
    <div id="writeTitle" class="add-hot-content write-title" style="display: none">
        <div class="add-hot-bottom-div">
            <p style="padding: 50px;"><label for="addHotTitle">请出入热点上方的文字title(可不填):</label></p>
            <input type="text" id="addHotTitle"/>
        </div>
        <div class="add-hot-button" onclick="addHotSpot()">完成</div>
    </div>
</div>

<div class="add-voice" style="display: none" name="#toolVoice">
	<div class="add-hot-banner">添加背景语音/音乐<a class="div-close" onclick="hideAddVoice()">×</a></div>
	<div id="writeTitle" class="add-hot-content write-title">
        <div class="add-hot-bottom-div" id="add-voice-frame">
            <p style="padding: 20px;"><label for="addHotTitle">请选择一段语音/音乐插入到场景中:</label> <button class="sureBtn" onclick="addVoice()">确定选择</button></p>
        </div>
    </div>
</div>

<script src="./script/jQuery-2.1.4.min.js"></script>
<script src="./script/krpano.editor.js"></script>
<script src="./script/template.min.js"></script>
</body>
</html>

krpano.editor.css

html, body, div, span, applet, input, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, menu, nav, output, ruby, section, summary, time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    vertical-align: baseline;
}

article, aside, details, figcaption, figure, footer, header, menu, nav, section {
    display: block;
}

body {
    line-height: 1;
}

ol, ul {
    list-style: none;
}

blockquote, q {
    quotes: none;
}

blockquote:before,
blockquote:after {
    content: none;
}

q:before,
q:after {
    content: "";
}

table {
    border-collapse: collapse;
    border-spacing: 0;
}

button {
    padding: 0;
    margin: 0;
    background-color: #fff;
    border: none;
    outline: 0;
}

body {
    font-family: 'PingFang SC', 'Helvetica Neue', 'Helvetica', 'STHeitiSC-Light', 'Arial', 'Microsoft Yahei', sans-serif;
    font-size: 14px;
    line-height: 1.5;
}

a {
    text-decoration: none;
}

.btn {
    cursor: pointer;
    display: inline-block;
    padding: 8px 20px;
    background-color: rgba(0, 0, 0, .7);
    color: #fff;
    border-radius: 4px;
    font-size: 14px;
}

.btn-blue {
    background-color: #2185D0;
}

.scene-name {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    background-color: rgba(0, 0, 0, .6);
    color: #fff;
    text-align: right;
    height: 40px;
    line-height: 40px;
    padding-right: 15px;
}

.frame-line {
    position: absolute;
    background-color: #eee;
}

.frame-line-top,
.frame-line-bottom {
    height: 1px;
    left: 30%;
    right: 30%;
}

.frame-line-top {
    top: 25%;
}

.frame-line-bottom {
    bottom: 25%;
}

.frame-line-left,
.frame-line-right {
    top: 25%;
    bottom: 25%;
    width: 1px;
}

.frame-line-left {
    left: 30%;
}

.frame-line-right {
    right: 30%;
}

.angle {
    width: 40px;
    height: 40px;
    position: absolute;
}

.angle i {
    position: absolute;
    background-color: #eee;
}

.angle-a {
    left: 0;
    width: 8px;
    top: 0;
    bottom: 0;
}

.angle-b {
    top: 0;
    left: 0;
    right: 0;
    height: 8px;
}

.angle-tl {
    left: 30%;
    top: 25%;
}

.angle-tr {
    right: 30%;
    top: 25%;
}

.angle-tr .angle-a {
    left: auto;
    right: 0;
}

.angle-bl {
    left: 30%;
    bottom: 25%;
}

.angle-bl .angle-b {
    bottom: 0;
    top: auto;
}

.angle-br {
    right: 30%;
    bottom: 25%;
}

.angle-br .angle-a {
    left: auto;
    right: 0;
}

.angle-br .angle-b {
    top: auto;
    bottom: 0;
}

.frame .btn {
    position: absolute;
    left: 50%;
    top: 30%;
    transform: translate(-50%, 0);
}

.overlay {
    position: absolute;
    right: 15px;
    top: 15px;
    z-index: 9999;
}

.save-wrap {
    margin-top: 40px;
    margin-bottom: 20px;
}

.tool-panel {
    position: relative;
}

.tool-btn-lst {
    float: right;
}

.tool-btn-lst > li {
    margin-bottom: 10px;
    position: relative;
}

.tool-main {
    moz-user-select: -moz-none;
    -moz-user-select: none;
    -o-user-select:none;
    -khtml-user-select:none;
    -webkit-user-select:none;
    -ms-user-select:none;
    user-select:none;
    display: none;
    position: absolute;
    right: 80px;
    top: 0;
    padding: 15px;
    background-color: rgba(0, 0, 0, .7);
    min-width: 200px;
    border-top: 3px solid #00a3d8;
}

.tool-section {
    border-bottom: 1px solid #2185D0;
    padding: 15px 0;
}

.tool-section:last-child {
    margin-bottom: 0;
    border-bottom: none;
    padding-bottom: 0;
}

.tool-section:first-child {
    padding-top: 0;
}

.tool-section h4 {
    color: #999;
}

.choose-lst {
    margin: 7px 0;
}

.choose-lst li {
    padding: 3px 0;
}

.choose-lst input {
    margin-right: 5px;
}

.left-column {
    position: absolute;
    top: 0;
    left: -250px;
    z-index: 9999;
    background-color: rgba(0, 0, 0, 0.3);
    width: 250px;
    height: 100%;
    -webkit-animation:hideLeft 0.8s infinite;
    -webkit-animation-iteration-count:1;
}

@-webkit-keyframes showLeft {
     0% {left: -250px;}
     100% {left: 0;}
}

@-webkit-keyframes hideLeft {
    0% {left: 0;}
    100% {left: -250px;}
}

.scene-select {
    margin-top: 20px;
    margin-left: 10px;
    margin-right: 10px;
    background-color: rgba(0, 0, 0, 0.5);
    padding-bottom: 1px;
    overflow: auto;
    max-height: 600px;
    overflow-x: hidden;
}

.blue-banner {
    background-color: #00a3d8;
    height: 3px;
}

.li-scene {
    list-style-type: none;
    height: 30px;
    border: 2px solid rgba(255, 255, 255, 0);
    margin: 10px;
    width: 200px;
}

.li-scene:hover {
    border-color: #FF9800;
}

.li-scene-hover {
    border-color: #FF9800;
}

.li-scene-span {
    cursor: pointer;
    height: 30px;
    font-size: 16px;
    line-height: 30px;
    float: left;
    width: 100px;
    overflow: hidden;
}

.li-scene-input {
    background-color: rgba(185, 185, 185, 0.5);
    height: 30px;
    width: 100px;
    font-size: 18px;
}

.scene-li-button {
    width: 30px;
    height: 30px;
    background: rgba(255, 255, 255, 0) url("../img/krpano.modify.png");
    border: 0;
    float: right;
    cursor: pointer;
}

.circle {
    width: 30px;
    height: 30px;
    float: right;
    background: #292827 url("../img/krpano.home.png");
    border-radius: 50%;
    text-align: center;
    line-height: 30px;
    cursor: pointer;
}

.select_scene_text {
    text-align: center;
    background-color: rgba(40, 40, 40, 0.7);
    height: 50px;
}

.p_title {
    margin-top: 0;
    font-size: 20px;
    line-height: 50px;
}

.add-hot-pot {
    position: absolute;
    z-index: 9999;
    background-color: rgba(0, 0, 0, 0.8);
    width: 700px;
    height: 440px;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    margin: auto;
}

.add-voice {
    position: absolute;
    z-index: 9999;
    background-color: rgba(0, 0, 0, 0.8);
    width: 700px;
    height: 440px;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    margin: auto;
}

.progress-banner {
    margin: 20px;
    background-color: rgba(150, 150, 150, 0.4);
    height: 30px;
}

.progress-title {
    float: left;
    text-align: center;
    width: 33.33%;
    height: 100%;
}

.progress-title-on {
    background-color: #00a3d8;
}

.add-hot-banner {
    font-size: 16px;
    background-color: rgba(150, 150, 150, 0.4);
    padding: 8px 8px 8px 15px;
    height: 20px;
    line-height: 20px;
}

.div-close {
    cursor: pointer;
    float: right;
    font-size: 30px;
}

.add-hot-content {
    margin: 10px 20px 20px 20px;
}

.add-hot-bottom-div {
    height: 250px;
}

.write-title {
    font-size: 18px;
    text-align: center;
}

#addHotTitle {
    color: white;
    width: 57%;
    background-color: rgba(150, 150, 150, 0.4);
}

.add-hot-button {
    cursor: pointer;
    background-color: #00a3d8;
    line-height: 30px;
    text-align: center;
    font-size: 18px;
    height: 30px;
}

.hot-style {
    background-color: rgba(255, 255, 255, 0);
    border: 2px solid rgba(255, 255, 255, 0);
    cursor: pointer;
    margin: 7px;
    width: 64px;
    height: 56px;
    background-size: cover;
    float: left;
}

.hot-spot-img {
    background-color: rgba(255, 255, 255, 0);
    width: 32px;
    height: 32px;
    background-size: cover;
    float: left;
}

.hot-style:hover {
    border: 2px solid orange;
}

.hot-style-on {
    border: 2px solid orange;
}

.select-scene-div {
    float: left;
    width: 80px;
    text-align: center;
    cursor: pointer;
    margin: 5px;
}

.select-scene-div:hover {
    margin: 3px;
    border: 2px solid orange;
}

.select-scene-div-on {
    margin: 3px;
    border: 2px solid orange;
}

.thumbs-img {
    height: 80px;
    background-size: 80px 80px;
    margin-top: 5px;
    margin-left: auto;
    margin-right: auto;
}

.thumbs-img-scene-list {
    width: 30px;
    height: 30px;
    background-size: 30px 30px;
    float: left;
    margin-right: 10px;
}

.hot-pot-select-span {
    position: absolute;
    left: 15px;
    top: 5px;
}

.wait-time-input {
    vertical-align: middle;
    width: 30px;
    background-color: rgba(255, 255, 255, 0.5);
    text-align: center
}

.fov-input {
    vertical-align: middle;
    width: 65px;
    background-color: rgba(255, 255, 255, 0.5);
    text-align: center;
    float: right;
    height: 21px;
}

.hot-spot-list {
    height: 32px;
    width: 200px;
    color: white;
    font-size: 18px;
    border: solid 2px rgba(0, 0, 0, 0);
    margin-top: 5px;
}

.hot-spot-text {
    width: 130px;
    height: 26px;
    float: left;
    text-align: center;
    padding: 3px;
}

.hot-spot-del {
    cursor: pointer;
    width: 32px;
    height: 32px;
    float: left;
    text-align: center;
    background-color: rgba(255, 255, 255, 0.1);
}

.hot-spot-button {
    cursor: pointer;
    background-color: rgba(255, 255, 255, 0.1);
    height: 32px;
    width: 202px;
    color: white;
    font-size: 18px;
    margin-top: 10px;
}

.hot-spot-list-hover {
    border: solid 2px orange;
}

.number-pb {
    position: relative;
    height: 3px;
    background-color: #ffffff;
    margin: 40px 0;
}

.number-pb .number-pb-shown {
    position: absolute;
    background: #00a3d8;
    left: 0;
    height: 3px;
}

.number-pb .number-pb-num {
    position: absolute;
    background-color: #00a3d8;
    left: 0;
    padding: 0 5px;
}

.triangle-up-left {
    border-bottom: 20px solid #00a3d8;
    margin-top: 3px;
    margin-left: -10px;
}

.triangle-up-right {
    border-bottom: 20px solid #00a3d8;
    margin-top: 3px;
    margin-right: -10px;
}

.triangle-down {
    border-top: 20px solid #00a3d8;
    margin-top: -20px;
    float: none;
}

.triangle {
    width: 0;
    height: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
}

.my-open-out {
    margin-left: 90px;
    width: 40px;
    height: 20px;
    border-radius: 10px;
    position: relative;
    background: #00a3d8;
}

.my-open-in {
    width: 18px;
    height: 18px;
    border-radius: 9px;
    position: absolute;
    background: white;
    box-shadow: 0 2px 4px rgba(0,0,0,0.4);
    top: 1px;
}

.my-open-in-open {
    right: 1px;
}

.my-open-in-close {
    left: 1px;
}

.dive-text {
    line-height: 20px;
    float: left;
    margin-left: 20px;
}

jQuery-2.1.4.min.js

(略),自行下载。

template.min.js

/*!art-template - Template Engine | http://aui.github.com/artTemplate/*/
!function(){function a(a){return a.replace(t,"").replace(u,",").replace(v,"").replace(w,"").replace(x,"").split(y)}function b(a){return"'"+a.replace(/('|\\)/g,"\\$1").replace(/\r/g,"\\r").replace(/\n/g,"\\n")+"'"}function c(c,d){function e(a){return m+=a.split(/\n/).length-1,k&&(a=a.replace(/\s+/g," ").replace(/<!--[\w\W]*?-->/g,"")),a&&(a=s[1]+b(a)+s[2]+"\n"),a}function f(b){var c=m;if(j?b=j(b,d):g&&(b=b.replace(/\n/g,function(){return m++,"$line="+m+";"})),0===b.indexOf("=")){var e=l&&!/^=[=#]/.test(b);if(b=b.replace(/^=[=#]?|[\s;]*$/g,""),e){var f=b.replace(/\s*\([^\)]+\)/,"");n[f]||/^(include|print)$/.test(f)||(b="$escape("+b+")")}else b="$string("+b+")";b=s[1]+b+s[2]}return g&&(b="$line="+c+";"+b),r(a(b),function(a){if(a&&!p[a]){var b;b="print"===a?u:"include"===a?v:n[a]?"$utils."+a:o[a]?"$helpers."+a:"$data."+a,w+=a+"="+b+",",p[a]=!0}}),b+"\n"}var g=d.debug,h=d.openTag,i=d.closeTag,j=d.parser,k=d.compress,l=d.escape,m=1,p={$data:1,$filename:1,$utils:1,$helpers:1,$out:1,$line:1},q="".trim,s=q?["$out='';","$out+=",";","$out"]:["$out=[];","$out.push(",");","$out.join('')"],t=q?"$out+=text;return $out;":"$out.push(text);",u="function(){var text=''.concat.apply('',arguments);"+t+"}",v="function(filename,data){data=data||$data;var text=$utils.$include(filename,data,$filename);"+t+"}",w="'use strict';var $utils=this,$helpers=$utils.$helpers,"+(g?"$line=0,":""),x=s[0],y="return new String("+s[3]+");";r(c.split(h),function(a){a=a.split(i);var b=a[0],c=a[1];1===a.length?x+=e(b):(x+=f(b),c&&(x+=e(c)))});var z=w+x+y;g&&(z="try{"+z+"}catch(e){throw {filename:$filename,name:'Render Error',message:e.message,line:$line,source:"+b(c)+".split(/\\n/)[$line-1].replace(/^\\s+/,'')};}");try{var A=new Function("$data","$filename",z);return A.prototype=n,A}catch(B){throw B.temp="function anonymous($data,$filename) {"+z+"}",B}}var d=function(a,b){return"string"==typeof b?q(b,{filename:a}):g(a,b)};d.version="3.0.0",d.config=function(a,b){e[a]=b};var e=d.defaults={openTag:"<%",closeTag:"%>",escape:!0,cache:!0,compress:!1,parser:null},f=d.cache={};d.render=function(a,b){return q(a,b)};var g=d.renderFile=function(a,b){var c=d.get(a)||p({filename:a,name:"Render Error",message:"Template not found"});return b?c(b):c};d.get=function(a){var b;if(f[a])b=f[a];else if("object"==typeof document){var c=document.getElementById(a);if(c){var d=(c.value||c.innerHTML).replace(/^\s*|\s*$/g,"");b=q(d,{filename:a})}}return b};var h=function(a,b){return"string"!=typeof a&&(b=typeof a,"number"===b?a+="":a="function"===b?h(a.call(a)):""),a},i={"<":"&#60;",">":"&#62;",'"':"&#34;","'":"&#39;","&":"&#38;"},j=function(a){return i[a]},k=function(a){return h(a).replace(/&(?![\w#]+;)|[<>"']/g,j)},l=Array.isArray||function(a){return"[object Array]"==={}.toString.call(a)},m=function(a,b){var c,d;if(l(a))for(c=0,d=a.length;d>c;c++)b.call(a,a[c],c,a);else for(c in a)b.call(a,a[c],c)},n=d.utils={$helpers:{},$include:g,$string:h,$escape:k,$each:m};d.helper=function(a,b){o[a]=b};var o=d.helpers=n.$helpers;d.onerror=function(a){var b="Template Error\n\n";for(var c in a)b+="<"+c+">\n"+a[c]+"\n\n";"object"==typeof console&&console.error(b)};var p=function(a){return d.onerror(a),function(){return"{Template Error}"}},q=d.compile=function(a,b){function d(c){try{return new i(c,h)+""}catch(d){return b.debug?p(d)():(b.debug=!0,q(a,b)(c))}}b=b||{};for(var g in e)void 0===b[g]&&(b[g]=e[g]);var h=b.filename;try{var i=c(a,b)}catch(j){return j.filename=h||"anonymous",j.name="Syntax Error",p(j)}return d.prototype=i.prototype,d.toString=function(){return i.toString()},h&&b.cache&&(f[h]=d),d},r=n.$each,s="break,case,catch,continue,debugger,default,delete,do,else,false,finally,for,function,if,in,instanceof,new,null,return,switch,this,throw,true,try,typeof,var,void,while,with,abstract,boolean,byte,char,class,const,double,enum,export,extends,final,float,goto,implements,import,int,interface,long,native,package,private,protected,public,short,static,super,synchronized,throws,transient,volatile,arguments,let,yield,undefined",t=/\/\*[\w\W]*?\*\/|\/\/[^\n]*\n|\/\/[^\n]*$|"(?:[^"\\]|\\[\w\W])*"|'(?:[^'\\]|\\[\w\W])*'|\s*\.\s*[$\w\.]+/g,u=/[^\w$]+/g,v=new RegExp(["\\b"+s.replace(/,/g,"\\b|\\b")+"\\b"].join("|"),"g"),w=/^\d[^,]*|,\d[^,]*/g,x=/^,+|,+$/g,y=/^$|,+/;e.openTag="{{",e.closeTag="}}";var z=function(a,b){var c=b.split(":"),d=c.shift(),e=c.join(":")||"";return e&&(e=", "+e),"$helpers."+d+"("+a+e+")"};e.parser=function(a){a=a.replace(/^\s/,"");var b=a.split(" "),c=b.shift(),e=b.join(" ");switch(c){case"if":a="if("+e+"){";break;case"else":b="if"===b.shift()?" if("+b.join(" ")+")":"",a="}else"+b+"{";break;case"/if":a="}";break;case"each":var f=b[0]||"$data",g=b[1]||"as",h=b[2]||"$value",i=b[3]||"$index",j=h+","+i;"as"!==g&&(f="[]"),a="$each("+f+",function("+j+"){";break;case"/each":a="});";break;case"echo":a="print("+e+");";break;case"print":case"include":a=c+"("+b.join(",")+");";break;default:if(/^\s*\|\s*[\w\$]/.test(e)){var k=!0;0===a.indexOf("#")&&(a=a.substr(1),k=!1);for(var l=0,m=a.split("|"),n=m.length,o=m[l++];n>l;l++)o=z(o,m[l]);a=(k?"=":"=#")+o}else a=d.helpers[c]?"=#"+c+"("+b.join(",")+");":"="+a}return a},"function"==typeof define?define(function(){return d}):"undefined"!=typeof exports?module.exports=d:this.template=d}();

krpano.editor.js

var krpano = document.getElementById("krpanoSWFObject");
var sceneList = [];
var toAddHotSpot = {};
var currentSceneIndex = 0;
var movingSpot = {};
//视角拖动模块变量
var pbX = 0;
var moveIntervalId;
var canDownMove = false;
var canLeftMove = false;
var canRightMove = false;
//设置为不动态显示,在页面中直接显示就好了 已经设置left: 0 !important;到页面中
var canShowLeft = true;

$(function () {

    //右侧功能选择
    $(".J-tool-btn").click(function () {
        $(".J-tool-btn").each(function () {
            $(this).removeClass("btn-blue");
            $("[name=" + $(this).attr("data-target") + "]").hide();
        });
        $(this).addClass("btn-blue");
        $("[name=" + $(this).attr("data-target") + "]").show();
        window.clearInterval(moveIntervalId);
        $(".add-hot-pot").hide();
        $(".add-voice").hide();
    });

    //视角拖动条
    $(".triangle-down").mouseup(function () {
        canDownMove = false;
    }).mouseout(function () {
        canDownMove = false;
    });
    $(".triangle-up-left").mouseup(function () {
        canLeftMove = false;
    }).mouseout(function () {
        canLeftMove = false;
    });
    $(".triangle-up-right").mouseup(function () {
        canRightMove = false;
    }).mouseout(function () {
        canRightMove = false;
    });

    //添加热点模块
    $(".hot-style").click(function () {
        toAddHotSpot.style = $(this).attr("name");
        $(".hot-style").removeClass("hot-style-on");
        $(this).addClass("hot-style-on");
    });
    $(this).mousemove(function () {
        if (canShowLeft) {
            if (krpano.get("mouse.x") <= 300) {
                $(".left-column").css("-webkit-animation", "showLeft 0.8s infinite").css("-webkit-animation-iteration-count", "1")
                    .css("left", "0");
            } else {
                $(".left-column").css("-webkit-animation", "hideLeft 0.8s infinite").css("-webkit-animation-iteration-count", "1")
                    .css("left", "-250px");
            }
        }
    });

    $(".my-open-out").click(function () {
        if (toAddHotSpot.dive) {
            toAddHotSpot.dive = false;
            $(this).css("background", "rgba(255,255,255,0.4)");
            $(".my-open-in").removeClass("my-open-in-open").addClass("my-open-in-close");
        } else {
            toAddHotSpot.dive = true;
            $(this).css("background", "#00a3d8");
            $(".my-open-in").removeClass("my-open-in-close").addClass("my-open-in-open");
        }
    });
});

//noinspection JSUnusedGlobalSymbols
function onready() {
    //隐藏下方自带控制条
    krpano.set("layer[skin_control_bar].visible", false);
    krpano.set("layer[skin_splitter_bottom].visible", false);
    krpano.set("layer[skin_scroll_window].visible", false);
    //初始化场景选择列表
    var sceneListHTML;
    var dataSceneList = {list: []};      
    
    krpano.get("scene").getArray().forEach(function (scene) {
        dataSceneList.list.push({name: scene.name, index: scene.index, bgmusic: scene.bgmusic});
    });
    sceneListHTML = template('tplSceneList', dataSceneList);
    document.getElementById('sceneList').innerHTML = sceneListHTML;
           
    //初始化选中以及首场景
    $("li[name=" + krpano.get("startscene") + "] .circle").css("background-color", "#FF9800");
    $("li[name=" + krpano.get("xml.scene") + "]").addClass("li-scene-hover");
    currentSceneIndex = krpano.get("scene").getItem(krpano.get("xml.scene")).index;
    
    //热点列表模块
    var hotSpotHTML;
    var dataHotSpotList = {list: []};
    //覆盖原热点选中事件,添加热点点击移动事件
    krpano.get("hotspot").getArray().forEach(function (oldHotSpot) {
    	
        if (oldHotSpot.name !== 'vr_cursor' && oldHotSpot.name !== 'webvr_prev_scene'
            && oldHotSpot.name !== 'webvr_next_scene') {
            dataHotSpotList.list.push(oldHotSpot);
            hotSpotInitEvent(oldHotSpot.name);
        }
    });
    hotSpotHTML = template('tplHotSpotList', dataHotSpotList);
    document.getElementById('hotSpotList').innerHTML = hotSpotHTML;    

  //背景音乐列表模块
    var bgMusicHTML;
    var dataBgMusicList = {list: []};
    var bgMusicUrl=krpano.get("scene").getItem(currentSceneIndex).bgmusic;
    if(typeof(bgMusicUrl) != "undefined")
    {
        var bgmusicArr=bgMusicUrl.split("/");
        var bgMusicName=bgmusicArr[bgmusicArr.length-1].substring(0,bgmusicArr[bgmusicArr.length-1].length-4);
    	dataBgMusicList.list.push({name: bgMusicName});
    }   
    bgMusicHTML = template('tplBgMusicList', dataBgMusicList);
    document.getElementById('bgMusicList').innerHTML = bgMusicHTML;  
    
    //右侧数值初始化
    $("#waitTime").val(krpano.get("autorotate.waittime"));
    if (krpano.get("autorotate.enabled")) {
        $("#autoSpin").prop("checked", true);
        $("#waitTimeInput").show();
    } else {
        $("#autoSpin").prop("checked", false);
        $("#waitTimeInput").hide();
    }
    $("#initFov").val(krpano.get("view.fov").toFixed(0));
    $("#initFovMax").val(krpano.get("view.fovmax").toFixed(0));
    $("#initFovMin").val(krpano.get("view.fovmin").toFixed(0));
    updatePbLine();
    initPbLineEvent();

    //初始化提交数据
    if (!sceneList.length) {
        krpano.get("scene").getArray().forEach(function (scene) {
            var sceneObj = {};
            sceneObj.index = scene.index;
            sceneObj.name = scene.name;
            sceneObj.bgmusic = scene.bgmusic;
            if (scene.name == krpano.get("startscene")) {
                sceneObj.welcomeFlag = true;
            }
            sceneList.push(sceneObj);
        });
    }
}

//场景切换,重命名模块
function changeScene(index) {
    krpano.call("loadscene(" + krpano.get("scene").getItem(index).name + ")");
    //当前存储对象展示
    var currentScene = sceneList[index];        
    
    if (currentScene.initH) krpano.set("view.hlookat", currentScene.initH);
    if (currentScene.initV) krpano.set("view.vlookat", currentScene.initV);
    if (currentScene.fov) krpano.set("view.fov", currentScene.fov);
    if (currentScene.fovmax) krpano.set("view.fovmax", currentScene.fovmax);
    if (currentScene.fovmin) krpano.set("view.fovmin", currentScene.fovmin);
    if (currentScene.autorotate) {
        krpano.set("autorotate.enabled", currentScene.autorotate.enabled);
        krpano.set("autorotate.waittime", currentScene.autorotate.waitTime);
    }
    if (currentScene.hotSpots) {
        krpano.get("hotspot").getArray().forEach(function (everySpot) {
            if (everySpot.name !== "vr_cursor" && everySpot.name !== 'webvr_prev_scene'
                && everySpot.name !== 'webvr_next_scene') {
                krpano.call("removehotspot(" + everySpot.name + ")");
            }
        });
        currentScene.hotSpots.forEach(function (everySpot) {
            krpano.call("addhotspot(" + everySpot.name + ");");
            krpano.set("hotspot[" + everySpot.name + "].ath", everySpot.ath);
            krpano.set("hotspot[" + everySpot.name + "].atv", everySpot.atv);
            krpano.set("hotspot[" + everySpot.name + "].text", everySpot.text);
            krpano.set("hotspot[" + everySpot.name + "].linkedscene", everySpot.linkedscene);
            krpano.set("hotspot[" + everySpot.name + "].dive", everySpot.dive);
            krpano.get("hotspot[" + everySpot.name + "]").loadstyle(everySpot.style);
        });
    }
    $('.li-scene-hover').removeClass('li-scene-hover');
    $("li[name=" + krpano.get("xml.scene") + "]").addClass("li-scene-hover");
    $(".circle").css("background-color", "#292827");
    sceneList.forEach(function (scene) {
        if (scene.welcomeFlag) {
            $(".circle:eq(" + scene.index + ")").css("background-color", "#FF9800");
            krpano.set("startscene", scene.name);
        }
    });
    onready();
}

function rename(prevButton) {
    prevButton.prev().hide();
    prevButton.attr("type", "text");
    var focusValue = prevButton.val();
    prevButton.val("");
    prevButton.focus();
    prevButton.val(focusValue);
}

function doRename(thisInput) {
    var nameIndex = thisInput.parent().attr('key');
    var newName = thisInput.val();
    var oldName = krpano.get("scene").getItem(nameIndex).name;
    var doFlag = true;
    //判断名字是否重复
    sceneList.forEach(function (eachScene) {
        if (eachScene.index !== nameIndex) {
            if (eachScene.name === newName) {
                doFlag = false;
                return false;
            }
        }
    });
    if (doFlag) {
        krpano.get("scene").renameItem(oldName, newName);
        if (currentSceneIndex === nameIndex) {
            krpano.set("xml.scene", newName);
        }
        if (oldName === krpano.get("startscene")) {
            krpano.set("startscene", newName);
        }
        sceneList[nameIndex].name = newName;
        //修改热点指向场景名字
        sceneList.forEach(function (eachScene) {
            if (eachScene.index !== nameIndex && eachScene.hotSpots) {
                eachScene.hotSpots.forEach(function (eachSpot) {
                    if (eachSpot.linkedscene === oldName) {
                        eachSpot.linkedscene = newName;
                        eachSpot.text = newName;
                        krpano.set("hotspot[" + eachSpot.name + "].text", newName);
                        krpano.set("hotspot[" + eachSpot.name + "].linkedscene", newName);
                    }
                });
            }
        });
        $(".hot-spot-text").each(function () {
            if ($(this).text() == oldName) {
                $(this).text(newName);
            }
        });
        $("#isEdited").text('保存*');
        thisInput.prev().text(newName);
    } else {
        thisInput.val(oldName);
        alert("名字重复");
    }
    thisInput.prev().show();
    thisInput.attr("type", "hidden");
}

function selectWelcomeScene(index) {
    $(".circle").css("background-color", "#292827");
    $(".circle:eq(" + index + ")").css("background-color", "#FF9800");
    sceneList.forEach(function (scene) {
        scene.welcomeFlag = false;
    });
    sceneList[index].welcomeFlag = true;
    $("#isEdited").text('保存*');
}

//视角修改模块
function setAsDefaultView() {
    sceneList[currentSceneIndex].initH = krpano.get("view.hlookat");
    sceneList[currentSceneIndex].initV = krpano.get("view.vlookat");
    sceneList[currentSceneIndex].fov = krpano.get("view.fov");
    $("#initFov").val(krpano.get("view.fov").toFixed(0));
    updatePbLine();
    $("#isEdited").text('保存*');
}

function autoSpinClick() {
    var isChecked = $("#autoSpin").is(":checked");
    if (isChecked) {
        $("#waitTimeInput").show();
    } else {
        $("#waitTimeInput").hide();
    }
    krpano.set("autorotate.enabled", isChecked);
    krpano.set("autorotate.waittime", $("#waitTime").val());
    krpano.get("scene").getArray().forEach(function (scene) {
        sceneList[scene.index].autorotate = {enabled: $("#autoSpin").is(":checked"), waitTime: $("#waitTime").val()};
    });
    $("#isEdited").text('保存*');
}

function updateFov() {
    var fov = $("#initFov").val();
    var fovMax = $("#initFovMax").val();
    var fovMin = $("#initFovMin").val();
    if (fov == "" || Number(fov) > 180 || Number(fov) < 0) {
        $("#initFov").val(krpano.get("view.fov").toFixed(0));
        return
    }
    if (fovMax == "" || Number(fovMax) > 180 || Number(fovMax) < 0) {
        $("#initFovMax").val(krpano.get("view.fovmax").toFixed(0));
        return
    }
    if (fovMin == "" || Number(fovMin) > 180 || Number(fovMin) < 0) {
        $("#initFovMin").val(krpano.get("view.fovmin").toFixed(0));
        return
    }
    krpano.set("view.fov", fov);
    krpano.set("view.fovmax", fovMax);
    krpano.set("view.fovmin", fovMin);
    sceneList[currentSceneIndex].fov = fov;
    sceneList[currentSceneIndex].fovmax = fovMax;
    sceneList[currentSceneIndex].fovmin = fovMin;
    updatePbLine();
    $("#isEdited").text('保存*');
}

function fovForAll() {
    sceneList.forEach(function (eachScene) {
        eachScene.fov = $("#initFov").val();
        eachScene.fovmax = $("#initFovMax").val();
        eachScene.fovmin = $("#initFovMin").val();
    });
    $("#isEdited").text('保存*');
    alert("操作成功");
}

function updatePbLine() {
    //视角条
    var startPx = Number(krpano.get("view.fovmin")) / 0.9;
    var widthPx = Number(krpano.get("view.fovmax")) / 0.9 - startPx;
    var currPx = Number(krpano.get("view.fov")) / 0.9 - startPx - 10;
    $(".triangle-down").css("margin-left", currPx.toFixed(0) + "px");
    $(".number-pb-shown").css("left", startPx.toFixed(0) + "px").css("width", widthPx.toFixed(0) + "px").show();
}

function initPbLineEvent() {
    $(".triangle-down").unbind("mousedown").mousedown(function () {
        pbX = krpano.get("mouse.x");
        canDownMove = true;
    }).unbind("mousemove").mousemove(function () {
        if (canDownMove) {
            moveDownLine();
        }
    });
    $(".triangle-up-left").unbind("mousedown").mousedown(function () {
        pbX = krpano.get("mouse.x");
        canLeftMove = true;
    }).unbind("mousemove").mousemove(function () {
        if (canLeftMove) {
            moveLeftLine();
        }
    });
    $(".triangle-up-right").unbind("mousedown").mousedown(function () {
        pbX = krpano.get("mouse.x");
        canRightMove = true;
    }).unbind("mousemove").mousemove(function () {
        if (canRightMove) {
            moveRightLine();
        }
    });
}

function moveDownLine() {
    var startPx = Number(krpano.get("view.fovmin")) / 0.9;
    var widthPx = Number(krpano.get("view.fovmax")) / 0.9 - startPx;
    var leftPx = Number(krpano.get("view.fov")) / 0.9 - startPx - 10 + krpano.get("mouse.x") - pbX;
    if (leftPx + 10 < 0) {
        canDownMove = false;
        leftPx = -10;
    }
    if (leftPx + 10 > widthPx) {
        canDownMove = false;
        leftPx = widthPx - 10;
    }
    pbX = krpano.get("mouse.x");
    krpano.set("view.fov", (leftPx + 10 + startPx) * 0.9);
    $(".triangle-down").css("margin-left", leftPx.toFixed(0) + "px");
    $("#initFov").val(krpano.get("view.fov").toFixed(0));
    sceneList[currentSceneIndex].fov = krpano.get("view.fov");
    $("#isEdited").text('保存*');
}

function moveLeftLine() {
    var startPx = Number(krpano.get("view.fovmin")) / 0.9 + krpano.get("mouse.x") - pbX;
    var endPx = Number(krpano.get("view.fovmax")) / 0.9;
    if (startPx < 0) {
        startPx = 0;
        canLeftMove = false;
    }
    if (endPx - startPx < 20) {
        startPx = endPx - 20;
        canLeftMove = false;
    }
    if (krpano.get("view.fov") < krpano.get("view.fovmin")) {
        krpano.set("view.fov", krpano.get("view.fovmin"))
    }
    pbX = krpano.get("mouse.x");
    krpano.set("view.fovmin", startPx * 0.9);
    updatePbLine();
    $("#initFovMin").val(krpano.get("view.fovmin").toFixed(0));
    sceneList[currentSceneIndex].fovmin = krpano.get("view.fovmin");
    $("#isEdited").text('保存*');
}

function moveRightLine() {
    var startPx = Number(krpano.get("view.fovmin")) / 0.9;
    var endPx = Number(krpano.get("view.fovmax")) / 0.9 + krpano.get("mouse.x") - pbX;
    if (endPx > 200) {
        endPx = 200;
        canRightMove = false;
    }
    if (endPx - startPx < 20) {
        endPx = startPx + 20;
        canRightMove = false;
    }
    if (krpano.get("view.fov") > krpano.get("view.fovmax")) {
        krpano.set("view.fov", krpano.get("view.fovmax"))
    }
    pbX = krpano.get("mouse.x");
    krpano.set("view.fovmax", endPx * 0.9);
    updatePbLine();
    $("#initFovMax").val(krpano.get("view.fovmax").toFixed(0));
    sceneList[currentSceneIndex].fovmax = krpano.get("view.fovmax");
    $("#isEdited").text('保存*');
}

//提交表单修改模块
function updateHotSpotData() {
    var hotSpotHTML;
    var dataHotSpotList = {list: []};
    //修改全局变量
    var hotSpotData = [];
    krpano.get("hotspot").getArray().forEach(function (everySpot) {
        if (everySpot.name !== "vr_cursor" && everySpot.name !== 'webvr_prev_scene'
            && everySpot.name !== 'webvr_next_scene' && everySpot.name.indexOf('vrtooltip') == -1) {
        	//这里加判断过滤掉vrtooltip热点标签
            dataHotSpotList.list.push(everySpot);
            var hotSpot = {};
            hotSpot.ath = everySpot.ath.toString();
            hotSpot.atv = everySpot.atv.toString();
            hotSpot.linkedscene = everySpot.linkedscene;
            hotSpot.name = everySpot.name;
            hotSpot.style = everySpot.style;
            hotSpot.text = everySpot.text;
            hotSpot.dive = everySpot.dive;
            hotSpotData.push(hotSpot);
        }
    });
    sceneList[currentSceneIndex].hotSpots = hotSpotData;
    hotSpotHTML = template('tplHotSpotList', dataHotSpotList);
    document.getElementById('hotSpotList').innerHTML = hotSpotHTML;
}

//数据保存并提交操作
function save() {
    if ($("#isEdited").text() === '保存') {
        return;
    }
    var postData = JSON.stringify(sceneList);
    var panoramicId = $("#panoramicId").val();
    var panoramicMaterialPicIds = $("#panoramicMaterialPicIds").val();
    var tourUrlIds = $("#tourUrlIds").val();
    var curWwwPath = window.document.location.href;
    var pathName = window.document.location.pathname;
    var pos = curWwwPath.indexOf(pathName);
    var localhostPaht = curWwwPath.substring(0, pos);
    var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
    var prefix = localhostPaht + projectName +  "/a";
    alert(postData);
    alert(panoramicId);
    alert(tourUrlIds);
    alert(prefix);
    $.ajax({
        type: 'POST',
        contentType: "application/json; charset=utf-8",
        url: prefix + "/hnly/panoramic/vtourSave?panoramicId=" + panoramicId + "&tourUrlIds=" + tourUrlIds,
        data: postData,
        success: function (data) {
            alert(data);
            if (data === "保存成功") {
                $("#isEdited").text('保存');
            }
        },
        error: function () {
            alert("系统错误");
        }
    });
}

//热点移动模块
function autoMove() {
    krpano.call("screentosphere(mouse.x, mouse.y, mouseath, mouseatv);");
    krpano.set("hotspot[" + movingSpot.name + "].ath", krpano.get("mouseath") + movingSpot.athDis);
    krpano.set("hotspot[" + movingSpot.name + "].atv", krpano.get("mouseatv") + movingSpot.atvDis);
    krpano.set("hotspot[vrtooltip_" + movingSpot.name + "].ath", krpano.get("mouseath") + movingSpot.athDis);
    krpano.set("hotspot[vrtooltip_" + movingSpot.name + "].atv", krpano.get("mouseatv") + movingSpot.atvDis);
}

//添加热点模块
function showAddHotSpot() {
    $(".hot-style").removeClass("hot-style-on");
    $(".hot-style").first().addClass("hot-style-on");
    toAddHotSpot.style = $(".hot-style").first().attr("name");
    toAddHotSpot.dive = true;
    $(".my-open-out").css("background", "#00a3d8");
    $(".my-open-in").removeClass("my-open-in-close").addClass("my-open-in-open");
    $("#hotToolButton").hide();
    $(".add-hot-pot").show();
    $("#selectStyle").show();
    $("#goToScene").hide();
    $("#writeTitle").hide();
    $("#selectStyleTitle").addClass("progress-title-on");
    $("#goToSceneTitle").removeClass("progress-title-on");
    $("#writeTitleTitle").removeClass("progress-title-on");
}

//隐藏添加热点窗口
function hideAddHotSpot() {
    window.clearInterval(moveIntervalId);
    toAddHotSpot = {};
    $(".add-hot-pot").hide();
    $("span[data-target=#toolHot]").click();
}

//隐藏添加语音窗口
function hideAddVoice() {
	$("div").remove(".radio-voice");
    $("#add-voice").hide();
    $("span[data-target=#toolVoice]").click();
}

function nextToSelectTargetScene() {
    if (!toAddHotSpot.style) {
        alert("请选择热点样式");
        return
    }

    window.clearInterval(moveIntervalId);

    // 目标场景列表
    var targetSceneHTML;
    var dataTargetScene = {list: []};
    krpano.get("scene").getArray().forEach(function (scene) {
        if (scene.name !== krpano.get('xml.scene')) {
            dataTargetScene.list.push({name: scene.name, index: scene.index + 1})
        }
    });
    targetSceneHTML = template('tplTargetScene', dataTargetScene);
    document.getElementById('targetScene').innerHTML = targetSceneHTML;

    $(".select-scene-div").removeClass("select-scene-div-on");
    $(".select-scene-div").first().addClass("select-scene-div-on");
    toAddHotSpot.linkedscene = $(".select-scene-div").first().attr("name");
    $(".select-scene-div").unbind("click").click(function () {
        toAddHotSpot.linkedscene = $(this).attr("name");
        $(".select-scene-div").removeClass("select-scene-div-on");
        $(this).addClass("select-scene-div-on");
    });

    $("#selectStyle").hide();
    $("#goToScene").show();
    $("#writeTitle").hide();
    $("#goToSceneTitle").addClass("progress-title-on");
    $("#selectStyleTitle").removeClass("progress-title-on");
    $("#writeTitleTitle").removeClass("progress-title-on");
}

function nextToWriteTitle() {
    if (!toAddHotSpot.linkedscene) {
        alert("请选择目标场景");
        return;
    }

    $("#addHotTitle").val(toAddHotSpot.linkedscene);

    $("#selectStyle").hide();
    $("#goToScene").hide();
    $("#writeTitle").show();
    $("#writeTitleTitle").addClass("progress-title-on");
    $("#selectStyleTitle").removeClass("progress-title-on");
    $("#goToSceneTitle").removeClass("progress-title-on");
}

//添加语音/音乐模块
function showAddVoice(){
	$(".add-voice").show();
	
	var postData = "";
	var curWwwPath = window.document.location.href;
    var pathName = window.document.location.pathname;
    var pos = curWwwPath.indexOf(pathName);
    var localhostPaht = curWwwPath.substring(0, pos);
    var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
    var prefix = localhostPaht + projectName +  "/a";
    $.ajax({
        type: 'POST',
        contentType: "application/json; charset=utf-8",
        url: prefix + "/hnly/panoramicMaterialMusic/getData",
        data: postData,
        success: function (data) {
        	var panoramicMaterialMusicLists = data.panoramicMaterialMusicList;
        	for(var i=0;i<panoramicMaterialMusicLists.length;i++){
        		//alert(JSON.stringify(panoramicMaterialMusicLists[i].id));
        		
        		$("<div style=\"float: left;-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;\" class=\"radio-voice\">" 
        		//$("<div style=\"-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;\" class=\"radio-voice\">" 
        				//+ "<div style=\"position: relative;float: left;width: 25%;line-height: 40px;font-weight: 700;text-align: left;\">"
        				+ "<div style=\"position: relative;line-height: 40px;font-weight: 700;\">"
        				+ "<label for=" + JSON.stringify(panoramicMaterialMusicLists[i].id)
        				+ "> <input type=\"radio\" name=\"panoramicMaterialMusicId\" value=" 
        				+ JSON.stringify(panoramicMaterialMusicLists[i].url) 
        				+ " id=" 
        				+ JSON.stringify(panoramicMaterialMusicLists[i].name) + "/> "
        				+ panoramicMaterialMusicLists[i].name 
        				+ "</label> " 
        				+ "</div>"
        				+ "<div style=\"position: relative;\">"
        				//+ "<div style=\"position: relative;float: left;width: 75%;\">"
        				//+ "<audio controls=\"controls\" height=\"40\" width=\"100\">"
						//+ "<source src=" + panoramicMaterialMusicLists[i].url + " type=\"audio/wav\" />"
						//+ "<source src=\"song.ogg\" type=\"audio/ogg\" />"
						//+ "<embed height=\"40\" width=\"100\" src=" + panoramicMaterialMusicLists[i].url + " />"
						//+ "</audio>" 
						
						+ "</div>"
					+ "</div>"
        				).appendTo("#add-voice-frame");
        	}
        },
        error: function () {
            alert("系统错误");
        }
    });
    $("#isEdited").text('保存*');
}

//添加热点到场景列表中,关闭热点弹出窗口
function addHotSpot() {
    // 计算中间位置的球面坐标
    krpano.set("halfHeight", krpano.get("stageheight") / 2);
    krpano.set("halfWidth", krpano.get("stagewidth") / 2);
    krpano.call("screentosphere(halfWidth,halfHeight,init_h,init_v);");
    var init_h = krpano.get("init_h");
    var init_v = krpano.get("init_v");   
    
    //添加热点
    var newHotSpotName = "spot" + new Date().getTime();
    krpano.call("addhotspot(" + newHotSpotName + ");");
    krpano.get("hotspot[" + newHotSpotName + "]").loadstyle(toAddHotSpot.style);
    krpano.set("hotspot[" + newHotSpotName + "].ath", init_h);
    krpano.set("hotspot[" + newHotSpotName + "].atv", init_v);
    krpano.set("hotspot[" + newHotSpotName + "].text", $("#addHotTitle").val());
    krpano.set("hotspot[" + newHotSpotName + "].linkedscene", toAddHotSpot.linkedscene);
    krpano.set("hotspot[" + newHotSpotName + "].dive", toAddHotSpot.dive);
    krpano.set("hotspot[" + newHotSpotName + "].onloaded", "add_all_the_time_tooltip_for_VR();");
    hotSpotInitEvent(newHotSpotName);
    updateHotSpotData();
    $("#isEdited").text('保存*');
    hideAddHotSpot();
    $("span[data-target=#toolHot]").click();
}

//添加语音到场景列表中,关闭语音弹出窗口
function addVoice(){
	var musicName;
	var obj = document.getElementsByName("panoramicMaterialMusicId");
	for(i=0; i<obj.length;i++){
		if(obj[i].checked){
			musicName=obj[i].value;	
			updateVoice(obj[i].id);
			krpano.get("scene").getItem(currentSceneIndex).bgmusic= obj[i].id;
			sceneList[currentSceneIndex].bgmusic=obj[i].value;
		}
	}
	
	hideAddVoice();
}

function updateVoice(musicName){
	var bgMusicHTML;
	var dataBgMusicList = {list: []};	
	dataBgMusicList.list.push({name: musicName});	
    bgMusicHTML = template('tplBgMusicList', dataBgMusicList);
    document.getElementById('bgMusicList').innerHTML = bgMusicHTML;
}


//热点选择模块
function selectHotSpot() {
    krpano.call("screentosphere(mouse.x, mouse.y, mouseath, mouseatv);");
    var nearHotSpot = {};
    krpano.get("hotspot").getArray().forEach(function (thisHotSpot) {
        var thisAthDis = krpano.get("hotspot[" + thisHotSpot.name + "]").ath - krpano.get("mouseath");
        var thisAtvDis = krpano.get("hotspot[" + thisHotSpot.name + "]").atv - krpano.get("mouseatv");
        var thisDis = Math.abs(thisAthDis) + Math.abs(thisAtvDis);
        if (!nearHotSpot.name) {
            nearHotSpot = {name: thisHotSpot.name, athDis: thisAthDis, atvDis: thisAtvDis, dis: thisDis};
        } else {
            if (thisDis < nearHotSpot.dis) {
                nearHotSpot = {name: thisHotSpot.name, athDis: thisAthDis, atvDis: thisAtvDis, dis: thisDis};
            }
        }
    });
    return nearHotSpot;
}

//热点初始化事件
function hotSpotInitEvent(spotName) {
    krpano.get("hotspot[" + spotName + "]").ondown = function () {
        movingSpot = selectHotSpot();
        var intervalId = setInterval(autoMove, 1000.0 / 30.0);
        krpano.set("autoMoveIntervalId", intervalId);
        canShowLeft = false;
    };
    krpano.get("hotspot[" + spotName + "]").onup = function () {
        window.clearInterval(krpano.get("autoMoveIntervalId"));
        movingSpot = {};
        updateHotSpotData();
        canShowLeft = true;
        $("#isEdited").text('保存*');
    };
    krpano.get("hotspot[" + spotName + "]").onclick = null;
    krpano.get("hotspot[" + spotName + "]").onover = function () {
        if (movingSpot === {}) {
            var currentSpot = selectHotSpot();
            $("[name=" + currentSpot.name + "Hover]").addClass("hot-spot-list-hover");
        }
    };
    krpano.get("hotspot[" + spotName + "]").onout = function () {
        $(".hot-spot-list").removeClass("hot-spot-list-hover");
    };
}

//去除热点
function removeHotSpot(name) {
    krpano.call("removehotspot(" + name + ")");
    updateHotSpotData();
    $("#isEdited").text('保存*');
}

//去除背景音乐
function removeBgMusic(name) {
	var bgMusicHTML;
	var dataBgMusicList = {list: []};	
    bgMusicHTML = template('tplBgMusicList', dataBgMusicList);
    document.getElementById('bgMusicList').innerHTML = bgMusicHTML;
    $("#isEdited").text('保存*');
    
    krpano.get("scene").getItem(currentSceneIndex).bgmusic= null;
	sceneList[currentSceneIndex].bgmusic=null;
}

 

© 著作权归作者所有

共有 人打赏支持
华山猛男
粉丝 5
博文 157
码字总数 76240
作品 0
海口
程序员
加载中

评论(3)

w
wagnkang

引用来自“wagnkang”的评论

确实写的不错,可惜能看懂的人太少了!

引用来自“华山猛男”的评论

:grimacing: 蟹蟹了,没时间更新,写完怕回头忘了就先贴上来,有空再慢慢分解掉。。
只可惜我不会Java:sweat_smile:
华山猛男
华山猛男

引用来自“wagnkang”的评论

确实写的不错,可惜能看懂的人太少了!
:grimacing: 蟹蟹了,没时间更新,写完怕回头忘了就先贴上来,有空再慢慢分解掉。。
w
wagnkang
确实写的不错,可惜能看懂的人太少了!
如何将krpano功能化?快哭了

公司项目有个需求:让用户自己在后台页面上传全景图片,然后在前台自动生成一个krpano全景漫游。 这让我很苦恼,本人在网上看了很多资料,这方面的几乎没有。 要生成一个全景,正常做法是将全...

alwaysVe ⋅ 2016/08/09 ⋅ 1

krpano的工具区别

MAKE OBJECT droplet指的是生成物体全景。请注意,是一件物体的全景,而不是我们平常意义的标准全景或漫游,关键词:环物全景 PANO指的是标准全景 VTOUR自然就是全景漫游了 MULTIRES指的是渐...

爬墙 ⋅ 2016/10/08 ⋅ 0

基于Krpano的Hotspot热区插件·版本一

由于最近工作中需要做一个web版本的动态360全景系统,本系统需要用户上传全景照片实现动态建模生成全景。生成的全景需要实现实时交互以及动态添加热 区等功能。之前想到的是使用unity3d或者a...

馨缘6009 ⋅ 2014/07/28 ⋅ 3

使用 krpano 实现全景视频

使用 krpano 制作全景视频 krpano的强大我就不多说了,了解过的人应该都知道,现在市场上只要应用全景的几乎都是使用的krp来实现,krp官方提供了插件,全景视频使用的是 插件,使用全景摄像机...

黑血沸腾 ⋅ 2017/11/29 ⋅ 0

krpano全景图怎么加评论功能啊?

用krpano怎么在生成好的全景图页面里加上评论功能啊。看懂的人请指教一下。谢谢。

孙亮 ⋅ 2016/06/28 ⋅ 0

全景视频方案

360° video stitching applications suitable for producing VR content include kolor autopano video, and video-stitch stitching video (or still panos) is also only part of the pr......

心翔 ⋅ 2015/10/20 ⋅ 0

Daydream VR入门基础教程,通过GVR示例SimpleVrPanorama制作VR全景图形应用

前言 前两篇介绍了Daydream Android VR开发环境的搭建和官方VR Demo寻宝游戏的演示,这篇我们来一起研究下示例项目SimpleVrPanorama,同时通过了解它来了解如何开发一款VR全景图形应用。 --...

jaikydota163 ⋅ 2016/11/05 ⋅ 0

SegmentFault 技术周刊 Vol.35 - WebGL:打开网页看大片

WebGL 可以说是 HTML5 技术生态链中最为令人振奋的标准之一,它把 Web 带入了 3D 的时代。 初识 WebGL 先通过几个使用 WebGL 的网站来认识下 WebGL 的魅力吧~ 温馨提示:浏览以下网页需要浏览...

keke ⋅ 2017/10/19 ⋅ 0

切图全景 JS 发布 v1.1 版本

切图全景js是切图公司开发的一款快速开发网页场景的js,是完全开源的js框架(可能算不上js框架,因为还没有封装),这次版本更新引入了一个非常不错的类3d效果,用到了css3的动画属性和流行的...

qietuwang ⋅ 2015/06/14 ⋅ 14

基于深度学习的图像风格迁移移植到iOS端 / 文字识别框架Tesseract-OCR 预研这个具体要怎么做

1, 负责VR全景项目视频/图片播放器的全景漫游模块 2, 负责开发美颜/滤镜/大眼/瘦脸/动态贴图等图像处理功能 3, 基于深度学习的图像风格迁移移植到iOS端 / 文字识别框架Tesseract-OCR 预研...

sca7 ⋅ 2017/09/29 ⋅ 2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

R计算IV

参考文章 #读取文件 rawdata = read.csv("/path/to/csv/file",header=T) colnames(rawdata)[18] <- "y" //重命名因变量y #数据分区 训练集测试集 trainIdx <- sample(nrow(rawdata), round(......

火力全開 ⋅ 10分钟前 ⋅ 0

SQL老司机,在SQL中计算 array & map & json数据

摘要: 场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primitive类型的数据。 场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primi...

阿里云云栖社区 ⋅ 10分钟前 ⋅ 0

SQL老司机,在SQL中计算 array & map & json数据

摘要: 场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primitive类型的数据。 场景 通常,我们处理数据,一列数据类型要么是字符串,要么是数字,这些都是primi...

猫耳m ⋅ 21分钟前 ⋅ 0

关于ireport自定义变量类型为list的时候

自己摸石头过河,我真的应该去趟市中心图书馆,借本真正靠谱的教材 网上的东西,只有0.01%是有用的,还有0.99%是垃圾,剩下的99%是垃圾的复制品。。 哎!~ 问题是这样的,报表带sql,从db中获...

炑炑milina ⋅ 22分钟前 ⋅ 0

Spring mvc ContextLoaderListener 原理解析

对于熟悉Spring MVC功能,首先应从web.xml 开始,在web.xml 文件中我们需要配置一个监听器 ContextLoaderListener,如下。 <!-- 加载spring上下文信息,最主要的功能是解析applicationContex...

轨迹_ ⋅ 22分钟前 ⋅ 0

阿里云发布企业数字化及上云外包平台服务:阿里云众包平台

摘要: 阿里云正式发布旗下众包平台业务(网址:https://zhongbao.aliyun.com/),支持包括:网站定制开发,APP、电商系统等软件开发,商标、商品LOGO、VI、产品包装设计、营销推广、大数据人...

阿里云官方博客 ⋅ 24分钟前 ⋅ 0

Redis安装异常解决办法

官网地址:http://redis.io/ 官网下载地址:http://redis.io/download 1. 下载Redis源码(tar.gz),并上传到Linux 2. 解压缩包:tar zxvf redis-2.8.17.tar.gz 3. 进入解压缩后的文件夹:c...

slagga ⋅ 29分钟前 ⋅ 0

006. 深入JVM学习—年轻代

1. 年轻代图片 年轻代(Young)属于JVM堆内存空间的一个组成部分 所有使用关键字new新实例化的对象一定会在伊甸园区进行保存,而对于存活区保存的一定是已经在伊甸园区存在一段时间并且经过了...

影狼 ⋅ 29分钟前 ⋅ 0

如何成为一个合格的程序员

偶尔的,我会被人问道:如何成为一名优秀的程序员,更或者,如何成为一名程序员。每次人们问起,我都力图给出不同的答案。因此,我的答案是各种各样的。下面就是我认为的成为一名优秀的程序员...

柳猫 ⋅ 30分钟前 ⋅ 0

cups error_log日志暴增

日志内容 File \"/usr/lib/cups/notifier/dbus\" has insecure permissions 解决(未验证适用范围) sudo service cups stopsudo rm /etc/cups/subscriptions.conf*sudo rm -r /var/cac......

一介码夫_Hum ⋅ 34分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部