迎國慶 | 頭像大作戰!

2021-02-15 創智俱樂部ISA
<!DOCTYPE html><html> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, initial-scale=1.0">     <meta http-equiv="X-UA-Compatible" content="ie=edge">     <title>頭像大作戰</title>     <style>              </style>
</head> <body> <header><h1>頭像大作戰</h1></header> <article> <section> </section> </article> <footer> <script> </script> </footer> </body></html>

然後,我們要做到可以預覽用戶選擇的頭像,我們先來給網頁加上一個文件選擇控制項,和圖片標籤,標籤上加 上 id,以便後面通過 Javascript 控制。

<p>          <input type="file" name="" id="upload" accept="image/*"> </p> <p id="avatar">     <img src="" alt="" id="avatar_img"> </p>

接著,我們來寫預覽圖片的代碼,藉助於 URL.createObjectURL 來加載圖片。

function loadImage(){        var imgUrl = window.URL.createObjectURL(document.getElementById('upload').files[0]);   document.getElementById('avatar_img').src = imgUrl;}

當用戶選擇圖片時,就要載入圖片,所以我們把 loadImage 綁定在 upload 的 onchange 事件裡面:

<input type="file" name="" id="upload" accept="image/*" onchange="loadImage()">

接著,我們要頭像疊加的效果,我已經事先從騰訊的網站把素材爬下來了。可以在這兒下載:https://github.com/szisa/avatar_maker/tree/master/img

我們把圖片都存放在 img 目錄。總共 4 種外框,分別命名為 head0.png, head1.png, head2.png, head3.png,另外,還抓多一張 bg.png 做背景。

我們先用 head0.png 做樣式。在頭像預覽的地方加入一個 img 標籤,用來顯示外框圖片。

<p id="avatar">     <img src="./img/head0.png" alt="0" id="avatar_template">      <img src="" alt="" id="avatar_img"></p>

這不是我們要的,外框太大,而且也沒重疊在一起,這時就要靠 CSS 大法來幫忙了。在 style 加入下面代碼:

body {          background: #000 url(./img/bg.png) no-repeat center;          text-align: center;  } #avatar {            width: 300px;      height: 300px;            position: relative;            margin: auto;            overflow: hidden;  }#avatar img {          width: 100%; } #avatar_template {          position: absolute;     top: 0;     right: 0; }

ok,到這裡來有幾個知識點重點講解一下,只想趕快做出來的可以略過這部分。 

 margin: auto;

HTML 元素中,按照默認樣式,可以被分為內聯元素和塊級元素。內聯元素可以被 text-align 居 中,而塊級元素,則要靠外邊距的的補齊來實現左右居中。當設置塊級元素的 margin 為 auto 時,瀏覽器就會自動計算左右外邊距,將剩餘空間平分到左右外邊 距,這樣就實現了左右居中。 

 position: absolute;

為了實現把外框覆蓋在頭像上,我們需要讓外框圖片脫離正常文檔流,而絕對定位可以幫我們實現這一 點。絕對定位的定位原點則是通過包含塊來決定的。我們需要讓外框圖片精準對齊 #avatar 的左上角,那麼 就需要讓 #avatar 成為絕對定位的包含塊,而只要給 #avatar 設置 position 且值不等於 static,他 就會自動成為包含塊。當如果設置 fixed 或 absolute,則會讓標籤脫離文檔流,影響樣式,因此,我 們就給 #avatar 設置了 position: relative。

現在就要來做保存圖片的代碼了,我們沒辦法直接把標籤變成圖片。但是,我們可以通過 canvas,依次繪製兩張圖片,就可以實現圖片的疊加了!

首先,我們要給 HTML 裡加入一個 canvas 標籤:

<p>     <canvas width="300" height="300" id="cvs"></canvas></p>

然後,就要開始用圖片繪製了。定義一個函數 drawImage,傳入圖片地址,繪製圖片到畫布:

function drawImage(img) {     // 取得 Canvas     var cvs = document.getElementById('cvs');      var size = 300;     // 設定 canvas 寬高     cvs.width = size;     cvs.height = size;     // 取得 2d 畫布     var ctx = cvs.getContext('2d');          // 新建圖片對象,加載圖片          var image = new Image;          image.src = img;          image.onload = function() {                   // 加載完成後繪製 image 到(0,0)坐標,長寬重設為 size                   ctx.drawImage(image, 0, 0, size, size);           }} 

然後,當用戶選擇圖片後,我們就要把他畫上去,所以在 loadImage 最後要加上 drawImage :

function loadImage() {     var imgUrl =     window.URL.createObjectURL(document.getElementById('upload').files[0]);     document.getElementById('avatar_img').src = imgUrl;          drawImage(imgUrl)} 

接著,我們還得把外框繪製上去,因為後面還要提供更換外框的功能,把外框的地址作為參數傳入到 drawImage :

function drawImage(img, frame) {     var cvs = document.getElementById('cvs');     var size = 300;     cvs.width = size;     cvs.height = size;     var ctx = cvs.getContext('2d');     var image = new Image;      image.src = img;     image.onload = function() {         ctx.drawImage(image, 0, 0, size, size);                  image = new Image;         image.src = frame;         image.onload = function() {                              ctx.drawImage(image, 0, 0, size, size);          }      }} 

function loadImage() {     // 載入圖片生成 blob 連結     var imgUrl = window.URL.createObjectURL(document.getElementById('upload').files[0]);     document.getElementById('avatar_img').src = imgUrl;     // 再傳入 avatar_template 的圖片地址     drawImage(imgUrl, document.getElementById('avatar_template').src)}

這個 canvas 只是用來保存,那麼可以把他隱藏起來,加上 CSS 樣式 style="display:none" 在 canvas 上。

接著,我們來做保存的部分。canvas 有一個方法 toDataURL 用來將內容生成成圖片的 DataURL。那麼我們只 要把這個 DataURL 作為 a 標籤的地址,利用 a 標籤的 download 屬性,模擬點擊即可實現圖片下載了。具體代碼:

function downloadImage() {     var canvas = document.getElementById('cvs');           var image = canvas.toDataURL("image/png")         var save_link = document.createElement('a');    save_link.href = image;    save_link.download ='avatar.png';            var clickevent = document.createEvent('MouseEvents');    clickevent.initEvent('click', true, false);        save_link.dispatchEvent(clickevent); }

我們創建一個下載按鈕用來下載圖片,並把 downloadImage 綁定在按鈕上

<p>     <button id="download" onclick="downloadImage()">下載</button></p>

選擇頭像,點擊下載,瀏覽器就會下載圖片了,最後生成的圖片:

你學會了嗎?你滿足了嗎?不!我不滿足,我還要做到可以選擇不同的外框。那麼,讓我們繼續~

我們可以通過兩個按鈕,前後切換頭像邊框。那麼,先加上兩個按鈕,就放在下載按鈕的左右兩側:

<button id="prev">上一個</button><button id="download" onclick="downloadImage()">下載</button><button id="next">下一個</button>

上下切換邊框很簡單,只要計算邊框的地址,然後更新 avatar_template 的圖片地址就行了。為了節省解析 當前切換到哪張邊框的功夫,我們把當前邊框的 Index 存放在圖片的 alt 屬性。

function prevTemplate() {          var current = parseInt(document.getElementById('avatar_template').alt);          current = (current - 1 + 4) % 4;      document.getElementById('avatar_template').src = 'img/head' + current + '.png';     document.getElementById('avatar_template').alt = current;          loadImage();} 
function nextTemplate() { var current = parseInt(document.getElementById('avatar_template').alt); current = (current + 1) % 4; document.getElementById('avatar_template').src = 'img/head' + current + '.png'; document.getElementById('avatar_template').alt = current; loadImage();}

接著,把函數綁定到按鈕的 onclick 事件上,就大功告成了。

<button id="prev" onclick="prevTemplate()">上一個</button><button id="download" onclick="downloadImage()">下載</button><button id="next" onclick="nextTemplate()">下一個</button>

最後成品(http://avatar.m.sxisa.com/sample.html):

完整代碼可以來這看哦:https://github.com/szisa/avatar_maker/blob/master/sample.html

認真跟著做到這一步的同學們都很棒哦~細心的同學可能會發現,預覽的部分似乎不要也可以,直接使用 canvas 作為預覽不就可以了?事實上,確實是這樣的。不過,加多了一個 HTML 的預覽,是為了別的頭像生成 器去特地保留的!

10月來了,12月還會遠嗎~如果把邊框換成聖誕帽,是不是就可以用來生成聖誕帽頭像了呢!但是聖誕 帽可不會固定在一個位置,這就需要給用戶自行調整的機會,所以,我們就需要通過 HTML 預覽的部分提供給 用戶交互,因為 canvas 幾乎沒辦法做交互。那麼到底要怎麼實現呢?且聽下回分解!

(點擊 閱讀原文 查看原始碼,給個 star 吧~👇)

相關焦點

  • 你的頭像可能違法?!即將上線的爆款頭像,快來搶先定製!
    給我一面國旗@微信官方其實頭像右下角的小國旗並不是朋友圈「許願」得來的(也不知道是誰最開始發朋友圈「騙人」的……),而是騰訊推出的「迎國慶 換新顏」活動。 右下角除了飄揚的紅旗外,還可選擇代表70周年的金色「70」字樣、喜慶的「國慶快樂!」橫幅、和圓形五星紅旗logo。
  • 升旗儀式 | 巴州金富舉行「迎國慶」升國旗儀式
    10月1日,巴州金富特種紗業有限公司(以下簡稱「巴州金富」)在辦公區前小廣場舉行「迎國慶」升國旗儀式,巴州金富幹部員工120餘人參加儀式。儀式開始,在雄壯的《義勇軍進行曲》中,著裝整齊的巴州金富幹部員工,面對冉冉升起的五星紅旗,高唱國歌,表達對偉大祖國的無限熱愛之情。
  • 迎國慶,CUBE車友長街行
    29日下午,CUBE北京豐臺專賣店的高總,為迎國慶組織車友在9月30日晚上夜騎長安街,海報做的也是超級贊!於是當天電話裡跟高總簡單溝通了一下,約定好時間地點,我們東西兩路同出動,用車友自己的方式迎接國慶。昨天下午5點多,董哥、昆哥、Titans等車友陸續到公司匯合。
  • 慶祝建國70周年,田野鼓校「百鼓齊鳴」迎國慶
    2019年10月1日,正值建國70周年到來之際,為歌頌建國70年來的偉大成就,激發廣大群眾和學生熱愛祖國、熱愛社會主義的高尚情感,增強學生的歷史責任感、弘揚民族精神,陶冶群眾藝術情操和豐富業餘生活,展示青春活力,營造朝氣蓬勃、積極向上的群眾文化,擬舉辦慶祝建國70周年「百鼓齊鳴」迎國慶的大型文化活動
  • 個舊將舉辦迎國慶可樂球展演?很精彩有木有!
    為進一步掀起個舊全民健身活動熱潮,在國慶節即將到來之際,箇舊市將舉辦2016年迎國慶中老年人可樂球展演活動,這項活動將打造成箇舊市全民健身的又一個活動品牌。詩意個舊·人文錫都——2016年箇舊市迎國慶可樂球展演活動在國慶節來臨之際,通過舉辦此次活動,營造濃厚的節日氛圍,全面展示我市全民健身活動的蓬勃發展,增強全民的體育健身意識,在全社會形成崇尚健身、參與健身,追求健康文明生活方式的良好氛圍。
  • 千餘人快閃、唱響愛國歌曲……桓臺人這樣迎國慶
    1949-2019歌聲嘹亮、喜迎國慶!9月24日,885水世界、惠仟佳購物廣場分別開展迎國慶快閃活動,向祖國獻上最真摯的祝福,現場盛況先睹為快!歌聲嘹亮 喜迎國慶「我和我的祖國,一刻也不能分割……」9月24日,在國慶節來臨之際,885水世界組織全體工作人員齊唱《我和我的祖國》等歌曲,以獨特的方式慶祝新中國成立70周年,營造節日的喜慶氣氛,表達愛國之情。
  • 迎國慶過中秋丨波拉哩大狂歡 海量福利來襲
    活動時間:2017年10月1日-2017年10月8日活動內容:完成迎國慶過中秋系列活動,可獲得「迎國慶過中秋
  • 迎國慶,品海鮮,愜意在海濱
    文/馮春燕圖/馮春燕 2017年9月28-29日,陽江核電基地海濱花園餐廳舉辦了第八屆「迎國慶,品海鮮
  • 賀中秋迎國慶||「新徵程 中國節 展形象」中國當代書畫家網絡展
    賀中秋迎國慶||「新徵程 中國節 展形象」中國當代書畫家網絡展值此賀中秋迎國慶的大好日子裡,為深入貫徹落實習近平總書記講話和黨的十九大精神,切實做到「兩個維護」、增強「四個意識」、堅定「四個自信」,自覺承擔起「舉旗幟、聚民心、育新人、興文化、展形象」的使命任務,為我市創建全國衛生城市和省文明城市營造濃厚氛圍。
  • 罕見電視臺直播求婚大作戰(多圖!超浪漫!)
    昨天晚上2.14情人節,《今日最新聞》破天荒首次進行直播求婚大作戰
  • 達成7個國慶小目標,能拿共嬋娟坐騎了?
    國慶有什麼小目標?1.我要去的地方,不是人從眾人從眾?2.我能廋,你自重?
  • 畫說垃圾分類,步小師生主題繪畫迎國慶!
    9月25日上午為讓綠色分類烙印在同學們心間我校組織了超1000名學生參與「畫說垃圾分類——迎國慶千人主題繪畫活動」
  • 「歡度中秋迎國慶,中醫為媒話養生」聯歡活動成功舉辦
    2020年9月28日下午,南陽市南都中醫館內熱鬧非凡,空氣中瀰漫著絲絲艾香,「歡度中秋迎國慶,中醫為媒話養生」聯歡活動在這裡隆重舉行,共慶祖國華誕,共話健康養生。
  • 頭像更新
    在咱微信裡搜頭像的方法,往下看 ↓↓↓↓(有黃色方框標題的地方)逮蝦戶組合頭像奉上,國慶已經過了,用手指掰著數了距離下個假期還有多久,剔除了不放假的雙11和聖誕節,距離下次放假還有兩個多月後續我們也會把前面沒補的壁紙頭像都補齊哈,提前祝大家元旦快樂!
  • 國慶配鏡大放送——與您共迎盛世華誕!價值428元眼鏡免費送!!!
    亨得利眼鏡將與您共迎70華誕!亨得利眼鏡國慶狂歡周活動,為您準備了最強國慶福利禮讚祖國70華誕10月1日-10月7日轉發活動內容到朋友圈併集27個贊即可免費領取(198元鏡架+230元1.56防輻射鏡片)眼鏡一副光度範圍:近視:0.00~-6.00             散光:0.00~-2.00領取時僅收取綜合驗配費
  • 假日我在崗|伴著歌聲與歡笑的國慶特別之旅
    K508次列車"迎國慶 慶祝改革開改 40 周年 "列車文藝匯演在貴陽客運段北京二隊 K508 次列車上,列車員們精心準備了一臺 " 迎國慶 慶祝改革開改 40 周年 " 的車廂文藝匯演。在黃曼莉13年的列車乘務生涯中,數不清有多少個生日在工作崗位上渡過,每次都和同事們一起,在國慶小長假的繁忙乘務工作中服務旅客。在重慶客運段幾千名一線乘務人員中,每天都有黃曼莉這樣的「壽星」在崗值乘堅守在列車上,她們迎來送往,為旅途中歸心似箭的人們最溫馨的陪伴、最貼心的服務,在崗位上履行自己平凡的職責,奉獻青春的光和熱。
  • 【陽光城陽 文明實踐】大北曲西社區舉辦「陽光春和 和諧鄰裡」迎國慶歌詠比賽
    2019年9月8日,為慶祝中華人民共和國成立70周年,展示社區居民的新時代精神風貌,大北曲西社區舉行了「陽光春和 和諧鄰裡」迎國慶歌詠比賽。  社區居民按照社區網格劃分組成13支代表隊,社區居民紛紛趕來為參賽選手加油打氣。
  • 傳統文化公益行丨《慶祝祖國70華誕》迎國慶文藝匯演
    28日晚上,在寧晉謙德學校舉行了「慶祝祖國70華誕」迎國慶文藝匯演。在場的主要嘉賓有原中國作家協會書記處書記兼《文藝報》總編輯,中華文化促進會主席團諮詢委員金堅範先生。
  • 新時代 新青年 新作為 「亞特爾杯」坊子區迎國慶全民健身跑活動
    為迎接「十一」國慶節的到來,加快建設「四個城市」,打造「活力坊子」,9月29日,「新時代·新青年·新作為『亞特爾』杯」迎國慶全民健身跑活動在亞特爾未來廣場舉行
  • 日本電影:戀愛中毒大作戰
    預 告 片 欣 賞: __________  影 片 概 況: __________又名:腦內中毒大作戰分類:喜劇片長:120分鐘導演:佐藤祐市主演:真木陽子 西島秀俊 古川雄輝 成河 吉田羊  劇 情 介 紹: __________        在這部戀愛中毒大作戰中