本文為轉載,原文:Laravel項目中使用markdown編輯器及圖片粘貼上傳七牛云
Markdown
Markdown是一種可以使用普通文本編輯器編寫的標記語言,通過簡單的標記語法,它可以使普通文本內容具有一定的格式。
本次我們選用的編輯器是: Editor.md,官網中也有很詳細的介紹。從官網中下載安裝
下載的內容中,也有很多demo可以借鑒。
在下載的包中,去除一些多余的內容,只保留我們需要的內容,然后加到項目的public目錄下,如下圖紅色框內的內容:
項目中使用
在項目中使用editor.md編輯內容時,首先要先在blade模板中添加相對應的引用,css的引用如下:
<link rel="stylesheet" href="{{asset('editormd/editormd.min.css')}}">
js的引用如下:
<script src="{{asset('editormd/editormd.min.js')}}" type="text/javascript"></script>
然后在html中添加以下代碼,作為編輯器區域。
<div id="myeditormd">
<textarea style="display:none;"></textarea>
</div>
最后在添加js代碼,加載出editor.md:
<script type="text/javascript">
var testEditor;
$(function () {
testEditor = editormd("myeditormd",{
width:"100%",
height:600,
syncScrolling:"single",
taskList : true,
tocm: true,
path:"{{asset('/editormd/lib/')}}" + "/",
tex:true,
flowChart : true,
sequenceDiagram:true,
saveHTMLToTextarea : true,
imageUploadURL: "php/upload.php",
});
});
</script>
相關參數含義:
saveHTMLToTextarea: 保存 HTML 到 Textarea
tex: 科學公式TeX語言支持,默認關閉
flowChart: 流程圖支持,默認關閉
sequenceDiagram: 時序/序列圖支持,默認關閉
toolbar: 工具欄,默認開啟
watch: 實時預覽,默認開啟
如此,便可完整的加載出編輯器了。效果如下圖:
其中還有些比較重要的js方法。
testEditor.gotoLine(90);//跳轉至第90行
testEditor.show();//顯示編輯器
testEditor.hide;//隱藏編輯器
testEditor.getMarkdown();//獲取markdown代碼
testEditor.getHTML();//獲取markdown解析后的html代碼
testEditor.watch();//開啟實時預覽
testEditor.unwatch();//關閉實時預覽
testEditor.previewing();//預覽
testEditor.fullscreen();//全屏
testEditor.showToolbar();//顯示工具欄
testEditor.hideToolbar();//隱藏工具欄
在編輯器中編輯完內容后,一般情況下,保存的是markdown標記。但是如何解析已保存的markdown標記呢。
markdown解析
添加以下引用:
//css引用
<link rel="stylesheet" href="{{asset('editormd/editormd.min.css')}}">
//js引用
<script src="{{asset('editormd/editormd.min.js')}}" type="text/javascript"></script>
<script src="{{asset('editormd/lib/marked.min.js')}}"></script>
<script src="{{asset('editormd/lib/prettify.min.js')}}"></script>
<script src="{{asset('editormd/lib/raphael.min.js')}}"></script>
<script src="{{asset('editormd/lib/underscore.min.js')}}"></script>
<script src="{{asset('editormd/lib/sequence-diagram.min.js')}}"></script>
<script src="{{asset('editormd/lib/flowchart.min.js')}}"></script>
<script src="{{asset('editormd/lib/jquery.flowchart.min.js')}}"></script>
然后在html中添加解析的區域
<div id="show_editor">
<textarea style="display: none">{{$article->content}}</textarea>
</div>
其中{{$article->content}}為數據庫中讀取的已保存的markdown標記。
最后再添加響應的js代碼,便可完美解析了。
<script type="text/javascript">
$(function() {
var testEditormdView;
testEditormdView = editormd.markdownToHTML("show_editor", {
htmlDecode : "style,script,iframe", // you can filter tags decode
emoji : true,
taskList : true,
tex : true, // 默認不解析
flowChart : true, // 默認不解析
sequenceDiagram : true, // 默認不解析
});
});
</script>
解析后的效果如下圖:
圖片粘貼上傳
首先分析一下實現步驟:
- QQ截圖后在編輯器中粘貼,肯定會有一個粘貼事件,即 paste 事件
- 在事件回調函數中對前端進行圖片的一次壓縮
- 前端壓縮多是使用canvas,返回的是base64,這里我使用了一個 localResizeIMG.js的插件
- 將生成好的base64傳給后臺,后臺可以進行圖片的第二次壓縮,但是感覺沒必要
- 后臺先得到七牛云的upToken,即一個上傳的憑證,然后執行七牛sdk提供的上傳函數
paste事件
截圖之后,在富文本編輯器中右鍵黏貼或者CTRL V就會觸發這個事件,這個事件有一個clipboardData屬性。我們需要使用js代碼監聽paste事件,并獲取clipboardData屬性,代碼如下:
function paste(event) {
var clipboardData = event.clipboardData;
var items, item, types;
if (clipboardData) {
items = clipboardData.items;
if (!items) {
return;
}
// 保存在剪貼板中的數據類型
types = clipboardData.types || [];
for (var i = 0; i < types.length; i++) {
if (types[i] === 'Files') {
item = items[i];
break;
}
}
// 判斷是否為圖片數據
if (item && item.kind === 'file' && item.type.match(/^image\//i)) {
// 讀取該圖片
var file = item.getAsFile(),
reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
//前端壓縮
lrz(reader.result, {width: 1080}).then(function (res) {
$.ajax({
url: "{{asset('php-sdk/myapis/uploadImageToQiliu.php')}}",
type: 'post',
data: {
"image": res.base64,
"name": new Date().getTime() + ".png"
},
contentType: 'application/x-www-form-urlencoded;charest=UTF-8',
success: function (data) {
var imageName;
try {
imageName = JSON.parse(data).key;
} catch (e) {
alert(e.toString);
}
var qiniuUrl = '';
testEditor.insertValue(qiniuUrl);
}
})
});
}
}
}
}
document.addEventListener('paste', function (event) {
paste(event);
})
前端壓縮
前端壓縮使用的是localResizeIMG.js插件。
兼容IE10以上,所以還得做個IE版本判斷,然后看自己是否需要使用干這個插件,我這里就不寫IE的判斷了。
使用方法也很簡單,lrz方法接受一個文件路徑或者base64的圖片,可以設置一個壓縮寬度的對象,低于這個寬度的圖片不會壓縮,大于這個寬度的就會壓縮,然后在then方法中取得壓縮后的圖片:
得先引入這個插件,可以使用src引入,也支持amd or cmd模塊化
<script src="{{asset('js/lrz.bundle.js')}}" type="text/javascript"></script>
開始使用:
//image就是經過paste事件后得到的圖片
lrz(image, {width: 1080}).then(function (res) {
var base64 = res.base64;
}
七牛云sdk
七牛云注冊好像就送10G的云儲存,需要的可以去注冊,先下載七牛云sdk,我使用的是php,地址https://developer.qiniu.com/kodo/sdk/php
配置這個上傳的文件也很簡單。將下載后的壓縮包解壓,刪掉一下沒用的文件,然后拖到項目中:
uploadImageToQiliu.php文件是自己新增的,代碼如下:
<?php
require_once __DIR__ . '/../autoload.php';
use Qiniu\Auth;
// 引入上傳類
use Qiniu\Storage\UploadManager;
$accessKey = '你的accessKey';
$secretKey = '你的secretKey';
// 初始化簽權對象。
$auth = new Auth($accessKey, $secretKey);
$bucket = "空間名字";
$upToken = $auth->uploadToken($bucket);
// 初始化 UploadManager 對象并進行文件的上傳。
$uploadMgr = new UploadManager();
$key = $_POST['name'];
$filePath = $_POST['image'];
list($ret, $err) = $uploadMgr->putFile($upToken, $key, $filePath);
if ($err !== null) {
echo json_encode($err);
} else {
echo json_encode($ret);
}
accessKey和secretKey注冊后就可以看到,bucket是云儲存空間名字。
接下來是前臺傳圖片和圖片名給后臺,圖片名我就直接用 new Date().getTime() 了。
$.ajax({
url: "{{asset('php-sdk/myapis/uploadImageToQiliu.php')}}",
type: 'post',
data: {
"image": res.base64,
"name": new Date().getTime() + ".png"
},
contentType: 'application/x-www-form-urlencoded;charest=UTF-8',
success: function (data) {
var imageName;
try {
imageName = JSON.parse(data).key;
} catch (e) {
alert(e.toString);
}
var qiniuUrl = '';
testEditor.insertValue(qiniuUrl);
}
})
testEditor 是我使用的markdown編輯器的對象實例,testEditor.insertValue(qiniuUrl);就是把格式化好的markdown語句插到光標處。
整個前端代碼如下:
<script type="text/javascript">
function paste(event) {
var clipboardData = event.clipboardData;
var items, item, types;
if (clipboardData) {
items = clipboardData.items;
if (!items) {
return;
}
// 保存在剪貼板中的數據類型
types = clipboardData.types || [];
for (var i = 0; i < types.length; i++) {
if (types[i] === 'Files') {
item = items[i];
break;
}
}
// 判斷是否為圖片數據
if (item && item.kind === 'file' && item.type.match(/^image\//i)) {
// 讀取該圖片
var file = item.getAsFile(),
reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
//前端壓縮
lrz(reader.result, {width: 1080}).then(function (res) {
$.ajax({
url: "{{asset('php-sdk/myapis/uploadImageToQiliu.php')}}",
type: 'post',
data: {
"image": res.base64,
"name": new Date().getTime() + ".png"
},
contentType: 'application/x-www-form-urlencoded;charest=UTF-8',
success: function (data) {
var imageName;
try {
imageName = JSON.parse(data).key;
} catch (e) {
alert(e.toString);
}
var qiniuUrl = '';
testEditor.insertValue(qiniuUrl);
}
})
});
}
}
}
}
document.addEventListener('paste', function (event) {
paste(event);
})
</script>
再編輯器中粘貼完圖片的效果如下: