摘要:二編輯合成照片使用編輯壓縮重設(shè)尺寸比例轉(zhuǎn)成輸出預(yù)覽。三保存并上傳照片提交數(shù)據(jù)到服務(wù)器需要服務(wù)器支持我跳過了。數(shù)據(jù)主要來自拍攝的照片,多用于移動端開發(fā),端也會用到,此插件兼容主流瀏覽器,以下不支持。
系列文章
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(零)
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(一) ----- XMLHttpRequest
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(二) ----- File
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(三) ----- FormData
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(四) ----- FileReader
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(五) ----- H5拖拽事件
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(六) ----- 圖片上傳,旋轉(zhuǎn),重繪,預(yù)覽等實(shí)戰(zhàn)(附DEMO)
距離我上次寫的系列文章好像都過了半年了,廢話不多說,先來展示一下技術(shù)思路
一、獲取用戶照片數(shù)據(jù)
獲取用戶攝像頭圖片,不是所有手機(jī)支持,并且部分手機(jī)會有旋轉(zhuǎn)角度的問題;
Input控件獲取照片文件。
二、編輯合成照片
使用canvas編輯壓縮,重設(shè)尺寸比例;
轉(zhuǎn)成base64輸出預(yù)覽。
三、保存并上傳照片
提交base64數(shù)據(jù)到服務(wù)器需要服務(wù)器支持,我跳過了。
因?yàn)橐话闶謾C(jī)像素都很高,所以把原始圖片尺寸限制在300里;
原始圖片
修改圖片
想要上傳圖片,就要用type="file"獲得文件信息,其中下面幾個重要屬性,(在pc瀏覽器打開文件要很久,所以可以選擇性屏蔽)
屬性 | 描述 |
---|---|
accept | 表示可以選擇的文件MIME類型,多個MIME類型用英文逗號分開 |
multiple | 是否可以選擇多個文件,多個文件時其value值為第一個文件的虛擬路徑 |
capture | 表示,可以捕獲到系統(tǒng)默認(rèn)的設(shè)備,比如:camera--照相機(jī);camcorder--攝像機(jī);microphone--錄音 |
通過監(jiān)聽input變化觸發(fā)方法
window.onload = function () { var dom = document.getElementById("file"); dom.addEventListener("change", function (e) {}); }Exif.js
Exif.js 提供了 JavaScript 讀取圖像的原始數(shù)據(jù)的功能擴(kuò)展,例如:拍照方向、相機(jī)設(shè)備型號、拍攝時間、ISO 感光度、GPS 地理位置等數(shù)據(jù)。
EXIF 數(shù)據(jù)主要來自拍攝的照片,多用于移動端開發(fā),PC 端也會用到,此插件兼容主流瀏覽器,IE10 以下不支持。
為了不讓用戶等待太久,我們可以在一系列操作之前先展示獲取的圖片,可以直接從本地先讀取出原始數(shù)據(jù),然后在頁面上展示出來,下面用到的知識點(diǎn)之前已經(jīng)寫過就不再重復(fù)了,可以前往瀏覽文章
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(二) ----- File
關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(四) ----- FileReader
var file = e.target.files[0], //旋轉(zhuǎn)角度 orientation = null, fReader = new FileReader(); //限制大小格式 if (!filtration(file)) { return false; }
上面的filtration(file)是我抽離出去的過濾函數(shù)
filtration: function(file, extend) { var extend = extend || {}, settings = { size: extend.size || 5 * 1024 * 1024, reg: extend.reg || /image/w+/ }; if (file.size > settings.size || !settings.reg.test(file.type)) { alert(extend.msg || ("上傳格式非圖片類型或上傳圖片超過" + settings.size / 1024 / 1024 + "M")) return false; } return true; },
接下來要獲取圖片信息了,解決部分手機(jī)會有旋轉(zhuǎn)角度的問題的前提(可能鏈接格式問題,生成文章之后沒帶鏈接,只能自己復(fù)制粘貼訪問地址了)
中文文檔: http://code.ciaoca.com/javasc...
Demo: http://code.ciaoca.com/javasc...
EXIF.getData(file, function () { orientation = EXIF.getTag(this, "Orientation"); console.log("旋轉(zhuǎn)角度: ", orientation); });
我們已經(jīng)拿到原始數(shù)據(jù),result屬性中將包含一個data: URL格式的字符串以表示所讀取文件的內(nèi)容.然后新建img對象加載資源
//轉(zhuǎn)碼完成 fReader.onload = function (e) { //加載圖片 var img = new Image(); img.src = e.target.result; img.onload = function () { } } //執(zhí)行 fReader.readAsDataURL(file);
接著我們使用canvas畫布重新設(shè)定尺寸重繪達(dá)到壓縮的功能,我只用到基礎(chǔ)使用方法,詳情(Canvas API)
var canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"), nSize = resetSize(this, 300, 300, 1, 600); canvas.width = nSize.width; canvas.height = nSize.height; ctx.drawImage(this, 0, 0, nSize.width, nSize.height);
上面的resetSize是我自定義的一個方法,可以設(shè)置高寬比例最大范圍值,可能有點(diǎn)繁瑣,因?yàn)槲蚁肟刂频墓δ鼙容^多,中間容易發(fā)生沖突,我暫時是后面設(shè)置能覆蓋前面設(shè)置(注意:這里的this是上文的data: URL格式)
resetSize: function(img, width, height, ratio, max) { var w = img.naturalWidth, h = img.naturalHeight, width = width || w, height = height || h; console.log("圖片寬高: ", w, h, "入?yún)? ", width, height, ratio, max); if (w != width) w = width; if (h != height) h = height; if (ratio && w / h != ratio) w = h * ratio; //限制最大值范圍 if (max) { if (w > max && w >= h) { h = Math.ceil(h * max / w); w = max; } else if (h > max && h >= w) { w = Math.ceil(w * max / h); h = max; } } console.log("重設(shè)寬高: ", w, h); return { width: w, height: h } },
接下來就是比較復(fù)雜的圖形操作了,只要掌握了中心點(diǎn)位置就還好理解,詳情(HTML 5 Canvas 參考手冊)
上面拿到的orientation不是真的旋轉(zhuǎn)角度,只是給一個值代表拍攝方向,
最后返回新圖片展示的 data URI,這里水比較深,我測試了jpg和png是沒問題,但是gif什么的就輸出一個靜態(tài)圖,詳情(toDataURL)
var canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"), nSize = picProcess.resetSize(this, 600, 400); switch (+ orientation) { case 3: canvas.width = nSize.width; canvas.height = nSize.height; ctx.rotate(180 * Math.PI / 180); ctx.drawImage(this, -nSize.width, -nSize.height, nSize.width, nSize.height); break; case 6: canvas.width = nSize.height; canvas.height = nSize.width; ctx.rotate(90 * Math.PI / 180); ctx.drawImage(this, 0, -nSize.height, nSize.width, nSize.height); break; case 8: canvas.width = nSize.height; canvas.height = nSize.width; ctx.rotate(270 * Math.PI / 180); ctx.drawImage(this, -nSize.width, 0, nSize.width, nSize.height); break; default: canvas.width = nSize.width; canvas.height = nSize.height; ctx.drawImage(this, 0, 0, nSize.width, nSize.height); break; } return canvas.toDataURL(file.type, 0.8);
現(xiàn)在回看上面,我們已經(jīng)實(shí)現(xiàn)了獲取圖片,重繪圖片,讀取本地圖片,剩下就是預(yù)覽了,我簡單實(shí)現(xiàn)一個支持id和class的方法,也能判斷出img和div智能設(shè)置展示方式
preview: function(selector, url) { var isId = /^#w+/ig.test(selector), isClass = /^.w+/ig.test(selector), name = selector.slice(1), dom = null; //選擇器類型 if (isId) { dom = document.getElementById(name); } else if (isClass) { dom = document.getElementsByClassName(name)[0]; } else { alert("選擇器傳參不支持!"); return false; } //判斷類型 if (dom.nodeName == "IMG") { dom.src = url; } else { dom.style.backgroundImage = "url(" + url + ")"; }; }
然后我們在監(jiān)聽方法里調(diào)用就好了.為了更加直觀的看到代碼效果,我簡單寫了一個demo版本,可以直接下載本地運(yùn)行,不依賴任何環(huán)境實(shí)戰(zhàn)Demo
大家且看且珍惜吧,我可能后續(xù)還會研究手勢旋轉(zhuǎn)處理之類更加復(fù)雜的東西,但也說不好,畢竟還是太懶散了.
循例還是得加上一句,因?yàn)槎紱]有很深入測試過,所以肯定會有些隱藏的問題,歡迎大家指出最好還有答案咯
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/106300.html
摘要:在中,拖放是標(biāo)準(zhǔn)的一部分,任何元素都能夠拖放。如果需要設(shè)置允許放置,我們必須阻止對元素的默認(rèn)處理方式方法。 系列文章 關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(零)關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(一) ----- XMLHttpRequest關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(二) ----- File關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(三) ----- FormData關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(...
摘要:為了解救上面說到的問題是向提交的一個草案,旨在推出一套標(biāo)準(zhǔn)的,其基本功能是實(shí)現(xiàn)用對本地文件進(jìn)行操作。出于安全性的考慮,該只對本地文件提供有限的訪問。 系列文章 關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(零)關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(一) ----- XMLHttpRequest關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(二) ----- File關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(三) ----- For...
摘要:沒有瀏覽器測試,所以不知道是不是有效,其實(shí)里面看起來比我寫的那個復(fù)雜,實(shí)際上多了個檢驗(yàn)格式上兼容寫法所以不要怕,如果我錯了記得提醒下我啊。目前為止其實(shí)已經(jīng)該說的都差不多覆蓋到了吧,動手能力強(qiáng)的話已經(jīng)可以根據(jù)教程寫一個實(shí)例出來的了。 系列文章 關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(零)關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(一) ----- XMLHttpRequest關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(...
摘要:如果是傳入三個參數(shù)的方式,那么該值將是一個布爾值,文件,或者一個,如果不是,將被轉(zhuǎn)成一個字符串可選傳給服務(wù)器的文件名稱一個。 系列文章 關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(零)關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(一) ----- XMLHttpRequest關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(二) ----- File關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(三) ----- FormData關(guān)于前端上傳文...
摘要:表單用于向服務(wù)器傳輸數(shù)據(jù)。屬性對象的屬性指定了一個事件句柄函數(shù)。標(biāo)簽的屬性應(yīng)當(dāng)與相關(guān)元素的屬性相同。詳情查閱請狠狠地點(diǎn)擊關(guān)于對象代表表單中的一個提交按鈕在表單提交之前,觸發(fā)事件句柄,并且一個句柄可以通過返回來取消表單提交。 系列文章 關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(零)關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(一) ----- XMLHttpRequest關(guān)于前端上傳文件全面基礎(chǔ)掃盲貼(二) -...
閱讀 1570·2021-11-19 09:55
閱讀 2795·2021-09-06 15:02
閱讀 3564·2019-08-30 15:53
閱讀 1118·2019-08-29 16:36
閱讀 1247·2019-08-29 16:29
閱讀 2298·2019-08-29 15:21
閱讀 636·2019-08-29 13:45
閱讀 2692·2019-08-26 17:15