1. 程式人生 > >搭建本地的百度腦圖

搭建本地的百度腦圖

login bubuko urn require script pro 服務器文件 進入 現在

百度有許多優秀的開源軟件,百度腦圖就是其中的一款。這是一款開源產品,咱們可以將其隨意搭建在任何地方。今天我們來在本地計算機上搭建這個項目。

  • 百度腦圖官網
  • 百度腦圖開源地址——github倉庫

準備工作

  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對象,代表當前元素坐標到指定元素坐標之間的轉換。

關於我

  • 【個人網站】http://www.pelli.ren
  • 【博客園主頁】https://www.cnblogs.com/pellime/

微信公眾號:撩碼

技術分享圖片

搭建本地的百度腦圖