搭建本地的百度腦圖
百度有許多優秀的開源軟件,百度腦圖就是其中的一款。這是一款開源產品,咱們可以將其隨意搭建在任何地方。今天我們來在本地計算機上搭建這個項目。
- 百度腦圖官網
- 百度腦圖開源地址——github倉庫
準備工作
- 計算機環境準備,必備軟件:
node
,npm
,git
,瀏覽器
- 全局
npm
包準備,必備模塊:grunt
,bower
- 部署環境:靜態
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);
});
瀏覽器打開項目
按道理說,該項目編譯完成了,本地服務器也啟動了,打開瀏覽器就能夠使用了,就像在百度腦圖網站上一樣,各種功能齊全的。實際上在運行過程中還會有一些問題。
- 登錄的問題
- 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.html
和edit.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>
文件夾結構
說明
- 百度腦圖是一款優秀的軟件,感謝百度開源了這麽一款優秀軟件。
- 上面描述的一些過程,某些是為了避開百度的驗證。這是因為在本地搭建一個環境,我覺得沒有必要註冊開發者賬號,註冊客戶端ID之類的信息。如果是部署到線上的產品,我認為還是有必要按著百度的要求進行註冊的。
Firefox
並沒有移除SVG的非標準API,如果不想解決兼容問題,直接使用Firefox
瀏覽器打開就好了node.getTransformToElement(SVGElement)
,該方法返回一個SVGMatrix
對象,代表當前元素坐標到指定元素坐標之間的轉換。
關於我
- 【個人網站】http://www.pelli.ren
- 【博客園主頁】https://www.cnblogs.com/pellime/
微信公眾號:撩碼
搭建本地的百度腦圖