公司的產品同窗看到朋友圈瘋傳的這張圖後。一拍腦殼,決定作個H5版本的來推廣一波。css
需求以下:html
文字變成能夠點擊的,並且還要可以變色(閃瞎有木有)canvas
中間的姓名換成用戶的微信頭像api
點擊button後,將canvas的操做結果保存成圖片,來現微信長按保存到本地的功能。微信
難點總結:ide
頁面元素canvas基本的api畫到畫布上(要解決顯示自適應的問題);函數
如何實現點擊canvas,識別點擊文字的對應位置;spa
圖片保存的api;設計
代碼部分請忽略css樣式調試
canvas初始化
html
<canvas id="test"></canvas>
var canvas = document.getElementById('test'), ctx = canvas.getContext('2d');
等比公式:設計圖元素尺寸/設計圖寬度 = 顯示圖元素尺寸/移動設備像素寬度;
推導: 顯示圖元素尺寸 = 設計圖元素尺寸*(移動設備像素寬度/設計圖寬度);
定義: rate= 移動設備像素寬度/設計圖寬度;
var width = document.documentElement.clientWidth, //自適應比率計算 rate = (document.documentElement.clientWidth/ 960).toFixed(2), height = rate*1540,
經由高人指點,將canvas內部的元素記錄成一個個記錄了顏色、大小、座標、等屬性的對象。
這樣能夠將元素分爲幾類:簡單幾何圖形(圓,矩形等)、文字、圖片這幾類;
同類元素能夠用相同的方法繪製(請務必get此技能)
baseColor = '#000'; //canvas文字對象 var textArr = [ {num:0, has_click: 0, worth:750000, x : 60, y : 50+60, fontSize : 25, text : '英雄聯盟', color: baseColor,isEn : true }, {num:1, has_click: 0, worth:750000, x : 310/3, y : 50+650/3, fontSize : 20, text : '守望先鋒', color: baseColor } ]; //轉爲自適應文字對象 var getTextScope = function(textArr){ var arr = []; textArr.forEach(function(item){ item.x = item.x * rate; item.y = item.y * rate; item.fontSize = item.fontSize * rate; //計算文字對象在canvas中的觸摸範圍 item.r = item.x + (item.isEn ? item.text.length / 2 : item.text.length) * item.fontSize; item.b = item.y + item.fontSize; arr.push(item); }); return arr; }; var newArr = getTextScope(textArr); //繪製文字方法 var fillTextArr = function(el, textArr){ textArr.forEach(function(item){ el.font = item.fontSize + 'px Microsoft Yahei Helvetica Neue Helvetica, STHeiTi, Arial, sans-serif '; el.textAlign= 'left'; el.textBaseline = 'top'; el.fillStyle = item.color; el.fillText(item.text, item.x, item.y); //繪製文字的觸摸識別範圍(調試用) el.beginPath(); el.rect(item.x, item.y, item.r - item.x, item.b - item.y); el.stroke(); }); }; fillTextArr(canvas,newArr)
html
頁面隱藏元素加載canvas所須要用到的img元素,也能夠新建img對象來處理。
<footer class="footer"> <div class="img-source hide"> <img src="/images/avater.jpg" alt="" id="avater"/> <img src="/images/avater-bg_05.png" alt="" id="avaterBg"/> <img src="/images/3.jpg" alt="" id="img3"/> <img src="/images/21060715code_img.jpg" alt="" id="code"/> <img src="/images/canvas_tag.png" alt="" id="scan"/> </div> </footer>
js
繪製圖片的函數
var drawImages = function(el, arr){ arr.forEach(function(item){ el.drawImage(document.getElementById(item.id), item.x * rate, item.y * rate, item.w * rate, item.h * rate); }); }; var avatar = [ {id : 'avater', x : 106, y : 50+95, w : 340/3, h : 340/3}, {id : 'avater', x : 106, y : 50+95, w : 340/3, h : 340/3}, {id : 'avaterBg', x : 100, y : 50+90, w : 375/3, h : 366/3} ]; drawImages(ctx, avatar);
js
item.r、item.b、item.x、item.y在上文var newArr = getTextScope(textArr);
中已經獲取;
//判斷點擊的點是否在範圍內 var isInText = function(item, p){ if(p.x > item.x && p.x < item.r && p.y > item.y && p.y < item.b) { return true; }else { return false; } };
//獲取元素所在區域範圍的函數 var getEventPosition = function(ev){ var x, y; if (ev.layerX || ev.layerX == 0) { x = ev.layerX; y = ev.layerY; } else if (ev.offsetX || ev.offsetX == 0) { // Opera x = ev.offsetX; y = ev.offsetY; } return {x: x, y: y}; };
交互事件實例
canvas.addEventListener('click', function(e){ //獲取點擊座標 var p = getEventPosition(e); //遍歷歐判斷是否點擊到某元素 newArr.forEach(function(item, i){ //判斷是否點擊到元素進行分別操做 if(isInText(item, p)){ //點擊到某元素的操做 } }); }, false);
如今介紹了canvas繪製的基礎操做,下一節就會寫到項目的實踐部分。