1. 程式人生 > >前端實現文字框在游標後插入圖片

前端實現文字框在游標後插入圖片

為解決這個問題,我們需要先整理一下步驟:

1、從剪貼簿中讀出圖片

2、將圖片轉為base64編碼

3、將圖片存入游標的位置

1、(1)我們可以通過設定div監聽paste事件

                document.querySelector('#editDiv').addEventListener('paste',function(e){...})

             當觸發paste事件時,在Chrome環境下,我們可以通過

                                     var cbd = e.clipboardData;

              獲得剪貼簿的資料。

      (2)我們通過判斷獲得的資料型別確定img

                                     cbd.items[i].kind=='file'||'string'

               img的型別是‘file’,然後我們可以通過getAsFile方法

                                     var blob = item.getAsFile();

                得到圖片檔案

2、(1)新建一個檔案讀取物件

                                     var reader = new FileReader();

                這樣我們就可以通過該物件的readAsDataURL方法

                                     reader.readAsDataURL(blob);

                獲得當前blob(File)物件的base64編碼

        (2)根據base64編碼,我們可以生成一個img標籤

                                      

3、(1)獲得游標位置,生成range操作範圍

                              var selection= window.getSelection                               
                              var range= selection.createRange 

        (2)根據img字串聲稱對應的html標籤,並將它放入range中

                              var hasR = range.createContextualFragment(str);
                              range.insertNode(hasR);

         (3)將新建的range放入游標後面

                              selection.addRange(range)

部分程式碼:

document.querySelector('#editDiv').addEventListener('paste',function(e){
                var cbd = e.clipboardData;
                var ua = window.navigator.userAgent;
                // 如果是 Safari 直接 return
                if ( !(e.clipboardData && e.clipboardData.items) ) {
                    return ;
                }
                // Mac平臺下Chrome49版本以下 複製Finder中的檔案的Bug Hack掉
                if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" &&
                    cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" &&
                    ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49){
                    return;
                }
                for(var i = 0; i < cbd.items.length; i++) {
                    var item = cbd.items[i];
                    if(item.kind == "file"){
                        var blob = item.getAsFile();
                        if (blob.size === 0) {
                            return;
                        }

                        /*-----------------------不與後臺進行互動 直接預覽start-----------------------*/
                        var reader = new FileReader();
                        var imgs = new Image();
                        imgs.file = blob;
                        var img;
                        reader.onload = (function(aImg) {
                          return function(e) {
                            aImg.src = e.target.result;
                            img="<img src='"+aImg.src+"'>";
                            _insertimg(img)
                          };
                        })(imgs);
                        reader.readAsDataURL(blob);
                        /*-----------------------不與後臺進行互動 直接預覽end-----------------------*/
                    }
                }
            }, false);
//鎖定編輯器中滑鼠游標位置。。
    function _insertimg(str){
        var selection= window.getSelection ? window.getSelection() : document.selection;
        var range= selection.createRange ? selection.createRange() : selection.getRangeAt(0);
        if (!window.getSelection){
            document.getElementById('editDiv').focus();
            var selection= window.getSelection ? window.getSelection() : document.selection;
            var range= selection.createRange ? selection.createRange() : selection.getRangeAt(0);
            range.pasteHTML(str);
            range.collapse(false);
            range.select();
        }else{
        document.getElementById('editDiv').focus();
        range.collapse(false);
        var hasR = range.createContextualFragment(str);
        var hasR_lastChild = hasR.lastChild;
        while (hasR_lastChild && hasR_lastChild.nodeName.toLowerCase() == "br" && hasR_lastChild.previousSibling && hasR_lastChild.previousSibling.nodeName.toLowerCase() == "br") {
        var e = hasR_lastChild;
        hasR_lastChild = hasR_lastChild.previousSibling;
        hasR.removeChild(e)
        }
        range.insertNode(hasR);
        if (hasR_lastChild) {
        range.setEndAfter(hasR_lastChild);
        range.setStartAfter(hasR_lastChild)
        }
        selection.removeAllRanges();
        selection.addRange(range)
        }
    }