1. 程式人生 > >Canvas實現放大鏡效果完整案例分析(附程式碼)

Canvas實現放大鏡效果完整案例分析(附程式碼)

本文主要記錄 `canvas` 在影象、文書處理、離屏技術和放大鏡特效的實現過程中使用到的API。先看下效果吧: 一張模糊的圖片: ![](https://img2020.cnblogs.com/blog/1414921/202011/1414921-20201121144252753-583854096.png) 滑鼠點選任意位置,產生放大效果: ![](https://img2020.cnblogs.com/blog/1414921/202011/1414921-20201121144334515-7116998.png) 哇塞~ 一個帥哥,哈哈哈哈~ #### 1、顯示模糊照片 其實一般的互動不是模糊照片,這裡我只是為了誇張下效果,用了張模糊的原圖,哈哈哈,canvas本身是可以對清晰的圖片做濾鏡處理,涉及到很多圖形學的演算法,然後我不會,默默的打開了PS手動高斯模糊了一張照片...嗯,沒毛病! 首先定義一個`canvas`元素 ```html ``` ```js //定義canvas畫布 var canvas1 = document.getElementById('canvas1'); ctx1 = canvas.getContext('2d'); //模糊圖片載入 var image1 = new Image(); image1.src = "./模糊.png"; //圖片載入成功後繪製圖片 image1.onload = function() { //drawImage 在畫布上繪製模糊圖片 ctx1.drawImage(image1, 0, 0, canvas1.width, canvas1.height); }; ``` > ctx1.drawImage(圖片,x位置,y位置,圖片顯示寬度,圖片顯示高度) #### 2、放大鏡原理 實現效果:如上圖,點選或點選滑動滑鼠顯示一個區域,區域中顯示對應點選部分範圍的放大清晰圖片。那麼問題就可以肢解為3部分: ```js 1、如何在canvas(模糊圖)上再畫出另外一個canvas(清晰放大圖); 2、如何將canvas中顯示的(清晰放大圖)剪切出圓形區域。 3、如何在滑鼠點選滑動的時候顯示該區域; ``` #### 3、載入清晰圖片 我們再加一個canvas(放大鏡看到的圖片),初始隱藏: ```html ``` ```js var canvas2 = document.getElementById('canvas2'), ctx2 = canvas2.getContext('2d'), scale = 2; // 放大倍數 // canvas2的圖片大小是模糊圖片的2倍 canvas2.width = canvas.width * scale; canvas2.height = canvas.height * scale; // 在canvas2中載入圖片 var image2 = new Image(); image2.src = "name2.png"; image2.onload = function() { ctx2.drawImage(image2, 0, 0, canvas2.width, canvas2.height); }; ``` #### 4、顯示放大鏡 ##### 4.1 繪製放大鏡 滑鼠所處的位置點(x,y)是區域的中心,計算出清晰圖所在的位置點,我們先假設繪製一個正方形; ```js // 圓的半徑是mr var mr = 100; // 對應模糊圖的左上角起點 var dx = x - mr, dy = y - mr; // 找出清晰圖截圖的左上角起點 var sx = x * scale - mr, sy = y * scale- mr; ``` ![](https://img2020.cnblogs.com/blog/1414921/202011/1414921-20201121150905862-704485635.png) 擷取圓形 ```js // 儲存當前狀態 ctx.save(); // 邊框 ctx.strokeStyle = "#9eddf1"; ctx.lineWidth = 3; // 開始繪製 ctx.beginPath(); // ⚪ ctx.arc(x, y, mr, 0, Math.PI * 2); ctx.stroke(); // 表示剪下 ctx.clip(); // 釋放當前狀態 ctx.restore(); ``` ![](https://img2020.cnblogs.com/blog/1414921/202011/1414921-20201121153924235-480579505.png) > 繪製狀態的最佳搭檔save()和restore():用於對當前狀態的儲存及釋放不影響其他操作;可用於重複的繪製圖形的變化過程; > clip():表示剪下區域 ##### 4.2 離屏技術 所謂的離屏技術就是在一個canvas上繪製另外一個canvas,前面使用的繪製圖片的API是`drawImage()`,它分別可以支援,3個、5個和9個引數; 其中第一個引數既可以是圖片,也可以是canvas物件!那麼我們就可以使用這個方法,在圓上繪製出清晰圖了~ ```js // 在對應的位置上重新繪製圖片 //drawImage(img,sx,sy,swidth,sheight,x,y,width,height) 9個引數時 //img: 圖片/canvas //sx: 圖片的X起點 //sy: 圖片的Y起點 //swidth:要繪製的圖片選取的寬度 //sheight:要繪製的圖片選取的高度 //x,y:圖片在canvas上顯示的位置 //width,height:在Canvas上要顯示的大小 ctx1.drawImage(canvas2, sx, sy, 2 * mr, 2 * mr, dx, dy, 2 * mr, 2 * mr); ``` #### 5、滑鼠互動事件 效果:滑鼠點選並滑動滑鼠產生反應,鬆開滑鼠或者移除畫布則失效。 ```js //定義一個判斷滑鼠是否是點選滑動的識別符號 var flag; //滑鼠點入事件 canvas.onmousedown = function(e) { flag = true; //顯示放大鏡 } // 滑鼠移動事件 canvas.onmousemove = function(e) { if (flag) { //顯示放大鏡 } } //滑鼠鬆開事件 canvas.onmouseup = function(e) { flag = false; // 隱藏放大鏡 } //滑鼠離開事件 canvas.onmouseout = function(e) { flag = false; // 隱藏放大鏡 } ``` 完整程式碼: ```js var scale = 3; var mr = 150; var photo = { //初始化 init: function() { var that = this; that.canvas = document.getElementById('canvas'); that.ctx = that.canvas.getContext('2d'); that.canvas2 = document.getElementById('canvas2'); that.ctx2 = that.canvas2.getContext('2d'); that.canvas.width = 800; that.canvas.height = 500; that.canvas2.width = that.canvas.width * scale; that.canvas2.height = that.canvas.height * scale; that.image1 = new Image(); that.image1.src = "./name3.jpg"; that.image2 = new Image(); that.image2.src = "./name4.jpg"; that.image1.onload = function() { that.ctx.drawImage(that.image1, 0, 0, that.canvas.width, that.canvas.height); }; that.image2.onload = function() { that.ctx2.drawImage(that.image2, 0, 0, that.canvas2.width, that.canvas2.height); that.moveEvt(); }; }, bigerImage: function(x, y) { var that = this; var imageX = x * scale, imageY = y * scale, sx = imageX - mr, sy = imageY - mr; var dx = x - mr, dy = y - mr; that.ctx.save(); that.ctx.strokeStyle = "#9eddf1"; that.ctx.lineWidth = 3; that.ctx.beginPath(); that.ctx.arc(x, y, mr, 0, Math.PI * 2); that.ctx.shadowColor = "#6ed25b"; that.ctx.shadowBlur = 10; that.ctx.stroke(); that.ctx.clip(); that.ctx.drawImage(that.canvas2, sx, sy, 2 * mr, 2 * mr, dx, dy, 2 * mr, 2 * mr); that.ctx.restore(); }, //移動 moveEvt: function() { var that = this; that.canvas.onmousedown = function(e) { that.flag = true; that.showImage(e); } that.canvas.onmousemove = function(e) { if (that.flag) { that.showImage(e) } } that.canvas.onmouseup = function(e) { that.hideImage(e) } that.canvas.onmouseout = function(e) { that.hideImage(e) } }, showImage: function(e) { e.preventDefault() var x = e.offsetX, y = e.offsetY, that = this; that.ctx.clearRect(0, 0, that.canvas.width, that.canvas.height); that.ctx.drawImage(that.image1, 0, 0, that.canvas.width, that.canvas.height); that.bigerImage(x, y); }, hideImage: function(e) { e.preventDefault() var that = this; that.flag = false; that.ctx.clearRect(0, 0, that.canvas.width, that.canvas.height); that.ctx.drawImage(that.image1, 0, 0, that.canvas.width, that.canvas.height); } } window.onload = function() { photo.init(); } ``` 轉載請說明出處,