前幾天你們都在朋友圈@微信官方,求賜一面國旗,沒有獲得微信官方的小盆友們,有沒有很失落呀~心血來潮的我,決定用js來寫一個給頭像加國旗的功能,而後我就送了本身一面國旗,事實證實,想要的東西仍是隻能靠本身的雙手去創造。哈哈哈,這雞湯灑的觸不及防~,迴歸正題,下面就一塊兒來看看我是怎麼實現的吧~~css
其實給頭像加國旗的實現原理很簡單,就是拿到你的圖片資源(就是你的頭像),用canvas繪製該圖片,而後在圖片的右下角再繪製一個小國旗,這樣基礎的功能就實現了。下面咱們來一步步實現給頭像加國旗的功能。源碼地址html
應評論區需求,我這裏貼一個代碼處理後的頭像的效果圖(圖像是有一個白色圓角邊框的,可能會與博客的白色背景重疊,審美不太好,湊合看哈~).vue
我把我開發該功能的整個思考流程梳理以下:web
html代碼:canvas
<div>
<div><button class="input-container">
上傳頭像
<input accept="image/gif,image/jpeg,image/png"
class="file-input" id="fileInput" type="file" />
</button>
<button class="save-btn" onclick="downLoad()">保存圖片</button>
</div>
<canvas id="canvas" class="canvas"></canvas>
</div>
複製代碼
js代碼:api
// 這一過程是定義一些可配置的參數,以便根據須要作修改
const options = {
avatarImgX: 0, // 頭像開始剪切的x座標
avatarImgY: 0, // 頭像開始剪切的y座標
avatarX: 10, // 畫布上頭像開始繪製的x座標
avatarY: 10, // 畫布上頭像開始繪製的y座標
avatarWidth: 200, // 畫布上要繪製的頭像的寬度
avatarHeight: 200, // 畫布上要繪製的頭像的寬度
radius: 5, // 頭像的圓角半徑
guoqiRadius: 3, // 國旗的圓角半徑
guoqiX: 0, // 國旗開始剪切的x座標
guoqiY: 0, // 國旗開始剪切的y座標
guoqiWidth: 50, // 畫布上要繪製的國旗的寬度
guoqiHeight: 33, // 畫布上要繪製的國旗的寬度
// 存放的是國旗的base64編碼,源碼地址點開可查看完整的
guoqi: ""
}
// 定義一些常量
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const inputUpload = document.getElementById('fileInput');
// 定義input的onchange事件,經過fileReader拿到圖片的base64編碼
window.onload = function() {
inputUpload.onchange = function uploadAvatar() {
const file = this.files[0];
if(file) {
// 讀取圖片資源
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = function () {
// 爲了保證圖片不失真,畫布的高度是根據上傳頭像的寬高比
// 和options中定義好的繪製寬度計算出來的,
// 因此須要把國旗的繪製放在頭像繪製完成後的回調函數中執行。
function cb() {
const param = {
sx: options.guoqiX,
sy: options.guoqiY,
x: canvas.width - options.guoqiWidth - options.radius * 2,
y: canvas.height - options.guoqiHeight - options.radius * 2,
width: options.guoqiWidth,
height: options.guoqiHeight
}
// 調用繪製圖片的工具函數,傳入所需參數
drawAvatar(options.guoqi,cb, param.sx,param.sy,param.x,param.y,
param.width,param.height, options.guoqiRadius)
}
// 調用繪製圖片的工具函數,傳入所需參數
drawAvatar(this.result,cb,options.avatarImgX,options.avatarImgY,
options.avatarX,options.avatarY,options.avatarWidth,
options.avatarHeight);
}
}
};
}
// 繪製圖片
function drawAvatar(imgSrc,cb, ...args) {
let img = new Image();
img.src = imgSrc;
// 不少狀況下的圖片繪製的邏輯都會寫在onload裏面
// 是由於一般的圖片資源都是網絡請求獲取的,
// 咱們會要保證在資源加載完成後才能正確完成繪製。
// 我這裏是直接使用的圖片的base64編碼,
// 繪製圖片的邏輯也可不寫在onload函數裏
img.onload = function () {
args.splice(2, 0, img.width,img.height);
// 繪製的是頭像,則計算並設置畫布的高度,清空input的值
if(args[6] === options.avatarWidth) {
args[7] = parseInt(args[6] / (img.width / img.height));
canvas.width = args[6] + 20;
canvas.height = args[7] + 20;
inputUpload.value = '';
}
const r = args[8] || options.radius, x = args[4],
y = args[5], w = args[6], h=args[7];
ctx.drawImage(img, ...args);
// 繪製圖像的圓角的函數
drawRadius(x, y, w, h, r);
// 繪製國旗
typeof cb === 'function' && cb();
}
}
// 繪製圖片圓角
function drawRadius(x,y,w,h,r) {
ctx.beginPath();
ctx.strokeStyle='white';
ctx.fillStyle ='white'
ctx.lineWidth= r;
console.log(ctx.lineWidth);
ctx.moveTo(x+r, y);
ctx.arcTo(x+w, y, x+w, y+h, r);
ctx.arcTo(x+w, y+h, x, y+h, r);
ctx.arcTo(x, y+h, x, y, r);
ctx.arcTo(x, y, x+w, y, r);
ctx.stroke();
ctx.closePath();
}
// 圖片下載,下載的原理就是建立a標籤,指向圖片的下載地址,
// 模擬觸發a標籤的點擊完成下載
function downLoad(url){
let oA = document.createElement("a");
oA.download = 'avatar';
// 經過canvas.toDataURL方法生成圖片的下載地址
oA.href = saveAsPNG();
document.body.appendChild(oA);
oA.click();
oA.remove(); // 下載以後把建立的元素刪除
}
// 保存成png格式的圖片,你這裏能夠選擇其餘格式的圖片保存
function saveAsPNG() {
return canvas.toDataURL("image/png");
}
複製代碼
css代碼:微信
.save-btn, .input-container{
border: none;
box-shadow: none;
width: 150px;
padding: 10px;
margin-bottom: 20px;
margin-right: 20px;
text-align: center;
color: #fff;
background-color: blue;
border-radius: 5px;
cursor: pointer;
}
.save-btn {
background-color: #67c23a;
}
.input-container {
background-color: #409eff;
position: relative;
.file-input {
cursor: pointer;
position: absolute;
display: inline-block;
width: 100%;
height: 100%;
top: 0;
left: 0;
opacity: 0;
}
}
複製代碼
到這兒,給頭像添加國旗的功能就完成了,不知道大家有沒有學會呢?代碼寫到這裏其實還有不少待完善的地方,例如國旗的素材,我選的這個國旗圖片很規矩,沒有太多的設計感,還能夠利用canvas的其餘api,讓生成的圖片更有趣,更好看,更天然。我今天的分享就到這兒了,有什麼疑惑或者建議可評論區留言給我奧~~,最後,祝咱們的祖國生日快樂~,國泰民安,繁榮富強,這盛世,如你所願!網絡