1. 程式人生 > >從web圖片裁剪出發:瞭解H5中的canvas

從web圖片裁剪出發:瞭解H5中的canvas

本篇內容不針對canvas文件對每個api進行逐個的詳解!

  本篇內容不針對canvas文件對每個api進行逐個的詳解!

  本篇內容不針對canvas文件對每個api進行逐個的詳解!

  重說三,好了,現在進入正文。在上一回《從web圖片裁剪出發:瞭解H5中的blob》中我解釋了圖片在瀏覽器中以怎樣的形式留存,並且在最後一個example中演示了選擇圖片、預覽最後提交的過程。然而這個預覽並沒有起到什麼卵用,因為只能預覽不能處理,原圖片還是原圖片,預覽變得可有可無。這一篇我們就在預覽這一步裡做點手腳,加入處理圖片的功能。

  我們先修改之前的example,既然要處理圖片,肯定要引入canvas,所以我們把原來img這個標籤去掉,取而代之的是canvas,並在js中加入對應的修改。

複製程式碼
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <form name='test'>
    <input type="file" name='file'>
    <input type="submit" value="提交">
  </form>
  <canvas width
="0" height="0"></canvas> <script> var canvas = document.querySelector('canvas'), ctx = canvas.getContext('2d'), preview = new Image(); document.test.file.addEventListener('change', function() { var fr = new FileReader(); fr.onload = function() { preview.src
= this.result; canvas.width = preview.width; canvas.height = preview.height; drawImage(); }; fr.readAsDataURL(this.files[0]); }) function drawImage() { ctx.drawImage(preview, 0, 0); //把圖片繪製到canvas上 } document.test.addEventListener('submit', function(e) { e.preventDefault(); var formData = new FormData(), xhr = new XMLHttpRequest(), mime = 'image/jpeg', dataUrl = canvas.toDataURL(mime, 0.8), //取出base64 data = atob(dataUrl.split(',')[1]), n = data.length, uInt8 = new Uint8Array(n), blob; while(n--) { uInt8[n] = data.charCodeAt(n); } blob = new Blob([uInt8.buffer], {type: mime}); formData.append('file', blob, 'test.jpg'); xhr.open('post', '/upload'); xhr.send(formData); }) </script> </body> </html>
複製程式碼

  之前example的canvas版實現了,現在我們加入處理圖片的功能。首先我們加入裁剪的功能,裁剪的引入必須先引入橡皮筋功能,就是一個選取框。一般我們見過的選取框是這樣的。

預覽的樣子

選取一部分的樣子

  我們來分析下實現這樣一個功能需要做什麼。首先選取框有個開始點和結束點,在滑鼠按下去的時候確定開始點,在鬆開的時候確定結束點,在移動的時候還要不停的繪製。那麼繪製一個有選取框的內容分幾步呢?第一步是繪製底圖,第二步是繪製陰影,第三部還是繪製底圖,但是隻作用於選取框內部。最後想取消選取框怎麼辦,我們還要有個方法重置開始點和結束點,並且只繪製底圖。

  我們一步一步來,首先確定開始點和結束點。

複製程式碼
var sPoint = {},
        ePoint = {};
    canvas.addEventListener('mousedown', function(e) {
      if(e.button === 0) {
        sPoint.x = e.offsetX;
        sPoint.y = e.offsetY;
        sPoint.drag = true;
      }
    });
複製程式碼

  然後我們確定繪製陰影的的方法,並且在滑鼠按下去移動的時候不停的繪製。

複製程式碼
function drawCover() {
      ctx.save();
      ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.restore();
    }
    canvas.addEventListener('mousemove', function(e) {
      if(e.button === 0 && sPoint.drag) {var nPoint = {
          x: e.offsetX,
          y: e.offsetY
        };
        ctx.save();    //clip要通過restore回覆
        ctx.clearRect(0, 0, canvas.width, canvas.height);    //畫布全清
        drawImage();    //繪製底圖
        drawCover();    //繪製陰影
        ctx.beginPath();    //開始路徑
        ctx.rect(sPoint.x, sPoint.y, nPoint.x - sPoint.x, nPoint.y - sPoint.y);    //設定路徑為選取框
        ctx.clip();    //擷取路徑內為新的作用區域
        drawImage();    //在選取框內繪製底圖
        ctx.restore();    //恢復clip擷取的作用範圍
      }
    });
複製程式碼

  最後我們新增鬆開滑鼠的事件監聽,鬆開左鍵為拖動結束,鬆開右鍵為復原

複製程式碼
canvas.addEventListener('mouseup', function(e) {
      if(e.button === 0) {
        sPoint.drag = false;
        ePoint.x = e.offsetX;
        ePoint.y = e.offsetY;
      }else if(e.button === 2) {
        restore();
      }
    });
    function restore() {
      sPoint = {};
      ePoint = {};
      drawImage();
    }
複製程式碼

  由於右鍵會出現噁心的瀏覽器自帶選單欄,影響體驗,我們遮蔽它。

document.addEventListener('contextmenu', function(e) {
      e.preventDefault();
      e.stopPropagation();
    });

  現在選取框有了,我們要開始截取了。新新增一個按鈕,然後新增點選監聽。

html程式碼

<form name='test'>
    <input type="file" name='file'>
    <button id="clip">裁剪</button>
    <input type="submit" value="提交">
  </form>

js程式碼

複製程式碼
var clip = document.querySelector('#clip');
    clip.addEventListener('click', function(e) {
  e.preventDefault();    //阻止預設事件,不然會觸發form的submit
      if(sPoint.x !== undefined && ePoint.x !== undefined) {
        var imgData = ctx.getImageData(sPoint.x, sPoint.y, ePoint.x - sPoint.x, ePoint.y - sPoint.y);    //把裁剪區域的圖片資訊提取出來
        ctx.clearRect(0, 0, canvas.width, canvas.height);    //清空畫布
        canvas.width = Math.abs(ePoint.x - sPoint.x);    //重置canvas的大小為新圖的大小
        canvas.height = Math.abs(ePoint.y - sPoint.y);
        ctx.putImageData(imgData, 0, 0);    //把提取出來的圖片資訊放進canvas中
        preview.src = canvas.toDataURL();    //裁剪後我們用新圖替換底圖,方便繼續處理
      }else {
        alert('沒有選擇區域');
      }
    });
複製程式碼

  現在我們裁剪後選擇提交,會發現伺服器生成的是裁剪後的圖片

  裁剪的功能完成了,我們在來實現第二個功能:灰度。如果說裁剪的功能在於clip的用法,那麼灰度的實現是基於getImageData返回的物件的認識。這個物件中有一個屬性叫data,這是一個數組,以4個為一組,分別儲存了一個畫素red、green、blue、opacity四個資料。也就是當你的canvas尺寸為1*1時,它的ImageData.data元素為4個。

   廢話不多說,直接給出實現的程式碼。

html程式碼

複製程式碼
<form name='test'>
    <input type="file" name='file'>
    <button id="clip">裁剪</button>
    <button id="grey">灰度</button>
    <input type="submit" value="提交">
  </form>
複製程式碼

js程式碼

複製程式碼
var grey = document.querySelector('#grey');
    grey.addEventListener('click', function(e) {
  e.preventDefault();
      var startX = 0, startY = 0, width = canvas.width, height = canvas.height;
      ctx.clearRect(0, 0, canvas.width, canvas.height);    //一如既往的先清空畫布,不然會處理含有選取框的圖片內容
      drawImage();    //繪製底圖
      var imgData = ctx.getImageData(startX, startY, width, height);   //把整個底圖的圖片內容取出來 
      for(var i = 0; i < imgData.data.length;) {
        var red = imgData.data[i],
            green = imgData.data[i+1],
            blue = imgData.data[i+2],
            opacity = imgData.data[i+3],    //不處理,可以省去這一行,佔位說明這一位是透明度
            average = (red + green + blue) / 3;    //所謂灰度其實是取三種顏色的平均值
        imgData.data[i] = imgData.data[i+1] = imgData.data[i+2] = average;    //三個顏色設為一樣即是對應的灰色
        i += 4;
      }
      ctx.putImageData(imgData, startX, startY, 0, 0, width, height);    //把處理過的imagedata放回canvas中
      preview.src = canvas.toDataURL();    //儲存圖片資訊方便再進行處理
    });
複製程式碼

  選擇灰度並提交,我們看伺服器上生成的圖片

  最後我們結合裁剪和灰度,一起處理一張圖片再提交。

 

  好了,簡單的兩個圖片處理的方式就介紹到這,至於複雜的,你可以拿到每一個畫素的資訊,還擔心實現不了其他的功能麼。

複製程式碼

相關推薦

web圖片裁剪出發瞭解H5canvas

本篇內容不針對canvas文件對每個api進行逐個的詳解!   本篇內容不針對canvas文件對每個api進行逐個的詳解!   本篇內容不針對canvas文件對每個api進行逐個的詳解!   重說三,好了,現在進入正文。在上一回《從web圖片裁剪出發:瞭解H5中的blob》

萊斯定理出發看程式分析的sound與complete

萊斯定理是計算理論中非常重要的結論,從它出發也可以明瞭的分析出針對圖靈完備語言進行靜態分析的理論上限。萊斯定理的定義是這樣的: Let S be a set of languages that is nontrivial, meaning there exists a T

利用H5canvas畫布繪製一個時鐘(動態)

注意:Internet Explorer 9、Firefox、Opera、Chrome 以及 Safari 支援 <canvas> 及其屬性和方法。Internet Explorer 8 以及更早的版本不支援 <canvas> 元素 效果圖如下:     實現

#圖文詳解實際和理論出發,帶你瞭解Java的多執行緒

這裡並沒有講什麼新東西,只是把多執行緒一些知識來個總結。大家懂得可以複習複習,還有些童鞋對多執行緒朦朧的可以拿這個做為入門~ 舉個栗子說明啥是多執行緒:玩遊戲,前面一堆怪,每個怪都是一個執行緒,你射了一槍,子彈飛出去了,這顆子彈也是一個執行緒。你開啟你的程序管理,看到你遊戲的後臺程序,這就是程序

Dynamic Web TWAIN使用教程如何Firefox掃描圖片

除了用於IE的ActiveX版本,Dynamic Web TWAIN 同時提供了Plug-in版本,用於Firefox, Chrome,Safari以及其他基於Gecko的瀏覽器。 我們可以使用HTML EMBED來觸發Dynamic Web TWAIN Plug-in.下

開發者應該瞭解web 效能 and Web效能優化教程如何對網站圖片優化?

http://www.wtoutiao.com/p/1deiv1x.html 開發者應該瞭解的 web 效能 併發程式設計網(ifeve) · 2016-01-04 22:16 網站的快和慢有什麼區別呢? 存在一種正確答案嗎? 沒有,很不幸,還沒

web實時通訊講H5 WebSocket

通常我們開啟一個瀏覽器訪問網頁時,都會向頁面所在的伺服器傳送一個HTTP請求,然後web伺服器確認請求並向瀏覽器做出響應。簡單的說,就是一個請求對應的一個響應。然而這種方法對許多的應用場景都會使伺服器的HTTP請求變得臃腫,甚至崩潰。比如:對於股價、新聞每日推送、好友聊天資訊收發等情況,如果每

caffe lmdb資料集的準備原始圖片到生成lmdb檔案

        最近在學習SSD模型,執行官方demo,總是報錯:Data layer prefetch queue empty,網上查各種原因都沒有一個很好的解決方案,自己也快崩潰。即使把batch size設為1,也沒有用。        自己尋思著是不是生成的資料集有

Spring Batch將資料Web服務處理到MongoDB

概觀 在這篇文章中,我們將介紹如何建立一個使用Web服務資料並將其插入MongoDB資料庫的Spring Batch應用程式。 要求 閱讀本文的開發人員必須熟悉Spring Batch(示例)和MongoDB。 環境 Mongo資料庫部署在MLab中。請按照本快速入門中的步驟操作。 批

NDK開發 入門到放棄(一基本流程入門瞭解)

一、前言 ● NDK Native Development Kit(NDK)是一系列工具的集合。它提供了一系列的工具,幫助開發者快速開發C/C++的動態庫,並能自動將so和java一起打包成apk。 ● JNI Java Native Interface(JNI)標準是java平臺的

10年web前端工程師自白前端如何入門到不放棄

首先前端開發的發展這兩年的確冷卻了不少,但是冷卻的並不是行業本身,只能說是技術在沉澱。發展是事物的本質,淘汰陳舊的,與這個時代進步脫節的東西是永恆不變的趨勢。web前端開發由網頁製作演變而來,隨著web2.0的發展,網頁不再只是承載單一的文字和圖片,各種豐富媒體讓網頁的內容更

Web效能優化系列藉助響應式圖片來改進網站圖片顯示

開始使用 <picture> 元素 響應式網頁設計太棒了,它改變了我們向手機端使用者呈現內容的方式,無論使用者使用何種尺寸的手機,我們都能夠為其提供定製化的體驗。響應式網頁設計使用起來很靈活,也容易上手。然而,如果沒有正確使用,它會對網頁效能帶來負面影響。 用於在

Java併發基礎瞭解無鎖CAS就原始碼分析

CAS的全稱為Compare And Swap,直譯就是比較交換。是一條CPU的原子指令,其作用是讓CPU先進行比較兩個值是否相等,然後原子地更新某個位置的值,其實現方式是基於硬體平臺的彙編指令,在intel的CPU中,使用的是cmpxchg指令,就是說CAS是

web前端實驗一利用Js捕獲滑鼠事件實現圖片切換

    很多時候在做web時,頭疼的不是功能的實現,而是前臺的介面,下面是介紹關於利用javascript捕獲滑鼠事件的實驗 實驗目的:滑鼠指向某一圖片時,把該圖片切換為指定圖片,離開時回覆原來圖片。 實驗用途:製作web導航、強調某一功能時非常常用。 直接附上原始碼,非

實踐出發微服務佈道師告訴你Spring Cloud與Spring Boot他如何選擇

背景 隨著公司業務量的飛速發展,平臺面臨的挑戰已經遠遠大於業務,需求量不斷增加,技術人員數量增加,面臨的複雜度也大大增加。在這個背景下,平臺的技術架構也完成了從傳統的單體應用到微服務化的演進。 系統架構的演進過程 單一應用架構(第一代架構) 這是平臺最開始

Maven教程零開始學習到深入瞭解

Maven 簡述 Maven是apache 官方推出的一款專案自動構建工具。這款工具可以方便我們專案依賴的維護,構建,測試,釋出。 不同構建工具的對比 Eclipse 使用eclipse進行專案構建,相對來說,步驟比較零散,不好操作 Ant

web前端基礎案例圖片隨機切換特效

知識點:靜態佈局技巧,定位,浮動,背景設定,CSS樣式選擇器,JS特效,JQ庫呼叫,隨機函式運用。 html程式碼: <body><!--身體 視覺化標籤--> &l

Android開發仿微信和QQ空間發說說相簿讀取、拍照、圖片裁剪圖片上傳伺服器等功能的實現

第一步:新增依賴包: dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23.2.1' compile project('

基礎出發統計學習方法三要素

統計學習方法,初聽起來感覺很陌生,到底什麼是統計學習方法,怎麼去理解?李航老師版的《統計學習方法》給了詳細的解釋,以下是我的理解,如理解有偏差,還望指教。 統計學習方法由三個要素構成,即 模型

Web---圖片驗證碼生成教程詳解-簡單到複雜-本地到前後臺

首先,我們先來看本地如何生成圖片驗證碼的,再來寫輸出到網頁的驗證碼如何實現。 先來看最簡單的—實現的功能是,將一個字串變成圖片寫入到檔案中 實現程式碼: package cn.hncu.img; import java.awt.Graphics;