SS3中引入的clip-path(裁剪路徑)屬性是一個很強大的特性。clip-path的含義如下圖所示,好比剪紙一樣,你用剪刀沿著某條路徑把目標對象(圖像或元素)裁剪成我們想要的形狀。
clip-path支持多種方式,如基本的圖形(多邊形polygon(), 圓形circle(), inset() (用來定義內(nèi)部矩形), 和橢圓 ellipse()),也支持直接引用SVG中的clipPath元素。先看二個效果圖
通常簡單的裁剪,我們直接使用基本圖形,或者使用在線工具輔助生成,我們推薦使用:
http://www.ikinsoft.com/clippath/clippath.html
來生成一些簡單的裁剪路徑,代碼如下:
/* Using a CSS basic shape function */
.element {
clip-path: polygon(...); /* or one of the other shape functions */
}
對于更為復雜的裁剪,使用SVG無疑是更好的選擇,我們可以在AI或Inkscape中創(chuàng)作好矢量圖,然后根據(jù)其路徑(path)數(shù)據(jù)生成相應的clipPath元素,然后在CSS3中直接引用,代碼如下:
/* Referencing an SVG clipPath */
.element {
clip-path: url(#svgClipPathID);
}
但是在使用SVG clipPath元素時,經(jīng)常會遇到單位不匹配的情況,因為通常通過工具生成的g元素,會應用一些變換(如位移和縮放):
<g transform="translate(0.000000,126.000000) scale(0.100000,-0.100000)"><clipPath>your paths here</clipPath></g>
而在CSS3直接引用clipPath時,不會自動去處理這些變換,需要我們自己來處理,
把path數(shù)據(jù)轉換成百分比,然后給clipPath添加clipPathUnits="objectBoundingBox"屬性來自適應:
<svg width="0" height="0">
<defs>
<clipPath id="svgPath" clipPathUnits="objectBoundingBox">
<!-- your paths here -->
</clipPath>
</defs>
</svg>
clipPathUnits 屬性用來指定<clipPath>元素內(nèi)容的坐標系,有2種取值:
clipPathUnits="userSpaceOnUse | objectBoundingBox"
userSpaceOnUse表示當前網(wǎng)頁所使用的屏幕坐標系,而objectBoundingBox則把坐標空間的原點調整到被裁剪對象的左上角,坐標空間的長寬設定為該元素的長寬。
生成polygons圖形clipPath數(shù)據(jù)的JavaScript代碼,如下:
$.each(shape_array.polygon, function (i, shape) {
paths='';
$.each(shape.coords, function (i, coord) {
type="polygon";
var x=coord[0] + "%";
var y=coord[1] + "%";
var path='clip-path: polygon()';
var coord='';
if (i==shape.coords.length - 1) {
// last coordinate to add, omits a comma at the end
paths +=x + ' ' + y;
var clip_path='polygon(' + paths + ')';
appendFigure(clip_path, shape);
} else {
// loops through each coordinate and adds it to a list to add
paths +=x + ' ' + y + ', ';
}
});
下截圖:
點擊文件選擇框,我們不妨選一張尺寸比較大的圖片,例如下面這種2M多的釣魚收獲照:
于是圖片歘歘歘地傳上去了:
此時我們點擊最終上傳完畢的圖片地址,會發(fā)現(xiàn)原來2M多3000多像素寬的圖片被限制為400像素寬了:
保存到本地會發(fā)現(xiàn)圖片尺寸已經(jīng)變成只有70K了:
以上就是圖片前端壓縮并上傳demo的完整演示。
二、實現(xiàn)原理
要想使用JS實現(xiàn)圖片的壓縮效果,原理其實很簡單,核心API就是使用canvas的drawImage()方法。
Canvas本質上就是一張位圖,而drawImage()方法可以把一張大大的圖片繪制在小小的Canvas畫布上,不久等同于圖片尺寸壓縮了?
對于本案例的壓縮,使用的5個參數(shù)的API方法:
context.drawImage(img, dx, dy, dWidth, dHeight);復制代碼
各參數(shù)具體含義可以參見“Canvas API中文文檔-drawImage”,這里不展開。
舉例:
一張圖片(假設圖片對象是img)的原始尺寸是4000*3000,現(xiàn)在需要把尺寸限制為400*300大小,很簡單,原理如下代碼示意:
var canvas=document.createElement('canvas'); var context=canvas.getContext('2d'); canvas.width=400; canvas.height=300; // 核心JS就這個 context.drawImage(img,0,0,400,300);復制代碼
把大圖片畫在一張小畫布上,壓縮就這么實現(xiàn)了,是不是簡單的有點超乎想象。
三、如果想要上傳或下載?
如果想要上傳圖片或者下載圖片,可以使用canvas.toDataURL()或者canvas.toBlob()方法先進行轉換。
1. canvas.toDataURL()
語法如下:canvas.toDataURL(mimeType, qualityArgument)復制代碼
可以把畫布轉換成base64格式信息圖像信息,純字符的圖片表示法。
其中:
mimeType表示canvas導出來的base64圖片的類型,默認是png格式,也即是默認值是'image/png',我們也可以指定為jpg格式'image/jpeg'或者webp等格式。file對象中的file.type就是文件的mimeType類型,在轉換時候正好可以直接拿來用(如果有file對象)。
qualityArgument表示導出的圖片質量,只要導出為jpg和webp格式的時候此參數(shù)才有效果,默認值是0.92,是一個比較合理的圖片質量輸出參數(shù),通常情況下,我們無需再設定。
更多關于toDataURL()方法的信息可以參見“Canvas API中文文檔-toDataURL()”。
2. canvas.toBlob()方法
語法如下:canvas.toBlob(callback, mimeType, qualityArgument)復制代碼
可以把畫布轉換成Blob文件,通常用在文件上傳中,因為是二進制的,對后端更加友好。
和toDataURL()方法相比,toBlob()方法是異步的,因此多了個callback參數(shù),這個callback回調方法默認的第一個參數(shù)就是轉換好的blob文件信息,本文一開始的demo案例中的文件上傳就是將canvas圖片轉換成二進制的blob文件,然后再ajax上傳的,代碼如下:
// canvas轉為blob并上傳 canvas.toBlob(function (blob) { // 圖片ajax上傳 var xhr=new XMLHttpRequest(); // 開始上傳 xhr.open("POST", 'upload.php', true); xhr.send(blob); });復制代碼
更多關于toBlob()方法的信息可以參見“Canvas API中文文檔-toBlob()”。
一旦有了可傳輸?shù)膱D像數(shù)據(jù),上傳下載就好實現(xiàn)了。例如下載前端壓縮好的圖片,可以參考我上一篇在掘金發(fā)布的文章:“純JS生成并下載各種文本文件或圖片”。
四、總結
經(jīng)過“圖片→canvas壓縮→圖片”三步曲,我們完成了圖片前端壓縮功能。
作者:張鑫旭
鏈接:https://juejin.im/post/5bec3c6cf265da614312a0fa
來源:掘金
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。
cropperjs是一款基于JavaScript的網(wǎng)頁端圖片裁剪插件,可能相對于圖片預覽來說,圖片的裁剪使用場景貌似并不是很多,但是圖片預覽插件又要比裁剪插件容易找到,而且從實現(xiàn)難度上來說也不及圖片裁剪,今天我們就一起來看看這款良心的圖片裁剪插件——Cropperjs
作者的幾個經(jīng)典作品都在Github上,并且都獲得不菲的stars,感謝作者提供這么好用的免費插件
https://github.com/fengyuanchen/cropperjs
使用npm安裝或者直接下載編譯好的js文件
npm install cropperjs
<link href="/path/to/cropper.css" rel="stylesheet">
<script src="/path/to/cropper.js"></script>
new Cropper(element[, options])
使用案例:
<div>
<img id="image" src="picture.jpg">
</div>
img {
display: block;
/* This rule is very important, please don't ignore this */
max-width: 100%;
}
import Cropper from 'cropperjs';
const image=document.getElementById('image');
const cropper=new Cropper(image, {
aspectRatio: 16 / 9,
crop(event) {
console.log(event.detail.x);
console.log(event.detail.y);
console.log(event.detail.width);
console.log(event.detail.height);
console.log(event.detail.rotate);
console.log(event.detail.scaleX);
console.log(event.detail.scaleY);
},
});
PS:具體的配置選項可以到Github上查看相關文檔,同時也提供了一個在線的預覽demo
https://fengyuanchen.github.io/cropperjs/
cropperjs是一個純前端的圖片裁剪工具,同時筆者之前文章也介紹過和cropperjs同源作者的另一個佳作viewerjs,這是一個優(yōu)秀的前端圖片預覽插件,功能豐富,配置簡單,推薦使用,enjoy it!
https://www.toutiao.com/i6775436136027259404/
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。