頭像圖片上傳可能會(huì)用到的圖片壓縮和圖片旋轉(zhuǎn)技術(shù)

# 業(yè)務(wù)背景

突然有一次搞活動(dòng),需要用戶上傳自己的自拍照,然后服務(wù)器端把頭像做些特殊處理,這個(gè)時(shí)候可能會(huì)遇到的坑。

## 坑點(diǎn)二:人像是倒著的

如果用戶直接采用攝像頭拍照,這樣的話獲取到的照片可能會(huì)是倒著的,這樣是影響業(yè)務(wù)的。

## 坑點(diǎn)一:圖片過(guò)大

現(xiàn)在手機(jī)拍出來(lái)的照片,基本都是5M 以上的圖片,對(duì)于上傳壓力太大了。

# 解決方案

## 人像是倒著的: exif.js 來(lái)解決

可以通過(guò) exif.js 來(lái)獲取圖片的各種信息。

采用的是 [exif-js](https://www.npmjs.com/package/exif-js) 來(lái)獲取圖片基本信息

函數(shù)封裝:

```js

const getImgExif = function (file, callback) {

? ? ? ? ? ? $('#hideImg').attr('src', ''); // 先清空操作

? ? ? ? ? ? var reader = new FileReader();

? ? ? ? ? ? // 文件base64化,以便獲知圖片原始尺寸

? ? ? ? ? ? reader.onload = function (e) {

? ? ? ? ? ? ? ? var imgBase64 = e.target.result;

? ? ? ? ? ? ? ? $('#hideImg').attr('src', imgBase64);

? ? ? ? ? ? ? ? var $img = document.getElementById('hideImg');

? ? ? ? ? ? ? ? $img.onload = function () {

? ? ? ? ? ? ? ? ? ? window.EXIF.getData($img, function () {

? ? ? ? ? ? ? ? ? ? ? ? var orientation = EXIF.getTag(this, 'Orientation');

? ? ? ? ? ? ? ? ? ? ? ? callback(false, orientation, imgBase64);

? ? ? ? ? ? ? ? ? ? });

? ? ? ? ? ? ? ? };

? ? ? ? ? ? };

? ? ? ? ? ? reader.readAsDataURL(file);

? ? ? ? }

```

這樣就可以獲取到圖片的`orientation` 屬性了。

## 圖片過(guò)大:canvas 壓縮圖片

可以利用 `canvas` 提供的 `drawImage` 方法來(lái)實(shí)現(xiàn) 圖片的壓縮。

核心方法

```js

? ? /**

? ? *

? ? * @param imgBase64? 圖片的 base64

? ? * @param rotate 旋轉(zhuǎn)角度

? ? * @param maxW 壓縮的最大寬度

? ? * @param maxH 壓縮的最大高度

? ? * @param callback 回調(diào)函數(shù)。

? ? */

? ? function rotateImg(imgBase64, rotate, maxW, maxH, callback) {

? ? ? ? var img = new Image();

? ? ? ? img.src = imgBase64;

? ? ? ? if (typeof maxW == 'function') {

? ? ? ? ? ? callback = maxW;

? ? ? ? ? ? maxW = null;

? ? ? ? ? ? maxH = null;

? ? ? ? }

? ? ? ? if (rotate) {

? ? ? ? ? ? if (rotate !== '90' && rotate !== '-90' && rotate !== '180') {

? ? ? ? ? ? ? ? rotate = null;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? img.onload = function (ev) {

? ? ? ? ? ? var originWidth = this.width;

? ? ? ? ? ? var originHeight = this.height;

? ? ? ? ? ? var targetWidth = originWidth;

? ? ? ? ? ? var targetHeight = originHeight;

? ? ? ? ? ? var maxWidth = maxW || 750, maxHeight = maxH || 750;

? ? ? ? ? ? if (originWidth > maxWidth || originHeight > maxHeight) {

? ? ? ? ? ? ? ? if (originWidth / originHeight > maxWidth / maxHeight) {

? ? ? ? ? ? ? ? ? ? targetWidth = maxWidth;

? ? ? ? ? ? ? ? ? ? targetHeight = Math.round(maxWidth * (originHeight / originWidth));

? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? targetHeight = maxHeight;

? ? ? ? ? ? ? ? ? ? targetWidth = Math.round(maxHeight * (originWidth / originHeight));

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? var canvas = document.createElement('canvas');

? ? ? ? ? ? var context = canvas.getContext('2d');

? ? ? ? ? ? canvas.width = targetWidth;

? ? ? ? ? ? canvas.height = targetHeight;

? ? ? ? ? ? context.clearRect(0, 0, targetWidth, targetHeight);

? ? ? ? ? ? context.drawImage(img, 0, 0, originWidth, originHeight, 0, 0, targetWidth, targetHeight);

? ? ? ? ? ? var dataUrl = canvas.toDataURL("image/jpeg");

? ? ? ? ? ? if (rotate) {

? ? ? ? ? ? ? ? var angle = 0;

? ? ? ? ? ? ? ? var canvas2 = document.createElement('canvas');

? ? ? ? ? ? ? ? var context2 = canvas2.getContext('2d');

? ? ? ? ? ? ? ? canvas2.width = targetWidth;

? ? ? ? ? ? ? ? canvas2.height = targetHeight;

? ? ? ? ? ? ? ? var _setting = {

? ? ? ? ? ? ? ? ? ? dx: 0,

? ? ? ? ? ? ? ? ? ? dy: 0,

? ? ? ? ? ? ? ? ? ? dw: 0,

? ? ? ? ? ? ? ? ? ? dh: 0,

? ? ? ? ? ? ? ? ? ? transX: 0,

? ? ? ? ? ? ? ? ? ? transY: 0

? ? ? ? ? ? ? ? };

? ? ? ? ? ? ? ? var scale = 0;

? ? ? ? ? ? ? ? if (rotate === '180') {

? ? ? ? ? ? ? ? ? ? angle = Math.PI;

? ? ? ? ? ? ? ? ? ? _setting.dw = targetWidth;

? ? ? ? ? ? ? ? ? ? _setting.dh = targetHeight;

? ? ? ? ? ? ? ? ? ? context2.translate(targetWidth, targetHeight);

? ? ? ? ? ? ? ? ? ? context2.rotate(angle);

? ? ? ? ? ? ? ? ? ? context2.translate(0, 0);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? else {

? ? ? ? ? ? ? ? ? ? if (rotate === '90') {

? ? ? ? ? ? ? ? ? ? ? ? angle = 90 * (Math.PI / 180);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? else if (rotate === '-90') {

? ? ? ? ? ? ? ? ? ? ? ? angle = -90 * (Math.PI / 180);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? _setting.transX = parseFloat(targetHeight / 2);

? ? ? ? ? ? ? ? ? ? _setting.transY = parseFloat(targetWidth / 2);

? ? ? ? ? ? ? ? ? ? _setting.dw = targetHeight;

? ? ? ? ? ? ? ? ? ? scale = targetWidth / targetHeight;

? ? ? ? ? ? ? ? ? ? _setting.dh = parseFloat(_setting.dw / scale);

? ? ? ? ? ? ? ? ? ? _setting.dy = (targetWidth - _setting.dh) / 2;

? ? ? ? ? ? ? ? ? ? context2.translate(_setting.transX, _setting.transY);

? ? ? ? ? ? ? ? ? ? context2.rotate(angle);

? ? ? ? ? ? ? ? ? ? context2.scale(scale, scale);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? /**

? ? ? ? ? ? ? ? * ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

? ? ? ? ? ? ? ? *

? ? ? ? ? ? ? ? * image: 可以是一個(gè)image ,或者一個(gè)canvas

? ? ? ? ? ? ? ? * sx: 在畫布所繪制圖片本身的x軸的距離

? ? ? ? ? ? ? ? * sy: 在畫布所繪制圖片本身y軸的距離

? ? ? ? ? ? ? ? * sWidth:表示所繪制圖片的寬度范圍,一般默認(rèn)是圖片的完整大小。也可以是部分繪制。

? ? ? ? ? ? ? ? * sHeight:表示所繪制圖片的高度范圍,一般默認(rèn)是圖片的完整大小。也可以是部分繪制。

? ? ? ? ? ? ? ? * dx:表示在畫布x軸的坐標(biāo)值

? ? ? ? ? ? ? ? * dy:表示在畫布y軸的坐標(biāo)值

? ? ? ? ? ? ? ? * dWidth: 在畫布繪制的寬度

? ? ? ? ? ? ? ? * dHeight:在畫布繪制的長(zhǎng)度

? ? ? ? ? ? ? ? */

? ? ? ? ? ? ? ? context2.drawImage(canvas, 0, 0, targetWidth, targetHeight, _setting.dx - _setting.transX, _setting.dy - _setting.transY, _setting.dw, _setting.dh);

? ? ? ? ? ? ? ? dataUrl = canvas2.toDataURL("image/jpeg");

? ? ? ? ? ? }

? ? ? ? ? ? callback(dataUrl);

? ? ? ? };

? ? }

```

# demo

demo地址:https://bosscheng.github.io/canvas-rotate-image

demo2地址:https://bosscheng.github.io/web-h5/2018%E4%B8%96%E7%95%8C%E6%9D%AF/wap0618/index.html

github地址:https://github.com/bosscheng/canvas-rotate-image

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容