方案:html+wkwebview诗祸,支持加粗媒抠、下劃線瞎疼、斜體、對齊方式密强、字體更改顏色、插入圖片蜗元、插入視頻或渤、插入鏈接、清除格式奕扣、撤回上一個操作
核心:利用html5新特性contenteditable薪鹦,當div的contenteditable為true時,div進入編輯狀態(tài)惯豆,可以通過執(zhí)行html5的命令對文本進行操作池磁。命令文檔地址:https://developer.mozilla.org/zh-TW/docs/Web/API/Document/execCommand。
具體實現(xiàn):
一:文件目錄
1.editor.html,該文件實現(xiàn)了編輯器的節(jié)點骨架楷兽,一個contenteditable為true的div地熄。
<body onLoad="zss_editor.init();">
<div id="zss_editor_content" class="zs_editor_content" contenteditable="true"><p><br></p><!-- defaultContent --></div>
?<div id="zss_editor_placeHolder">請輸入文章內(nèi)容</div>
</body>
2.ZJSTextEditor.js,該文件是編輯器的核心內(nèi)容芯杀,主要實現(xiàn)編輯器的各種操作端考,以插入視頻為例,外部的wkwebview只需要執(zhí)行js方法evaluateJavaScript:‘zss_editor.insertVideo(...)’,將url帶入
zss_editor.insertVideo =function(videoUrl) {
? ? var poster = videoUrl+'?vframe/jpg/offset/5/w/210';
?? ? var str = '<br name = "deleteBr"><video? controls="controls" src="'+videoUrl+'" poster = "'+poster+'"></video>';
?? ? zss_editor.insertHTML(str);
?? ? zss_editor.insertP();
?? ? zss_editor.deleteNode('deleteBr');
}
zss_editor.insertP = function() {?? ?
var contentDiv = document.getElementById("zss_editor_content");?? ?
var p = document.createElement("p");?? ?
contentDiv.appendChild(p);
}
zss_editor.insertHTML = function(str) {??
var result = document.execCommand('insertHTML', false, str);? ?
if(result == false) {? ? ? ?
$('#zss_editor_content').html(str);? ?
}
}
3.EditorView這個文件主要是放wkwebview瘪匿,以及wkwebview調(diào)用ZJSTextEditor.js中js方法的部分跛梗。如頁面加載完,設(shè)置占位文字棋弥,或者默認對一些標簽的處理
- (void)webView:(WKWebView*)webViewdidFinishNavigation:(WKNavigation*)navigation {
? ? NSLog(@"頁面加載完畢");
? ? [[UIApplication sharedApplication].keyWindow? zjs_removeIndicatorWithBackgroundColor];
? ? if(_webView) {
?? ? ? ? NSString *trigger = @"zss_editor.setDefualt();";
?? ? ? ? [self.webViewevaluateJavaScript:triggercompletionHandler:^(id_Nullableres,NSError*_Nullableerror) {
? ? ? ? ? ? ? if(error) {
? ? ? ? ? ? ? DLog(@"===%@",error);
? ? ? ? ? ? ? }
?? ? ? ? }];
?? ? ? ? NSString*setPlaceHolder =@"zss_editor.placeholder();";
?? ? ? ? [self.webViewevaluateJavaScript:setPlaceHoldercompletionHandler:^(id_Nullableres,NSError*_Nullableerror) {
? ? ? ? ? ? ? if(error) {
? ? ? ? ? ? ? DLog(@"===%@",error);
? ? ? ? }
?? ? ? ? }];
?? ? }
}
二:開發(fā)中產(chǎn)品提出的需求和我的設(shè)計方案
1.web端要求dom結(jié)構(gòu)為<p>...</p>?<p>...</p>?<p>...</p>?<p>...</p>?<p>...</p>,也就是n個p里包含著你插入的視頻圖片等子節(jié)點核偿?
我的方案:
1.1:在editor.html文件中插入的div中,插入一個默認的空p標簽<p><br></p>,這樣會保證你在文字中間插入圖片顽染、視頻或者換行時漾岳,系統(tǒng)給你新增一個p標簽包裹而不是div標簽
1.2:在插入圖片后加入一個空p轰绵,在文字中間插入視頻后加入一個空的p和br再刪除br,插入br是為了在文字中間插入視頻時尼荆,讓系統(tǒng)自動給你補全p標簽左腔,否則視頻會被加在該文字的下一行。
2.每個圖片要緊緊跟隨一個圖片輸入框捅儒,且圖片輸入框支持粘貼液样,且圖片和圖片輸入框可以通過某個按鈕同時被刪除?
我的方案:
圖片有三個途徑添加巧还,第一個是粘貼來的新聞中帶有圖片鞭莽,第二個是自己插入的圖片,第三個是從html剛剛開始加載時自帶圖片(從web端發(fā)布的文章麸祷,在ios端編輯)澎怒。
2.1:每個圖片要緊緊跟著一個圖片輸入框,我在三個途徑處分別做了圖片的處理阶牍,首先是自己插入的圖片喷面,我在插入圖片時,緊接著插入一個textarea標簽和一個p標簽走孽。插入一個p標簽的目的是滿足需求1惧辈,其次是粘貼來的新聞和html剛剛加載自帶的圖片,我選擇遍歷所有的圖片標簽融求,首先檢查img標簽的name屬性是否有值咬像,若沒有值,新增textarea標簽生宛,并設(shè)置img標簽和textarea標簽的name屬性為同一個UUID县昂,若name屬性有值,檢查它的后一個兄弟節(jié)點是否跟隨一個同name的dom陷舅,如果有且是i標簽(提交數(shù)據(jù)時倒彰,要將所有的輸入框變成i標簽,此刻要從i標簽變回輸入框)莱睁,將它轉(zhuǎn)化成輸入框待讳,如果沒有,添加默認輸入框仰剿。
2.2:圖片輸入框支持粘貼创淡,textarea自帶粘貼
2.3:圖片和圖片輸入框可以通過某個按鈕同時被刪除,設(shè)置img標簽和textarea標簽的name屬性為同一個UUID南吮,用name的原因是document.getElementsByName給的是該name的一組標簽琳彩,刪除時,只需要根據(jù)name刪除即可
3.從微信或者頭條粘貼過來的文章格式有誤,文字偏大或者偏新斗Α碧浊?
我的解決方案:
由于拿不到原文章的js,所以只能在粘貼時去除標簽內(nèi)的所有內(nèi)聯(lián)樣式瘟仿。當然這個地方有個特殊情況要處理箱锐,比如用戶在編輯時,設(shè)置了對齊方式劳较,系統(tǒng)會自動給標簽加上內(nèi)聯(lián)樣式驹止,這個樣式我們不應(yīng)該去掉。我的處理方案時自定義一個屬性名zjs-style兴想,在用戶設(shè)置對齊方式時幢哨,將標簽的style值賦值給zjs-style,我們在合適的時機嫂便,根據(jù)zjs-style復(fù)原其style
4.輸入框在提交后變成不可輸入的展示區(qū)域?
我的解決方案:
在提交時闸与,遍歷所有的textarea毙替,若textarea沒有值,去掉該textarea践樱,若有值的話厂画,將該textarea替換成i標簽,且name值賦值給新的i拷邢。
5.從web端來的數(shù)據(jù)支持展示和再編輯袱院?
我的解決方案:
在editor.html的div中加入默認占位文字<!-- defaultContent -->,在html資源加載前瞭稼,將占位文字替換為后臺給的html內(nèi)容忽洛,并在網(wǎng)頁加載完后,做相關(guān)處理
調(diào)試工具:
<!--用于打印日志-->
<!--<script src="https://cdn.bootcss.com/vConsole/3.3.2/vconsole.min.js"></script>-->
<!--<script>-->
<!--new VConsole()-->;
<!--</script>-->