zoukankan      html  css  js  c++  java
  • 搭建本地的百度脑图

    百度有许多优秀的开源软件,百度脑图就是其中的一款。这是一款开源产品,咱们可以将其随意搭建在任何地方。今天我们来在本地计算机上搭建这个项目。

    准备工作

    1. 计算机环境准备,必备软件:node,npm,git,浏览器
    2. 全局npm包准备,必备模块:grunt, bower
    3. 部署环境:静态web服务器(Apache,tomcat,node server,nginx等)

    开始搭建

    我这里是在Windows下,使用git bash进入D盘,创建文件夹baidunaotu:

    # 进入D盘
    $ cd /d
    # 创建baidunaotu文件夹,并进入该文件夹
    $ mkdir baidunaotu && cd baidunaotu
    # 克隆项目
    $ git clone https://github.com/fex-team/kityminder.git
    # 等待项目克隆完成......
    # 进入项目目录
    $ cd kityminder
    # 初始化子模块
    $ git submodule init
    $ git submodule update
    
    # 安装项目的依赖
    $ npm install
    $ bower install
    # 等待项目的依赖安装完成......
    # 执行编译
    $ grunt
    # 等待编译结果......
    # 这时可以发现在该目录中多了一个文件夹dist
    # dist文件夹中就是可以运行的百度脑图
    
    # 进入上一级目录,并创建文件夹naotu
    $ cd ../ && mkdir naotu
    # 将kityminder中的dist文件夹拷贝到naotu文件夹下
    $ cp -r kityminder/dist naotu/
    # 进入naotu目录
    $ cd naotu
    # 初始化可运行的脑图项目
    $ npm init -y
    # 安装express
    $ npm install --save express
    # 创建node服务器文件
    $ touch server.js
    # 编辑server.js文件
    $ vim server.js
    # ......编辑中......
    # server.js文件内容看下面
    # 编辑完成
    # 执行server.js脚本,开启web服务器
    $ node server.js
    # 在浏览器中打开项目:localhost:3000
    

    server.js文件内容

    var express = require('express');
    var app = express();
    
    // 定义本地服务器的端口
    var port = 3000;
    
    // 设置dist目录为静态文件目录
    app.use(express.static('./dist'));
    
    app.listen(port, function(){
        console.log('本地服务器运行在:localhost:' + port);
    });
    

    命令行记录

    浏览器打开项目

    按道理说,该项目编译完成了,本地服务器也启动了,打开浏览器就能够使用了,就像在百度脑图网站上一样,各种功能齐全的。实际上在运行过程中还会有一些问题。

    1. 登录的问题
    2. chrome浏览器移除SVG API——getTransformToElement的问题

    问题1:浏览器打开localhost:3000:

    浏览器打开项目

    由于该项目是需要申请百度的Access Token,本地部署会出现验证问题

    遇到错误

    破解

    dist目录下的index.html文件中的第56行开始的点击事件修改为如下:

    $('p.login a').click(function() {
        window.location.href = './edit.html';
        
        // var urlparts = window.location.href.split('/');
        // urlparts.pop();
        // urlparts = urlparts.join('/');
        // fio.user.login({
        //     redirectUrl: urlparts + '/edit.html',
        //     remember: 7 * 24 * 60 * 60
        // });
        // loadingAnimate(true);
    });
    

    问题2:在chrome浏览器中,此时再次点击【马上开启】

    这时,页面会跳转到edit.html页面,但是控制台会报错

    此错误形成的原因就是因为chrome浏览器移除了一个SVG的非标准API——getTransformToElement

    控制台报错

    解决问题

    dist目录下的edit.html文件中, 在<script src="kityminder.edit.min.js?_=1539324364692" charset="utf-8"></script>的下一行,加上以下几行代码:

    这几行代码是为在SVGElement的原型上添加被chrome移除的API——getTransformToElement,添加后,控制台就不会报错了

    <script type="text/javascript">
        SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(toElement) {
            return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
        };
    </script>
    

    问题3:再次打开页面,发现页面会自动跳转到百度验证

    token验证

    破解

    <script src="kityminder.edit.min.js?_=1539324364692" charset="utf-8"></script>的下一行,接着加上以下几行代码:

    <script type="text/javascript">
        fio.user.login = Function.prototype;
    </script>
    

    刷新页面,就不会出现问题。

    前后一共修改了两个文件:index.htmledit.html

    最终index.html文件内容如下:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="title" content="百度脑图(KityMinder) - 控制创意,如此简单">
        <meta name="keyword" content="kityminder,脑图,思维导图,kity,svg,minder,百度,fex,前端,在线">
        <meta name="description" content="百度脑图,便捷的脑图编辑工具 - 控制创意,如此简单。让您在线上直接创建、保存并分享你的思路。免安装 云存储 易分享 体验舒适 功能丰富">
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
        <title>百度脑图 - 便捷的思维编辑工具</title>
        
        <script src="kityminder.index.min.js?_=1539324364692"></script>
    
        <script>
    
            $(function() {
    
                var pattern = /(?:shareId|share_id)=(w+)([&#]|$)/;
                var match = pattern.exec(window.location) || pattern.exec(document.referrer);
    
                if (match) {
                    window.location.href = 'viewshare.html?shareId=' + match[1];
                    return;
                }
    
                /* 初始化网盘使用的 APP 身份 */
                fio.user.init({
                    apiKey: 'wiE55BGOG8BkGnpPs6UNtPbb'
                });
    
                var $a = $('p.login a').hide();
    
                function loadingAnimate(on) {
                    if (on) {
                        $('hr').addClass('loading');
                        loadingAnimate.timer = setTimeout(function() {
                            $('hr').addClass('animated');
                        }, 660);
                    } else {
                        clearTimeout(loadingAnimate.timer);
                        $('hr').removeClass('loading animated');
                    }
                }
    
                loadingAnimate(true);
    
                fio.user.check().then(function(user) {
                    if (user) {
                        window.location.href = 'edit.html';
                    }
                    else {
                        $a.fadeIn(800);
                        loadingAnimate(false);
                    }
                });
                
                $('p.login a').click(function() {
                    window.location.href = './edit.html';
                    
                    // var urlparts = window.location.href.split('/');
                    // urlparts.pop();
                    // urlparts = urlparts.join('/');
                    // fio.user.login({
                    //     redirectUrl: urlparts + '/edit.html',
                    //     remember: 7 * 24 * 60 * 60
                    // });
                    // loadingAnimate(true);
                });
    
                function preload(url) {
                    return new Promise(function(resolve, reject) {
                        var img = new Image();
                        img.onload = resolve;
                        img.onerror = reject;
                        img.src = url;
                    });
                }
    
                preload('ui/theme/default/images/indexbackground.jpg').then(function() {
                    $('div.background').addClass('loaded');
                });
            });
    
        </script>
    
        <link href="favicon.ico" type="image/x-icon" rel="shortcut icon">
        <link href="favicon.ico" type="image/x-icon" rel="apple-touch-icon-precomposed">
    
        <style>
            body, html {
                margin: 0;
                padding: 0;
                overflow: hidden;
                height: 100%;
                font-size: 0;
                line-height: 0;
                z-index: -2;
            }
    
            body {
                background: #99806B;
                overflow: auto;
            }
    
            ::-webkit-selection {
                background: #FFEFEF;
                color: #4A4F5D;
            }
            ::-moz-selection {
                background: #FFEFEF;
                color: #4A4F5D;
            }
            ::-ms-selection {
                background: #FFEFEF;
                color: #4A4F5D;
            }
            ::selection {
                background: #FFEFEF;
                color: #4A4F5D;
            }
    
            div.background {
                opacity: 0;
                display: block;
                background: url(ui/theme/default/images/indexbackground.jpg) no-repeat;
                background-size: cover;
                position: absolute;
                z-index: -1;
                left: -10px;
                top: -10px;
                right: -10px;
                bottom: -10px;
                -webkit-filter: blur(5px);
                -moz-filter: blur(5px);
                -mz-filter: blur(5px);
                -o-filter: blur(5px);
                filter: url(ui/theme/default/images/blur.svg#blur);
                filter: blur(5px);
                -webkit-transition: opacity 1.5s ease;
                transition: opacity 1.5s ease;
            }
    
            div.background.loaded {
                opacity: 1;
            }
    
            h1:before {
                content: ' ';
                display: block;
                position: absolute;
                top: 0;
                bottom: 0;
                left: 0;
                right: 0;
                background: rgba(0, 0, 0, .5);
                z-index: -1;
            }
    
            h1, p {
                font-weight: 100;
                font-family: Arial, "Microsoft Yahei", "Heiti SC",  sans-serif;
                text-align: center;
                -webkit-font-smoothing: antialiased;
                -moz-osx-font-smoothing: grayscale;
            }
    
            h1 {
                margin: 0;
                margin-top: 100px;
                color: white;
                font-size: 50px;
                line-height: 1.4em;
            }
    
            h1 span {
                font-size: 0.6em;
            }
    
            p span {
                font-size: 12px;
                display: block;
                margin-top: 30px;
                color: rgba(255, 255, 255, .7);
                text-shadow: 0 0 1px rgba(0, 0, 0, .5);
            }
    
            hr {
                height: 0;
                border: none;
                border-bottom: 1px solid #F98183;
                 110px;
                margin: 40px auto;
                -webkit-transition: -webkit-transform 0.66s ease;
                transition: transform 0.66s ease;
                -webkit-backface-visibility: hidden;
            }
    
            hr.loading {
                -webkit-transform: translate3d(100px, 0, 0);
                transform: translate3d(100px, 0, 0);
            }
    
            hr.animated {
                -webkit-animation: slide 1.33s ease-in-out infinite alternate;
                animation: slide 1.33s ease-in-out infinite alternate;
            }
    
            @-webkit-keyframes slide {
                0% { 
                    -webkit-transform: translate3d(100px, 0, 0);
                    transform: translate3d(100px, 0, 0); 
                }
                100% { 
                    -webkit-transform: translate3d(-100px, 0, 0);
                    transform: translate3d(-100px, 0, 0); 
                }
            }
    
            @keyframes slide {
                0% { 
                    -webkit-transform: translate3d(100px, 0, 0);
                    transform: translate3d(100px, 0, 0); 
                }
                100% { 
                    -webkit-transform: translate3d(-100px, 0, 0);
                    transform: translate3d(-100px, 0, 0); 
                }
            }
    
            p.description {
                color: #CCC;
                font-size: 20px;
                line-height: 1.8em;
            }
    
            p.login a {
                display: inline-block;
                 200px;
                height: 60px;
                background: #F98183;
                font-size: 24px;
                line-height: 60px;
                text-align: center;
                border-radius: 30px;
                color: white;
                text-shadow: 0 1px 0 #F8474F;
                cursor: pointer;
                position: relative;
                overflow: hidden;
                margin-top: 50px;
                -webkit-user-select: none;
                -moz-user-select: none;
                -mz-user-select: none;
                user-select: none;
            }
    
            p.login a:active {
                background: #FF6161;
                -webkit-transform: scale(0.95);
                transform: scale(0.95);
            }
    
            p.login a:before {
                content: ' ';
                display: block;
                background: rgba(255, 255, 255, .2);
                position: absolute;
                left: 0;
                top: 0;
                right: 0;
                bottom: 0;
                border-radius: 30px;
                transform: scale(0, 1);
                -webkit-transform: scale(0, 1);
                transition: transform 0.3s ease;
                -webkit-transition: -webkit-transform 0.3s ease;
            }
    
            p.login a:hover:before {
                transform: scale(1, 1);
                -webkit-transform: scale(1, 1);
            }
        
        </style>
    </head>
    <body>
        <div class="background"></div>
        <h1>百度脑图 <br/> <span>控制创意,如此简单</span></h1>
        <hr /> 
        <p class="description">
            免安装 云存储 易分享<br/>
            舒适的体验 丰富的功能<br/>
        </p>
        <p class="login">
            <a>马上开启</a>
            <span>使用百度账号登录</span>
        </p>
    </body>
    
    <!--Baidu Tongji Code-->
    <script type="text/javascript">
    if (document.domain == 'naotu.baidu.com') {
        var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
        document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F0703917f224067c887f3664479a03887' type='text/javascript'%3E%3C/script%3E"));
    }
    </script>
    </html>
    

    最终edit.html文件内容如下:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="title" content="百度脑图(KityMinder)">
        <meta name="keyword" content="kityminder,脑图,思维导图,kity,svg,minder,百度,fex,前端,在线">
        <meta name="description" content="百度脑图,便捷的脑图编辑工具。让您在线上直接创建、保存并分享你的思路。">
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    
        <title>百度脑图 - 便捷的思维编辑工具</title>
    
        <script src="kityminder.edit.min.js?_=1539324364692" charset="utf-8"></script>
        <script type="text/javascript">
            SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(toElement) {
                return toElement.getScreenCTM().inverse().multiply(this.getScreenCTM());
            };
            
            fio.user.login = Function.prototype;
        </script>
        <script src="kityminder.config.js?_=1539324364692" charset="utf-8"></script>
        <script src="lang/zh-cn/zh-cn.js?_=1539324364692" charset="utf-8"></script>
        
        <link href="ui/theme/default/css/default.all.css?_=1539324364692" type="text/css" rel="stylesheet" />
    
        <link href="favicon.ico" type="image/x-icon" rel="shortcut icon">
        <link href="favicon.ico" type="image/x-icon" rel="apple-touch-icon-precomposed">
    </head>
    
    <body>
    <div id="content-wrapper">
        <div id="panel"></div>
    
        <div id="kityminder" onselectstart="return false">
            
        </div>
    </div>
    </body>
    
    <!--脑图启动代码-->
    <script>
    
    /* global km:true, ZeroClipboard:true, zip:true */
    /* jshint browser:true */
    
    $(function() {
        /* 依赖库初始化 */
        zip.inflateJSPath = 'lib/inflate.js';
    });
    
    // create km instance
    km = KM.getMinder('kityminder', window.KITYMINDER_CONFIG);
    
    // init ui for instance
    km.initUI();
    
    // New Version Notify
    $(function() {
    
        var lastVersion = localStorage.lastKMVersion;
        $('#km-version').text( 'v' + KM.version );
    
        if (lastVersion != KM.version) {
            $( '#km-version' ).addClass( 'new-version' );
            localStorage.lastKMVersion = KM.version;
        }
    });
    
    </script>
    
    <!--社会分享代码-->
    <script>window._bd_share_config={"common":{"bdSnsKey":{},"bdMini":"2","bdMiniList":[],"bdPic":"","bdStyle":"1","bdSize":"32"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
    </script>
    
    <!--Baidu Tongji Code-->
    <script type="text/javascript">
    if (document.domain == 'naotu.baidu.com') {
        var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
        document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F0703917f224067c887f3664479a03887' type='text/javascript'%3E%3C/script%3E"));
    }
    </script>
    </html>
    

    文件夹结构

    文件夹结构

    说明

    1. 百度脑图是一款优秀的软件,感谢百度开源了这么一款优秀软件。
    2. 上面描述的一些过程,某些是为了避开百度的验证。这是因为在本地搭建一个环境,我觉得没有必要注册开发者账号,注册客户端ID之类的信息。如果是部署到线上的产品,我认为还是有必要按着百度的要求进行注册的。
    3. Firefox并没有移除SVG的非标准API,如果不想解决兼容问题,直接使用Firefox浏览器打开就好了
    4. node.getTransformToElement(SVGElement),该方法返回一个SVGMatrix对象,代表当前元素坐标到指定元素坐标之间的转换。

    关于我

    微信公众号:撩码

    微信公众号——撩码
  • 相关阅读:
    多点触摸的一些代码
    精灵跳跃练习
    svn安装所遇到的几个问题[转载]
    简易包边字画法
    http和socket简介
    ant使用笔记
    j2se图片拖拽练习
    A星寻路示例
    迅为瑞芯微iTOP3399开发板资料更新
    迅为i.MX6Q开发板NXP恩智浦ARM安卓linux开发板
  • 原文地址:https://www.cnblogs.com/pellime/p/9795075.html
Copyright © 2011-2022 走看看