我們都知道在“寸土寸金”的互聯網時代, 速度是第一競爭力, 雖然我們的5G發展已經搖搖領先, 但是也經不住用戶在一個網頁里傳很多“巨無霸”圖片, 最終導致的結果就是頁面“龜速”打開......
那么作為技術人, 當然也有一堆的解決方案, 比如:
當然聰明的小伙伴也會將上面的方案組合, 設計更優秀的圖片“提速”方案.
今天不會和大家把所有方案都介紹一遍, 因為網上也有很多實踐, 接下來會從前端技術提升的角度, 分享一下如何用原生 javascript, 實現從圖片上傳到圖片自定義壓縮的完整方案. 大家可以把文章中介紹的方案直接用于自己的實際開發中, 或者基于它設計更棒的圖片壓縮方案.
前端實現圖片壓縮無非就是在用戶上傳圖片文件后, 將file轉換成image對象, 然后再利用canvas 及其 api 將圖片壓縮成指定體積. 如下流程:
首先我們先實現將file轉換成image對象, 這里我們用到了FileReader API, 代碼如下:
// 壓縮前將file轉換成img對象
function readImg(file:File) {
return new Promise((resolve, reject)=> {
const img=new Image()
const reader=new FileReader()
reader.onload=function(e:any) {
img.src=e.target.result
}
reader.onerror=function(e) {
reject(e)
}
reader.readAsDataURL(file)
img.onload=function() {
resolve(img)
}
img.onerror=function(e) {
reject(e)
}
})
}
這里使用 promise 來設計生成圖片數據的方法, 接下來我們看看核心的圖片壓縮源碼:
/**
* 壓縮圖片
* @param img 被壓縮的img對象
* @param type 壓縮后轉換的文件類型
* @param mx 觸發壓縮的圖片最大寬度限制
* @param mh 觸發壓縮的圖片最大高度限制
* @param quality 圖片質量
*/
function compressImg(img: any, type:string, mx: number, mh: number, quality:number=1) {
return new Promise((resolve, reject)=> {
const canvas=document.createElement('canvas')
const context=canvas.getContext('2d')
const { width: originWidth, height: originHeight }=img
// 最大尺寸限制
const maxWidth=mx
const maxHeight=mh
// 目標尺寸
let targetWidth=originWidth
let targetHeight=originHeight
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > 1) {
// 寬圖片
targetWidth=maxWidth
targetHeight=Math.round(maxWidth * (originHeight / originWidth))
} else {
// 高圖片
targetHeight=maxHeight
targetWidth=Math.round(maxHeight * (originWidth / originHeight))
}
}
canvas.width=targetWidth
canvas.height=targetHeight
context?.clearRect(0, 0, targetWidth, targetHeight)
// 圖片繪制
context?.drawImage(img, 0, 0, targetWidth, targetHeight)
canvas.toBlob(function(blob) {
resolve(blob)
}, type || 'image/png', quality)
})
}
這里通過控制 canvas的寬高, 以及對 canvas 的 toBlob設置參數, 來實現自定義的圖片壓縮.
如果大家對代碼有不理解的地方, 也可以在文末發表問題, 我會做出對應的解答.
的選擇是做或不做,但不做就永遠不會有機會。
監聽剪切板粘貼事件,讀取剪切板中的圖片文件,轉成base64通過img標簽顯示出來,此時可能會存在剪切板中圖片過大,產生上傳速度慢問題,接下來就跟大家分享下如何將base64圖片進行壓縮。先跟大家展示下最終實現的效果:
本篇文章主要講解剪切板圖片壓縮的實現,效果圖中如何將剪切板的圖片插入可編輯div以及如何發送,請移步我的另一篇文章:Vue解析剪切板圖片并實現發送功能
const that=this;
document.body.addEventListener('paste', function (event) {
that.$fullScreenLoading.show("讀取圖片中");
// 獲取當前輸入框內的文字
const oldText=that.$refs.msgInputContainer.textContent;
// 讀取圖片
let items=event.clipboardData && event.clipboardData.items;
let file=null;
if (items && items.length) {
// 檢索剪切板items
for (let i=0; i < items.length; i++) {
if (items[i].type.indexOf('image') !==-1) {
file=items[i].getAsFile();
break;
}
}
}
// 預覽圖片
const reader=new FileReader();
reader.onload=function(event) {
// 圖片內容
const imgContent=event.target.result;
// 創建img標簽
let img=document.createElement('img');//創建一個img
// 獲取當前base64圖片信息,計算當前圖片寬高以及壓縮比例
let imgObj=new Image();
let imgWidth="";
let imgHeight="";
let scale=1;
imgObj.src=imgContent;
imgObj.onload=function() {
// 計算img寬高
if(this.width<400){
imgWidth=this.width;
imgHeight=this.height;
}else{
// 輸入框圖片顯示縮小10倍
imgWidth=this.width/10;
imgHeight=this.height/10;
// 圖片寬度大于1920,圖片壓縮5倍
if(this.width>1920){
// 真實比例縮小5倍
scale=5;
}
}
// 設置可編輯div中圖片寬高
img.width=imgWidth;
img.height=imgHeight;
// 壓縮圖片,渲染頁面
that.compressPic(imgContent,scale,function (newBlob,newBase) {
// 刪除可編輯div中的圖片名稱
that.$refs.msgInputContainer.textContent=oldText;
img.src=newBase; //設置鏈接
// 圖片渲染
that.$refs.msgInputContainer.append(img);
that.$fullScreenLoading.hide();
});
};
};
reader.readAsDataURL(file);
});
// 參數: base64地址,壓縮比例,回調函數(返回壓縮后圖片的blob和base64)
compressPic:function(base64, scale, callback){
const that=this;
let _img=new Image();
_img.src=base64;
_img.onload=function() {
let _canvas=document.createElement("canvas");
let w=this.width / scale;
let h=this.height / scale;
_canvas.setAttribute("width", w);
_canvas.setAttribute("height", h);
_canvas.getContext("2d").drawImage(this, 0, 0, w, h);
let base64=_canvas.toDataURL("image/jpeg");
// 當canvas對象的原型中沒有toBlob方法的時候,手動添加該方法
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function (callback, type, quality) {
let binStr=atob(this.toDataURL(type, quality).split(',')[1]),
len=binStr.length,
arr=new Uint8Array(len);
for (let i=0; i < len; i++) {
arr[i]=binStr.charCodeAt(i);
}
callback(new Blob([arr], {type: type || 'image/png'}));
}
});
}else{
_canvas.toBlob(function(blob) {
if(blob.size > 1024*1024){
that.compressPic(base64, scale, callback);
}else{
callback(blob, base64);
}
}, "image/jpeg");
}
}
}
github: https://github.com/likaia/chat-system/blob/master/src/components/message-display.vue
作者:神奇的程序員K
轉發鏈接:https://mp.weixin.qq.com/s/hADXM37cactAGFf2vduQJw
實現 HTML 壓縮,可以使用 JavaScript 中的正則表達式來去除 HTML 中的空格和注釋。以下是一個簡單的 HTML 壓縮函數:
function compressHTML(html) {
// 去除注釋
html=html.replace(/<!--[\s\S]*?-->/g, "");
// 去除多余空白
html=html.replace(/\s+/g, " ");
// 去除標簽之間空格
html=html.replace(/>\s+</g, "><");
return html.trim();
}
該函數首先使用正則表達式去除 HTML 中的注釋。然后,它使用另一個正則表達式去除 HTML 中的多余空格。最后,它使用另一個正則表達式去除標簽之間的空格。
為了測試該函數,您可以創建一個 HTML 文件,并在其中添加一些冗余的空格和注釋。例如:
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<!-- This is a comment -->
<h1> Welcome to my website! </h1>
<p> This is some text. </p>
</body>
</html>
然后,您可以在Node.JS中使用以下代碼將 HTML 文件加載為字符串并壓縮它:
// 加載 HTML 文件
const fs=require("fs");
const html=fs.readFileSync("index.html", "utf8");
// 壓縮 HTML
const compressedHtml=compressHTML(html);
console.log(compressedHtml);
輸出是一個壓縮后的 HTML 字符串,其中不包含注釋或冗余空格。
或者直接在IE中測試,代碼如下:
function compressHTML(html) {
// 去除注釋
html=html.replace(/<!--[\s\S]*?-->/g, "");
// 去除多余空白
html=html.replace(/\s+/g, " ");
// 去除標簽之間空格
html=html.replace(/>\s+</g, "><");
return html.trim();
}
var html=`
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<!-- This is a comment -->
<h1> Welcome to my website! </h1>
<p> This is some text. </p>
</body>
</html>
`;
console.log(compressHTML(html));
運行效果:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。