搭建本地的百度脑图

Posted pellime

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搭建本地的百度脑图相关的知识,希望对你有一定的参考价值。

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

准备工作

  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:再次打开页面,发现页面会自动跳转到百度验证

技术分享图片

破解

<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;
            width: 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;
            width: 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对象,代表当前元素坐标到指定元素坐标之间的转换。

关于我

微信公众号:撩码

技术分享图片

以上是关于搭建本地的百度脑图的主要内容,如果未能解决你的问题,请参考以下文章

百度脑图怎么导出图片

百度脑图

DesktopNaotu 百度桌面脑图使用事项

百度脑图可以做词云图

明白脑图的作用

Java基础知识脑图