canvas 入門實戰--邀請卡生成與下載

2021-03-02 SegmentFault
1.前言

寫了很多的javascript和css3的文章,是時候寫一篇canvas的了。canvas是html5提供的一個新的功能!至於作用,就是一個畫布。然後畫筆就是javascript。canvas的用途非常的廣,特別是html5遊戲以及數據可視化這兩個方面。現在canvas給我的感覺就和css3一樣,可以不用太厲害,但是必須要會基礎的用法。但是以後對canvas的需求,肯定會越來越大。所以canvas很值得學習,而且學好canvas,就是很好的一個加分項。對於這篇文章,我也是以canvas初學者的角度寫的,會有很多改善的地方。如果大家覺得我有什麼可以改善的,或者建議,歡迎指點迷津!代碼已上傳github,需要的歡迎star(downloadImg)。

大家看這篇文章之前,要了解javascript的一些基礎,也要看著了解一些canvas的api(canvas-MSN教程,canvas菜鳥教程)

2.邀請卡實例

邀請卡自動生成這個會有的,畢竟有時候,很多邀請卡都是一樣的,就是被邀請的人不一樣而已,也就是說,整個邀請卡,就是一個名字不一樣,那麼下面。就寫一套代碼,根據名字生成邀請卡!

2-1.運行效果

html代碼:

   <html>

   <head>

       <meta charset="utf-8">

       <title>下載圖片</title>

       <style>

           .set-option {

               float: left;

               width: 400px;

           }

           .set-option .text {

               width: 200px;

               height: 40px;

               padding-left: 10px;

               border-radius: 4px;

               border: 1px solid #ccc;

           }

           .set-option td {

               padding: 10px 0;

           }

           .set-option td:first-child {

               text-align: right;

               padding-right: 10px;

           }

           .set-option p {

               margin: 0;

               line-height: 16px;

           }

           .check-box {

               width: 16px;

               height: 16px;

               margin: 0;

               vertical-align: top;

           }

           button {

               width: 200px;

               height: 50px;

               border: none;

               color: #fff;

               font-size: 16px;

               cursor: pointer;

               display: block;

               margin: 10px auto;

           }

           button:hover {

               opacity: .9;

           }

           .btn-all {

               background: #f90;

           }

           .btn-save {

               background: #09f;

           }

           .btn-download {

               background: #4CAF50;

           }

       </style>

   </head>

   <body>

   <div>

       <div class="set-option">

           <table>

               <tr>

                   <td>畫布尺寸</td>

                   <td><input type="text" class="text" id="size"/></td>

               </tr>

               <tr>

                   <td>背景圖片</td>

                   <td><input type="file" id="file"/></td>

               </tr>

               <tr>

                   <td>用戶名</td>

                   <td>

                       <input type="text" class="text" id="user-name"/>

                   </td>

               </tr>

               <tr>

                   <td>用戶名x坐標</td>

                   <td>

                       <input type="number" class="text" id="text-option-x"/></br>

                       <p><input type="checkbox" class="check-box" value="1" id="is-center-x">居中顯示</p>

                   </td>

               </tr>

               <tr>

                   <td>用戶名y坐標</td>

                   <td>

                       <input type="number" class="text" id="text-option-y"/></br>

                       <p><input type="checkbox" class="check-box" value="1" id="is-center-y">居中顯示</p>

                   </td>

               </tr>

               <tr>

                   <td>用戶名字體大小</td>

                   <td><input type="number" class="text" id="text-size"/></td>

               </tr>

               <tr>

                   <td>文字顏色</td>

                   <td><input type="text" class="text" id="text-color"/></td>

               </tr>

               <tr>

                   <td>圖片類型</td>

                   <td>

                       <select type="text" class="text" id="img-type">

                           <option value="jpg">jpg</option>

                           <option value="png">png</option>

                       </select>

                   </td>

               </tr>

           </table>

           <button id="save-image" class="btn-save">效果預覽</button>

           <button id="download-img" class="btn-download">下載當前圖片</button>

           <button id="download-all" class="btn-all">批量導出</button>

       </div>

       <div class="show-canvas">

           <canvas width=200 height=200 id="thecanvas"></canvas>

       </div>

   </div>

   </body>

   </html>

效果如圖,那麼大家細想一下,關於一張邀請卡,有什麼東西是需要改變的!看到上圖相比不難發現!有如下需要改變的屬性:圖片的大小,圖片,用戶名,用戶名的坐標(x,y,x軸是否居中,y軸是否居中),用戶名字體的大小,用戶名字體的顏色,以及下載圖片的類型。

這樣就得到了如下的參數(大家看到有些參數是有值的,可以想成默認值就行了)

   var option = {

       img: '111.jpg',

       width: 500,

       height: 350,

       fontSize: "20px Microsoft YaHei",

       color: "black",

       text: '守候',

       imgType: 'jpg',

       x: 30,

       y: 30,

       xCenter: false,

       yCenter: false,

   };

2-2.步驟1.初步效果

根據上面的參數,先初步畫一個效果,代碼基本都是一個寫法,沒什麼技巧。

   //畫圖

   function draw(obj) {

       var canvas = document.getElementById("thecanvas");

       //畫布大小

       canvas.width = obj.width;

       canvas.height = obj.height;

       //設置圖片

       var img = new Image();

       img.src = obj.img;

       var ctx = canvas.getContext("2d");

       //設置字體的坐標

       var _x = obj.x, _y = obj.y;

       //是否居中顯示

       if (obj.xCenter) {

           _x = obj.width / 2;

       }

       if (obj.yCenter) {

           _y = obj.height / 2;

       }

       //圖片加載後

       img.onload = function () {

           //先畫圖片

           ctx.drawImage(img, 0, 0);

           //設置文字的大小

           ctx.font = obj.fontSize;

           //設置文字的顏色

           ctx.fillStyle = obj.color;

           //設置文字坐標

           if (obj.xCenter) {

               ctx.textAlign = "center";

           }

           //畫文字

           ctx.fillText(obj.text, _x, _y);

       };

   }

   window.onload = function () {

       draw(option);

   }

 

2.動態改變參數

看到圖已經畫好了,工作其實已經完成一半了!

下面就是動態改變參數!這一步其實很簡單。

首先,改變畫布的尺寸

   //畫布尺寸

   //獲取按鈕

   var size = document.getElementById("size");

   size.addEventListener("blur", function () {

       //根據空格,區分高寬

       var _width = parseInt(size.value.replace(/(^\s*)|(\s*$)/g, "").split(/\s+/)[0]),

           _height = parseInt(size.value.replace(/(^\s*)|(\s*$)/g, "").split(/\s+/)[1]);

       //把參數的width和height改掉

       option.width = _width || 100;

       option.height = _height || 100;

       //重新畫圖

       draw(option);

   });

上面代碼設置了,只要輸入框失去了焦點,就會改變畫布的大小,下面來運行下,看下效果(gif圖差強人意,大家看懂就好)

canvas沒有層級的說法,只要改canvas,都要重繪。哪怕就是一個字移動一個像素。

做好了這個,下面做選擇圖片的功能!

   //選擇圖片

   //獲取圖片控制項

   var file = document.getElementById("file"), imagesFile, imageData;

   file.addEventListener('change', function (e) {

       //獲取圖片

       imagesFile = e.target.files[0];

       //把圖片轉base64

       var reader = new FileReader();

       reader.readAsDataURL(imagesFile);

       //圖片加載後

       reader.onload = function (e) {

           //設置option的img屬性,再衝洗年繪製

           imageData = this.result;

           option.img = imageData;

           draw(option);

       }

   });

下面開始改文字,用戶名這個有點不一樣,我以空格分割。如果輸入多個用戶名,以第一個用戶名重繪。下面代碼,注釋就不寫了,還是和上面的邏輯一樣!

   //用戶名

   var userName = document.getElementById("user-name");

   userName.addEventListener("blur", function () {

       var _text = userName.value.replace(/(^\s*)|(\s*$)/g, "").split(/\s+/);

       option.text = _text[0];

       draw(option);

   });

下面開始用戶名的坐標,代碼方面,也是改option的相關屬性。

       optionXCenter.addEventListener("change", function () {

           if (optionXCenter.checked) {

               option.xCenter = true;

           }

           else {

               option.xCenter = false;

               option.x = parseInt(optionX.value);

           }

           draw(option);

       });

       //縱坐標

       var optionY = document.getElementById("text-option-y");

       optionY.value = option.y;

       var optionYCenter = document.getElementById("is-center-y");

       optionY.addEventListener("input", function () {

           if (optionYCenter.checked) {

               option.yCenter = true;

           }

           else {

               option.yCenter = false;

               option.y = parseInt(optionY.value);

           }

           draw(option);

       });

       //是否垂直居中顯示

       optionYCenter.addEventListener("change", function () {

           if (optionYCenter.checked) {

               option.yCenter = true;

           }

           else {

               option.yCenter = false;

               option.y = parseInt(optionY.value);

           }

           draw(option);

       });

是否水平居中顯示:

其他的屬性,字體大小和顏色,基本是一樣的代碼,運行的效果圖我不放了!

   //字體顏色

   var textColor = document.getElementById("text-color");

   textColor.addEventListener("blur", function () {

       textColor.value === "" ? option.color = "#fff" : option.color = '#' + textColor.value;

       draw(option);

   });

   //字體大小

   var textSize = document.getElementById("text-size");

   textSize.addEventListener("input", function () {

       textSize.value === "" ? option.fontSize = '20px Microsoft YaHei' : option.fontSize = textSize.value + 'px Microsoft YaHei';

       draw(option);

   });

3.按鈕操作

效果預覽

就是預覽當前canvas的一個效果,這個就很簡單了,就是新開一個窗口,然後把圖片寫進去而已。

   //預覽圖片

   function saveImageInfo() {

       var mycanvas = document.getElementById("thecanvas");

       //生成圖片

       var image = mycanvas.toDataURL("image/png");

       var w = window.open('about:blank', 'image from canvas');

       //把圖片新進新的窗口

       w.document.write("<img src='" + image + "' alt='from canvas'/>");

   }

   var saveButton = document.getElementById("save-image");

   saveButton.addEventListener('click', saveImageInfo);

下載當前圖片

下載圖片這個,基本也是寫法的,都是些記憶的東西。

   //圖片類型

   var imgType = document.getElementById("img-type");

   imgType.addEventListener("change",function () {

       option.imgType=this.value;

   });

   //下載圖片

   function downloadImg(fileName) {

       //獲取canvas

       var myCanvas = document.getElementById("thecanvas");

       //設置圖片類型

       var image = myCanvas.toDataURL("image/" + option.imgType).replace("image/" + option.imgType, "image/octet-stream");

       var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');

       save_link.href = image;

       //設置下載圖片的名稱

       save_link.download = fileName + '.' + option.imgType;

       //下載圖片

       var event = document.createEvent('MouseEvents');

       event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);

       save_link.dispatchEvent(event);

   }

批量下載圖片

這個複雜一點,但也不難,下面一步一步來!

1、首先批量導出,那麼用戶名我這裡是使用空格分割,那麼現在我在option裡面,弄一個欄位textAll,所有文字的集合。all代表是否是批量下載。fn屬性代表回調函數

   //批量導出

   var downloadAll = document.getElementById("download-all");

   downloadAll.addEventListener('click', function () {

       var _text = userName.value.replace(/(^\s*)|(\s*$)/g, "").split(/\s+/);

       option.textAll = _text;

       option.all = true;

       option.fn = downloadImg;

       draw(option);

   });

2、然後修改繪製的函數draw,判斷是否是全部繪製的情況!

   function draw(obj) {

       var canvas = document.getElementById("thecanvas");

       //畫布大小

       canvas.width = obj.width;

       canvas.height = obj.height;

       //設置圖片

       var img = new Image();

       img.src = obj.img;

       var ctx = canvas.getContext("2d");

       //設置字體的坐標

       var _x = obj.x, _y = obj.y;

       //是否居中顯示

       if (obj.xCenter) {

           _x = obj.width / 2;

       }

       if (obj.yCenter) {

           _y = obj.height / 2;

       }

       //圖片加載後

       img.onload = function () {

           //是否是全部列印

           if(obj.all){

               //遍歷textAll

               for(var i=0;i<obj.textAll.length;i++){

                   //繪製圖片

                   ctx.drawImage(img,0,0);

                   //設置字體大小

                   ctx.font=obj.fontSize;

                   //設置字體顏色

                   ctx.fillStyle=obj.color;

                   //是否居中顯示

                   if(obj.xCenter){

                       ctx.textAlign="center";

                   }

                   //繪製文字

                   ctx.fillText(obj.textAll[i], _x,_y);

                   //是否回調

                   if(obj.fn){

                       obj.fn(obj.textAll[i]);

                   }

               }

               //最後取消全部批量下載

               defult.all=false;

           }

           else{

               ctx.drawImage(img,0,0);

               ctx.font=obj.fontSize;

               ctx.fillStyle=obj.color;

               if(obj.xCenter){

                   ctx.textAlign="center";

               }

               ctx.fillText(obj.text, _x,_y);

           }

       };

   }

3.小結

關於canvas入門的第一篇文章,就寫到這裡了。寫完之後,也發現自己對canvas的也是有很多的不懂!上文的這例子,知識canvas很簡單的一個入門實例。canvas如果深入學習,能做到很多讓人驚訝的效果,這個得以後要加強學習,如果發現些值得記錄的知識,我也會寫文章。canvas是一個非常值得學習的知識,也是很有趣的一個知識。期待與大家有更多的交流和學習!

相關文章推薦

簡單的 canvas 翻角效果

canvas 初體驗之 16 個經典 canvas 實例

原生JS+Canvas實現五子棋遊戲

歡迎關注 SegmentFault 微信公眾號 :)

相關焦點

  • Canvas入門實戰之實現一個圖形驗證碼
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫本文主要介紹用canvas實現圖形驗證碼的一些思路以及如何用javascript面向對象的方式更友好的實現canvas的功能,關於canvas的一些基本使用方法和API我整理了一個思維導圖,大家感興趣的可以參考學習
  • 一個有趣的例子帶你入門canvas
    今天,我們前端群問了一個這樣的問題,然後就開始了激烈的討論。
  • html2canvas - 動態生成海報的優質js庫
    今天分享的html2canvas就可以。介紹在微信項目中經常會遇到動態生成海報的需求,Web前端合成圖片往往會使用canvas。canvas雖然強大,但用來合成海報非常繁瑣,一不小心就幾百行代碼了。而html2canvas.js是一款輕鬆地將HTML+CSS寫成的布局直接轉換成canvas,生成可保存分享的圖片。
  • Arduino 機器學習實戰入門(下)
    前文回顧:Arduino 機器學習實戰入門(上)按照以下步驟設置Arduino IDE應用程式,該應用程式用於將推理模型上載到您的電路板,並在下一節中從電路板下載培訓數據。因為我們需要在Arduino IDE中下載和安裝特定的板和庫,所以比使用Arduino Create web editor要多幾個步驟。
  • 用一天入門 canvas 和 JavaScript
    回到 <canvas> 元素:canvas 在 HTML 頁面上是一個矩形。canvas 是默認沒有邊框和內容的。寫法像這樣:<canvas id="canvas" width="200" height="100"></canvas>開始已經做了那麼多介紹,讓我們專注於使用簡單的原生 JavaScript(不是很舊——
  • 「強烈建議收藏」小程序canvas繪製帶二維碼海報全流程(枚舉踩坑,詳解解決方案)
    ✅⑦ canvas怎麼繪製base64的圖片✅⑧ 如何繪製網絡的圖片,兩種canvas畫布api,繪製圖片有什麼區別完成✅生成二維碼遇到的坑⑨ 如何正確選型生成二維碼工具?✅⑩ 生成的二維碼,識別不出來怎麼辦,✅⑪ 如何繪製二維碼上的logo✅2 實現效果二 實戰一第一階段:小程序canva初始化1 兩種cavnas獲取上下文方式我們即將解決的問題① taro-vue createCanvasContext 獲取canvas實例無效問題,繪製不出來效果?
  • 功能妙用|在家預習英語單詞,從入門到實戰
    但是老師在布置單詞學習的時候,可能會面臨:難題1:英語單詞太難記,單純背單詞太枯燥,學生從入門到放棄。難題2:英語音標太難輸入,尋遍百度複製粘貼消耗時間。難題3:英語資源何處尋,各大資源網站下載要氪金。
  • Python Web 開發入門實戰【教學大綱+教學進度表】
    《Python Web開發從入門到實戰》
  • 微信小程序canvas繪製海報並保存本地相冊
    </view><view wx:if="{{ show }}"><canvas style="width: {{ windowW }}px; height: {{ windowH }}px;" canvas-id="firstCanvas"></canvas>
  • Android NDK 實戰入門指南
    本場 Chat 內容提綱什麼是 NDK為什麼要用 NDKNDK 編譯出來的目標類型NDK 下載寫個 hello JNI 可執行文件文件解析寫個 hello JNI 調用 soAndroid Studio 寫個 hello JNI
  • 【前沿】NIPS2017貝葉斯生成對抗網絡TensorFlow實現(附GAN資料下載)
    每種參數設定都和不同的數據生成假設相對應。上圖顯示了對應兩種不同手寫風格的參數設定而產生的樣本。這個貝葉斯生成對抗網絡保留了在參數上的全概率分布。相反,標準的生成對抗網絡使用點估計(類似於單個最大似然估計)來表示這個全概率分布,這樣會丟失一些潛在的並重要的數據解釋。
  • PyTorch 深度學習官方入門中文教程 pdf 下載|PyTorchChina
    官方教程包含了 PyTorch 介紹,安裝教程;60分鐘快速入門教程,可以迅速從小白階段完成一個分類器模型;計算機視覺常用模型,方便基於自己的數據進行調整,不再需要從頭開始寫;自然語言處理模型,聊天機器人,文本生成等生動有趣的項目。總而言之:如果你想了解一下 PyTorch,可以看介紹部分。
  • C/C++學習指南系列 QT界面開發入門與實戰視頻教程
    課程名稱: C/C++學習指南系列 QT界面開發入門與實戰視頻教程課程簡介:C/C++學習指南系列 QT
  • 怎麼根據下載等高線生成TIN
    這裡,我們以生成tin文件為例,介紹一下如何根據下載的高程數據生成tin文件。2. 下載高程數據在萬能地圖下載器中,將地圖切換到高程地圖,在菜單欄上點擊"下載\框選範圍下載"框選上需要下載的範圍,如下圖所示。
  • File、Blob、dataURL 和 canvas 的應用與轉換
    File(1) 通常情況下, File 對象是來自用戶在一個 input 元素上選擇文件後返回的 FileList 對象,也可以是來自由拖放操作生成的 DataTransfer 對象,或者來自 htmlCanvasElement 上的 mozGetAsFile() API。
  • 【下載】《機器學習》+《機器學習實戰》
    本書作為該領域的入門教材,在內容上儘可能涵蓋機器學習基礎知識的各方面。 為了使儘可能多的讀者通過本書對機器學習有所了解, 作者試圖儘可能少地使用數學知識。 然而, 少量的概率、統計、代數、優化、邏輯知識似乎不可避免。 因此, 本書更適合大學三年級以上的理工科本科生和研究生, 以及具有類似背景的對機器學 習感興趣的人士。 為方便讀者, 本書附錄給出了一些相關數學基礎知識簡介。
  • 開發者值得關注的HTML5新特性Canvas
    本文將帶領初學者學習Canvas的入門知識。  走近Canvas 元素標籤  官方對Canvas元素標籤的定義為:Canvas(畫布)可以用來進行繪製圖形,繪製遊戲的圖案或者其他圖形圖案,允許使用腳本動態渲染點陣圖像。簡單來說,Canvas就是允許你在HTML5中,使用Javascript去繪製你喜歡的任何圖形了,包括文字,圖片、線、點、各種形狀等。
  • 前端海報生成的不同方案和優劣
    備註rc5出現過ios生成不了圖片的問題,還原到rc4就可以了https://github.com/niklasvh/h..., error)    })前端canvas繪製0.canvaslet canvasBox = document.createElement('canvas')let ctx = canvasBox.getContext(                    '2d'
  • 全程指導:Node JS實戰之製作塗鴉遊戲
    在本文中,將帶領讀者通過實戰製作一個能供多人在線塗鴉畫畫的遊戲,讓讀者體會Node.js的特殊魅力,這個遊戲的特點是多人在瀏覽這個頁面時,大家都可以在頁面上自由塗鴉,而且大家是互相看到其塗鴉的效果的。Node.js由於可以讓開發者編寫服務端運行的Javascript,因此能同時處理大量的連接,特別適合比如聊天,網路遊戲等需要對即時性要求高的。
  • html2canvas 將代碼轉為圖片
    使用 html2canvashtml2canvas 的使用非常簡單,簡單到只需要傳入一個 DOM 元素,然後通過回調拿到 canvas:html2canvas(element, {    onrendered: function(canvas) {        // canvas is the