krpano功能化实现

    本人因为公司需求,需要做个VR全景功能,所以研究VR功能。在网上查询了一些资料以后发现krpano软件可以满足这个需求,果断学习之,如果大家有兴趣的话可以看下这些内容:


    krpano360,http://www.krpano360.com 这个网站,我是从入门教程看到初级教程,在此先感谢下网站所有人“肥宗”哥,感谢他的无私分享,如果你看完了我说的内容的话,基本也了解了krpano基本功能。

    分享下krpano的下载地址:https://pan.baidu.com/s/1oAaHjB0  密码:j6w8

    关于注册码,可以加我微信或者留言给我,我私信给你。


    好了,言归正传。下面我们开始讲解如何krpano功能化,首先我也是参考了cdsn的大神分享的文章,在此先谢谢“J_小浩子”的文章,地址:http://blog.csdn.net/change_on/article/details/77373644,有兴趣可以先看下。

    

    说说如何功能话krpano的思路:   先来看下krpano的文件夹结构,根目录是vtour

    这是最后生成好的文件,来说明下吧,panos-放置全景图或者缩略图文件夹,plugins-公用的插件文件夹,skin-皮肤以及一些配置文件夹,tour.html-主访问页面,tour.js-js文件用户html引用,tour.swf-用于flash引用,tour.xml-主配置文件。关于具体思路请参考小浩子大神的文章,本人不在这里重复阐述,说下最后我的结果文件夹内容:




这是最后的输出文件夹内容,其中plugin,skin和tour.html是公用的,target文件夹是每次上传都不同的。

    

    主要是在大神们的思路和代码上进行了一些代码优化,分离了方法代码和执行代码,增加了背景音乐,底部logo和载入进度条等功能。


下面我们来看下具体的实现代码:

首先是:krpano类封装

/**
 * 
 */
package krpano;

/**
 * krpano类封装
 * @author Administrator
 *
 */
public class KrpanoEntity {
    /**
     * 总标题
     */
    private String title;
    /**
     * 场景标题
     */
    private String[] sceneTitle;
    /**
     * krpano exe执行文件地址
     */
    private String krpanoPath;
    /**
     * 源文件地址
     */
    private String sourcePath;
    /**
     * 目标文件夹
     */
    private String targetPath;
    /**
     * 载入动画地址
     */
    private String loadingPath;
    /**
     * 音乐文件地址
     */
    private String musicPath;
    /**
     * 底部logo文件地址
     */
    private String logoPath;

    public String getKrpanoPath() {
        return krpanoPath;
    }

    public String getSourcePath() {
        return sourcePath;
    }

    public String getTargetPath() {
        return targetPath;
    }

    public String getLoadingPath() {
        return loadingPath;
    }

    public String getMusicPath() {
        return musicPath;
    }

    public String getLogoPath() {
        return logoPath;
    }

    public void setKrpanoPath(String krpanoPath) {
        this.krpanoPath = krpanoPath;
    }

    public void setSourcePath(String sourcePath) {
        this.sourcePath = sourcePath;
    }

    public void setTargetPath(String targetPath) {
        this.targetPath = targetPath;
    }

    public void setLoadingPath(String loadingPath) {
        this.loadingPath = loadingPath;
    }

    public void setMusicPath(String musicPath) {
        this.musicPath = musicPath;
    }

    public void setLogoPath(String logoPath) {
        this.logoPath = logoPath;
    }

    public String getTitle() {
        return title;
    }

    public String[] getSceneTitle() {
        return sceneTitle;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setSceneTitle(String[] sceneTitle) {
        this.sceneTitle = sceneTitle;
    }
    
}

krpano功能化的方法类:

package krpano;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * krpano功能化的方法
 * @author Administrator
 *
 */
public class UnitedMethod {
    
    
    public boolean copyFile(String oldPath, String newPath) throws IOException {
        File oldFile = new File(oldPath);
        if (!oldFile.exists())
            return false;

        File newFile = new File(newPath);
        // 判断是否有这个文件有不管没有创建
        if (!newFile.exists()) {
            newFile.mkdirs();
        }
        fileCopy(oldFile.getPath(),
                newPath + File.separator + oldFile.getName());// 继续调用复制方法
        // 递归的地方,自己调用自己的方法,就可以复制文件夹的文件夹了
        return true;

    }
    
    
    /**
     * 复制文件或者文件夹下的所有内容
     * @param oldPath
     * @param newPath
     * @throws IOException
     */
    public boolean copyFolder(String oldPath, String newPath) throws IOException {

        File oldFile = new File(oldPath);
        if (!oldFile.exists())
            return false;

        File newFile = new File(newPath);
        // 判断是否有这个文件有不管没有创建
        if (!newFile.exists()) {
            newFile.mkdirs();
        }
        
        // 遍历文件及文件夹
        for (File file : oldFile.listFiles()) {
            if (file.isFile()) {
                // 文件
                fileCopy(file.getPath(), newPath + File.separator + file.getName()); // 调用文件拷贝的方法
            } else if (file.isDirectory()) {
                // 文件夹
                copyFolder(file.getPath(), newPath + File.separator + file.getName());// 继续调用复制方法
                                                                          // 递归的地方,自己调用自己的方法,就可以复制文件夹的文件夹了
            }
        }

        return true;
    }
    
    
    private  void fileCopy(String src,String des) throws IOException{
      //io流固定格式
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(des));
        int i = -1;//记录获取长度
        byte[] bt = new byte[2014];//缓冲区
        while ((i = bis.read(bt))!=-1) {
            bos.write(bt, 0, i);
        }
        bis.close();
        bos.close();
        //关闭流
    }
    
    /**
     * 删除文件或者文件夹下的所有内容
     * @param src
     */
    public void delFile(String src){
        File file = new File(src);
        if(!file.exists()) return;
        delDir(file);
    }
    
    /**
     * 递归删除文件
     * @param f
     */
    private static void delDir(File f) {
        // 判断是否是一个目录, 不是的话跳过, 直接删除; 如果是一个目录, 先将其内容清空.
        if(f.isDirectory()) {
            // 获取子文件/目录
            File[] subFiles = f.listFiles();
            // 遍历该目录
            for (File subFile : subFiles) {
                // 递归调用删除该文件: 如果这是一个空目录或文件, 一次递归就可删除. 如果这是一个非空目录, 多次
                // 递归清空其内容后再删除
                delDir(subFile);
            }
        }
        // 删除空目录或文件
        f.delete();
    }
    
    
    public Document readeXMLDemo(String sourcePath) throws DocumentException{
        
        File file = new File(sourcePath);
        if(!file.exists()) return null;
        
        // 创建saxReader对象  
        SAXReader reader = new SAXReader();  
        // 通过read方法读取一个文件 转换成Document对象  
        Document document = reader.read(file);  
        
        return document;
        //遍历所有的元素节点  
        // listNodes(node); 
    }
    
    /**
     * 修改vr标题
     * @param fileFolder
     * @param title
     * @throws Exception
     */
    public void updateVtourTitle(String fileFolder,String title) throws Exception{
        
        if(null == title || StringUtils.isEmpty(title)) return;
        
        String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;
        Document tour_doc = this.readeXMLDemo(tour_filePath);
        if(null == tour_doc) return;
        
        Element tour_root = tour_doc.getRootElement(); 
        Attribute title_attr =  tour_root.attribute("title");
        title_attr.setValue(title);
        this.writer(tour_doc, tour_filePath);
    }
    
    /**
     * 修改每个场景的标题值
     * @param fileFolder
     * @param sceneTitles
     * @throws Exception
     */
    public void updateVtourSceneTitle(String fileFolder,String[] sceneTitles) throws Exception{
        
        if(null == sceneTitles || sceneTitles.length == 0) return;
        String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;
        Document tour_doc = this.readeXMLDemo(tour_filePath);
        if(null == tour_doc) return;
        
        Element tour_root = tour_doc.getRootElement(); 
        
        List<Element> sceneTitle_list =  tour_root.elements("scene");
        for(int i =0,size = sceneTitle_list.size();i < size;i++){
            sceneTitle_list.get(i).attribute("title").setValue(sceneTitles[i]);
        }
        this.writer(tour_doc, tour_filePath);
        
    }
    
    
    /**
     * 修改vtour.xml中的vtourskin路径地址
     * @param fileFolder
     * @throws Exception 
     */
    public void updateVtourSkinAddr(String fileFolder) throws Exception{
        String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;
        Document tour_doc = this.readeXMLDemo(tour_filePath);
        if(null == tour_doc) return;
        
        Element tour_root = tour_doc.getRootElement(); 
        Element vtourskin_element =  tour_root.element("include");
        Attribute attr =  vtourskin_element.attribute("url");
        attr.setValue("../" + attr.getValue());
        this.writer(tour_doc, tour_filePath);
    }
    
    /**
     * 增加vr背景音乐和控制按钮
     * @param fileFolder
     * @param musicPath
     * @throws Exception
     */
    public void addMusicElement(String fileFolder,String musicPath) throws Exception {
        
        //tour.xml文件解析的根节点
        String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;
        Document tour_doc = this.readeXMLDemo(tour_filePath);
        if(null == tour_doc) return;
        
        
        File music_file = new File(musicPath);
        if(!music_file.exists()) return ;
        
        Element tour_root = tour_doc.getRootElement(); 
        Element plugin_element =  tour_root.addElement("plugin");
        plugin_element.addAttribute("name", "soundinterface");
        plugin_element.addAttribute("url.flash", "%HTMLPATH%/plugins/soundinterface.swf");
        plugin_element.addAttribute("url.html5", "%HTMLPATH%/plugins/soundinterface.js");
        plugin_element.addAttribute("rootpath", "");
        plugin_element.addAttribute("preload", "true");
        plugin_element.addAttribute("keep", "true");
        
        //拷贝声音文件到目录下
        
        this.copyFile(musicPath, fileFolder);
        Element action_element =  tour_root.addElement("action");
        action_element.addAttribute("name", "bgsnd_action");
        action_element.addAttribute("autorun", "onstart");
        action_element.addText("playsound(bgsnd, '%SWFPATH%/"+ music_file.getName()+"', 0);");
        
        this.writer(tour_doc, tour_filePath);
        
        
        //skin/vtourskin.xml文件解析的根节点,增加声音控制按钮
//        String vtourskin_filePath =fileFolder + File.separator + VTOURSKIN_NAME;
//        Document vtourskin_doc = this.readeXMLDemo(vtourskin_filePath);
//        if(null == vtourskin_doc) return;
//        Element vtourskin_root = vtourskin_doc.getRootElement(); 
//        //查找bar_button节点
//        List<Element> list_1 = vtourskin_root.elements();
//        Element skin_layer_element = null;
//        for(Element ee : list_1){
//            if(null != ee.attributeValue("name") && "skin_layer".equals(ee.attributeValue("name").toString())){
//                skin_layer_element = ee;
//                break;
//            }
//        }
//        List<Element> list_2 = skin_layer_element.elements();
//        Element control_bar_element = null;
//        for(Element ee : list_2){
//            if(null != ee.attributeValue("name") && "skin_control_bar".equals(ee.attributeValue("name").toString())){
//                control_bar_element = ee;
//                break;
//            }
//        }
//        
//        Element bar_button_element  =  control_bar_element.addElement("layer");
//        bar_button_element.addAttribute("name", "skin_btn_sound");
//        bar_button_element.addAttribute("style", "skin_base|skin_glow");
//        bar_button_element.addAttribute("crop", "64|704|64|64");
//        bar_button_element.addAttribute("align", "right");
//        bar_button_element.addAttribute("x", "130");
//        bar_button_element.addAttribute("y", "0");
//        bar_button_element.addAttribute("scale", "0.5");
//        bar_button_element.addAttribute("onclick", "pausesoundtoggle(bgsnd);switch(crop,64|704|40|64,64|704|64|64);switch(alpha,1,0.25);switch(ox,0,-12)");
//        this.writer(vtourskin_doc, vtourskin_filePath);
    }
    
    /**
     * 新增底部logo图片
     * @param fileFolder
     * @param logoFloder 存放logo和配置文件的文件夹目录
     * @throws Exception 
     */
    public void addNadirLogo(String fileFolder,String logoFloder) throws Exception{
        File file = new File(fileFolder);
        if(!file.exists()) return ;
        
        File logoFile = new File(fileFolder + File.separator + KrpanoContants.LOGO_NAME);
        if(!logoFile.exists()) logoFile.mkdir();
        //拷贝logo文件到vr目录下
        this.copyFolder(logoFloder, logoFile.getPath());
        
        
        //tour.xml文件解析的根节点
        String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;
        Document tour_doc = this.readeXMLDemo(tour_filePath);
        if(null == tour_doc) return;
        
        
        Element tour_root = tour_doc.getRootElement(); 
        Element plugin_element =  tour_root.addElement("include");
        plugin_element.addAttribute("url", "logo/nadir-logo.xml");
        
        this.writer(tour_doc, tour_filePath);
    }
    
   /**
    * 增加进度条动画
    * @param fileFolder
    * @param loadingFloder
    * @throws Exception
    */
    public void addLoadingAnimation(String fileFolder,String loadingFloder) throws Exception{
        File file = new File(fileFolder);
        if(!file.exists()) return ;
        
        File logoFile = new File(fileFolder + File.separator + KrpanoContants.LOADING_NAME);
        if(!logoFile.exists()) logoFile.mkdir();
        //拷贝logo文件到vr目录下
        this.copyFolder(loadingFloder, logoFile.getPath());
        
        
        //tour.xml文件解析的根节点
        String tour_filePath = fileFolder + File.separator + KrpanoContants.TOUR_NAME;
        Document tour_doc = this.readeXMLDemo(tour_filePath);
        if(null == tour_doc) return;
        
        
        Element tour_root = tour_doc.getRootElement(); 
        
        Element animation_element =  tour_root.addElement("include");
        animation_element.addAttribute("url", "loading/loadinganimation.xml");
        
        Element text_element =  tour_root.addElement("include");
        text_element.addAttribute("url", "loading/loadingpercenttext.xml");
        
        Element bar_element =  tour_root.addElement("include");
        bar_element.addAttribute("url", "loading/loadingbar.xml");
        
        this.writer(tour_doc, tour_filePath);
    }
    
    /** 
     * 把document对象写入新的文件 
     *  
     * @param document 
     * @throws Exception 
     */  
    public void writer(Document document,String filePath) throws Exception {  
        // 紧凑的格式  
        // OutputFormat format = OutputFormat.createCompactFormat();  
        // 排版缩进的格式  
        OutputFormat format = OutputFormat.createPrettyPrint();  
        // 设置编码  
        format.setEncoding("UTF-8");  
        // 创建XMLWriter对象,指定了写出文件及编码格式  
        // XMLWriter writer = new XMLWriter(new FileWriter(new  
        // File("src//a.xml")),format);  
        XMLWriter writer = new XMLWriter(new OutputStreamWriter(  
                new FileOutputStream(new File(filePath)), "UTF-8"), format);  
        // 写入  
        writer.write(document);  
        // 立即写入  
        writer.flush();  
        // 关闭操作  
        writer.close();  
    }  
    
    
    public static void main(String[] args) throws Exception{
        UnitedMethod um = new UnitedMethod();
        
        String filePath = "E:\\works\\krpano\\test\\target";
        
        //um.addMusicElement(filePath, "E:\\one.mp3");
        
        //um.addNadirLogo(filePath, "E:\\works\\krpano\\krpano_test\\vtour\\logo");
        
        //um.addLoadingAnimation(filePath, "E:\\works\\krpano\\krpano_test\\vtour\\loading");
        
        //um.updateVtourSkinAddr(filePath);
        
        um.updateVtourSceneTitle(filePath, new String[]{"千年香榧-1","千年香榧-2"});
    }

}

krpano调用类:

/**
 * 
 */
package krpano;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

/**
 * krpano执行文件
 * @author Administrator
 *
 */
public class ExecuteMethod {
   
    
    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {

        
        ExecuteMethod em = new ExecuteMethod();
        KrpanoEntity krEntity = new KrpanoEntity();
        krEntity.setSourcePath("E:\\works\\krpano\\test");
        krEntity.setTargetPath("E:\\works\\krpano\\test\\target");
        krEntity.setKrpanoPath("E:\\works\\krpano\\krpano-1.19-pr14-win");
        krEntity.setMusicPath("E:\\works\\krpano\\public\\one.mp3");
        krEntity.setLoadingPath("E:\\works\\krpano\\public\\loading");
        krEntity.setLogoPath("E:\\works\\krpano\\public\\logo");
        krEntity.setTitle("一亩云-千年香榧");
        krEntity.setSceneTitle(new String[]{"千年香榧-1","千年香榧-2"});
        
        em.executeKrpanoExe(krEntity);
        
    }
    
    
    /**
     * 执行krpano应用程序进行输出,输出地址为:sourcePath\\vtour
     * @param krpanoPath
     * @param sourcePath
     * @throws InterruptedException 
     */
    private void executeKrpanoExe(KrpanoEntity krEntity) throws Exception{
       File sourceFile = new File(krEntity.getSourcePath());
       if(!sourceFile.exists()) return ;
       String ex = "krpanotools32.exe makepano -config=\\templates\\vtour-vr.config "
               + krEntity.getSourcePath() + File.separator + "*.jpg";
       Runtime runtime = Runtime.getRuntime();
       Process p = null;
       try {
           p = runtime.exec("cmd /c start " + krEntity.getKrpanoPath() + File.separator + ex);
           p.waitFor();
       } catch (Exception e) {
           e.printStackTrace();
       }finally{
           InputStream is1 =  p.getInputStream();
            new Thread() {
                public void run() {
                    BufferedReader br1 = new BufferedReader(new InputStreamReader(is1));
                    try {
                        String line1 = null;
                        while ((line1 = br1.readLine()) != null) {
                            if (line1 != null) {
                                System.out.println("=AA==========line1======"
                                        + line1);
                            }
                        }
                        is1.close();
                        ExecuteMethod em = new ExecuteMethod();
                        UnitedMethod um = new UnitedMethod();
                        em.copyVtourFiles(krEntity.getSourcePath(),krEntity.getTargetPath());
                        //递归删除临时文件夹
                        um.delFile(krEntity.getSourcePath() + File.separator + KrpanoContants.VTOUR_NAME);
                        try {
                            um.updateVtourTitle(krEntity.getTargetPath(), krEntity.getTitle());
                            um.updateVtourSceneTitle(krEntity.getTargetPath(), krEntity.getSceneTitle());
                            um.updateVtourSkinAddr(krEntity.getTargetPath());
                            um.addLoadingAnimation(krEntity.getTargetPath(), krEntity.getLoadingPath());
                            um.addMusicElement(krEntity.getTargetPath(), krEntity.getMusicPath());
                            um.addNadirLogo(krEntity.getTargetPath(), krEntity.getLogoPath());
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
           p.destroy();
       }
    }
    
    /**
     * 需要拷贝3个文件,如:tour.js,tour.swf,tour.xml,还有panos文件夹下的所有文件内容
     * @param sourcePath
     * @param targetPath
     */
    private void copyVtourFiles(String sourcePath,String targetPath){
        UnitedMethod um = new UnitedMethod();
        File targetFile = new File(targetPath);
        if(!targetFile.exists()) targetFile.mkdir();
        File sourceFile = new File(sourcePath);
        if(!sourceFile.exists()) return ;
        
        try {
            um.copyFile(sourcePath + File.separator + KrpanoContants.TOUR_XML_NAME, targetPath);
            um.copyFile(sourcePath + File.separator + KrpanoContants.TOUR_JS_NAME, targetPath);
            um.copyFile(sourcePath + File.separator + KrpanoContants.TOUR_SWF_NAME, targetPath);
            um.copyFolder(sourcePath + File.separator + KrpanoContants.PANOS_FOLDER_NANME, targetPath + File.separator + "panos");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

krpano常量类:

/**
 * 
 */
package krpano;

import java.io.File;

/**
 * 存放krpano功能化的自定义常量
 * @author Administrator
 *
 */
public class KrpanoContants {
    
    
    public static final String VTOUR_NAME ="vtour";
    
    public static final String TOUR_XML_NAME =  VTOUR_NAME + File.separator + "tour.xml";
    
    
    public static final String TOUR_JS_NAME = VTOUR_NAME + File.separator + "tour.js";
    
    
    public static final String TOUR_SWF_NAME = VTOUR_NAME + File.separator + "tour.swf";
    
    
    public static final String PANOS_FOLDER_NANME =  VTOUR_NAME + File.separator + "panos";
    
    
    public static final String TOUR_NAME = "tour.xml";
    
    public static final String VTOURSKIN_NAME = "skin\\vtourskin.xml";
    
    public static final String LOGO_NAME = "logo";
    
    public static final String LOADING_NAME = "loading";
}

下面是具体的源码下载地址:

    http://download.csdn.net/download/masti/10263263


  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值