html5仿小紅書的圖片標簽功能


  最近做了這樣的一個功能,在wap網頁上實現類似小紅書app里的圖片標簽功能,很是蛋疼。

  上傳頁示例如下圖:

  可以看到最上面的①是展示區域,也是編輯標簽的操作區域;中間②是可滑動的縮略圖,在此選擇要編輯的圖片;最下面③是“添加圖片”和“添加標簽”兩個按鈕。

  廢話不多說,下面介紹具體實現思路。

  首先就是要有“選擇圖片”的按鈕。

1 <input type="file" name="fileToUpload" accept="image/*" multiple onchange="fileSelectHandler()" id="image_file" />
 
        

  其中的 multiple 屬性是一次多選多張圖片,但並不是所有瀏覽器都支持,比如UC,如果不支持就只能多選幾次了。

  fileSelectHandler()的作用是處理你所選擇的圖片文件,首先要將圖片顯示在②的區域,這里的滑動效果是用swiper.js實現的,有興趣的同學可以百度一下,有中文官網。但是手機拍照動不動就幾兆的圖片,不利於上傳,而且手機瀏覽器處理時會有明顯卡頓,所以需要壓縮后再使用。

 1 function fileSelectHandler() {
 2     //...
 3     //獲取文件
 4     var oFile = $('#image_file')[0].files;
 5     for (var j = 0; j < oFile.length; j++) {
 6         var oReader = new FileReader();
 7         oReader.readAsDataURL(oFile[j]);
 8         oReader.onloadend = function (e) {
 9             var img = new Image();
10             img.src = this.result;
11             img.onload = function () {
12                 ctx.clearRect(0, 0, ww.width, ww.height);
13                 //兼容蘋果手機
14                 var mpImg = new MegaPixImage(img);
15                 mpImg.render(canvas, { maxWidth: 1000, maxHeight: 1000, quality: 0.1 });
16                
17                 var newImageData = canvas.toDataURL("image/jpeg", 0.3);
18                 var result_image_obj = new Image();
19                 result_image_obj.src = newImageData;
20                 imgkey++;
21                 var imgdata = dataURItoBlob(newImageData);//轉碼
22                 fd.append("file" + imgkey, imgdata);//壓入FormData等待提交
23                 swiper.appendSlide("<div class=\"swiper-slide\"><a href=\"javascript:;\"><img key=\"" + imgkey + "\" onclick=\"clickImg(this)\" src=\"" + result_image_obj.src + "\" /></a></div>");
24             }
25         }
26     }
27 }

  這里有一個坑,就是蘋果手機對canvas的限制,包括圖片大小以及canvas尺寸的限制,如果這里使用drawImage()來畫canvas的話,一旦圖片超出限制,是畫不出來的,所以這里使用了megapix-image.js來繪制圖片,有興趣的同學看這里: ios-imagefile-megapixel 

  這樣②區域就已經顯示剛剛選取的圖片了,我們需要點擊其中一個,使其展現在①區域來進行下一步操作,而①區域就是一個canvas。

1  function clickImg(e) {
2       //全局變量,記錄當前操作的圖片src
3       currentimgsrc = e.src;     
4       //全局變量,記錄當前操作的圖片順序標識
5       flag = e.attributes.key.nodeValue;
6       //核心方法,將所選圖片及其所有標簽繪到①區
7       drawMyCanvas();
8  }

  在實現drawMyCanvas()方法前需要先解決圖片及圖片標簽的存儲問題,我們可以有多張圖片,而每一張圖片又可以有多個標簽,因此,我的思路是由一個Dictionary來存儲。

 1 //鍵值對Dictionary
 2 function Dictionary() {
 3      this.data = new Array();
 4      this.put = function (key, value) {
 5             this.data[key] = value;
 6      };
 7      this.get = function (key) {
 8             return this.data[key];
 9      };
10 }
11 var images = new Dictionary();

  Dictionary的key就是圖片的順序標識,即<img>元素的key屬性值,而value則是一個Array,存儲的就是標簽集合,如下:

1 //圖片標簽
2 function myLabel(x, y, radius, color,text) {
3         this.x = x;//坐標X
4         this.y = y;//坐標Y
5         this.radius = radius;//半徑
6         this.color = color;//顏色
7         this.isSelected = false;//是否是當前選中,拖動標簽時用
8         this.text = text;//標簽文字
9 }

  解決了存儲,現在來為一個圖片添加一個標簽吧。

 1 //在某個范圍內生成隨機數
 2 function randomFromTo(from, to) {
 3         return Math.floor(Math.random() * (to - from + 1) + from);
 4 }
 5 //添加標簽
 6 function addMyLabel(e) {
 7         // 為圓圈設定一個大小和隨機位置
 8         var radius = 10;
 9         //sidelength是canvas的邊長(canvas是個正方形)
10         var x = randomFromTo(0, sidelength-30);
11         var y = randomFromTo(0, sidelength-30);
12 
13         var text = $("#labeltxt").val();//標簽文字
14         // 創建一個新標簽
15         var lab= new myLabel(x, y, radius, "white",text);
16 
17         // 把它保存在數組中
18         if (images.get(flag) == undefined) { //還記得前面的flag變量吧
19             var a=new Array();
20             a.push(lab);
21             images.put(flag,a);
22         } else {
23             images.get(flag).push(lab);
24         }
25         // 重新繪制畫布
26         drawMyCanvas();
27 }

  好了,現在我們來看drawMyCanvas()方法吧。

 function drawMyCanvas() {
          var img = new Image();
          img.src = imgsrc;//這也是前面的全局變量
          img.onload = function () {
              context.clearRect(0, 0, canvas.width, canvas.height);
              context.drawImage(img, 0, 0, canvas.width, canvas.height);
              //遍歷當前圖片的所有標簽
              for (var i = 0; i < images.get(flag).length; i++) {
                  var onelabel= images.get(flag)[i];
 
                  // 繪制標簽的圓點
                  context.globalAlpha = 0.85;
                  context.beginPath();
                  context.arc(onelabel.x, onelabel.y, onelabel.radius, 0, Math.PI * 2);
                  context.fillStyle = onelabel.color;
                  context.strokeStyle = "white";
                  //選中的標簽變粗,以便區分(標簽拖動)
                  if (onelabel.isSelected) {
                      context.lineWidth = 2;
                  }
                  else {
                      context.lineWidth = 1;
                  }
                  //繪制圓點與文字之間的折線
                  context.moveTo(onelabel.x, onelabel.y);
                  context.lineTo(onelabel.x + 15, onelabel.y - 20);
                  context.moveTo(onelabel.x + 15, onelabel.y - 20);
                  context.lineTo(onelabel.x + 30, onelabel.y - 20);
                  context.fill();
                  context.stroke();
                  //繪制標簽文字
                  context.font = "bold 20px 宋體";
                  context.fillText(onelabel.text, onelabel.x + 33, onelabel.y - 15);
 
              }
          }
      }

   最后就是標簽移動的功能了,大致的想法就是隨着拖動事件即時更新標簽的坐標,並調用drawMyCanvas()方法不斷重繪畫布,具體實現大家可以參考這篇文章:

  ----->HTML5 - Canvas的使用樣例14(圖形增加鼠標點擊、拖動交互)  

  這篇文章給了我很大幫助,感謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM