canvas离屏技术与放大镜实现
教程所示圖片使用的是 github 倉庫圖片,網(wǎng)速過慢的朋友請移步>>> (原文)canvas 離屏技術(shù)與放大鏡實(shí)現(xiàn)。
更多討論或者錯(cuò)誤提交,也請移步。
利用
canvas除了可以實(shí)現(xiàn)濾鏡,還可以利用離屏技術(shù)放大鏡功能。為了方便講解,本文分為 2 個(gè)應(yīng)用部分:
1. 什么是離屏技術(shù)?
canvas 學(xué)習(xí)和濾鏡實(shí)現(xiàn)介紹過
drawImage接口。除了繪制圖像,這個(gè)接口還可以: 將一個(gè)canvas對象繪制到另一個(gè)canvas對象上。這就是離屏技術(shù)。2. 實(shí)現(xiàn)水印和中心縮放
在代碼中,有兩個(gè) canvas 標(biāo)簽。分別是可見與不可見。不可見的 canvas 對象上的 Context 對象,就是我們放置圖像水印的地方。
更多詳解,請看代碼注釋:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Learn Canvas</title><style>canvas {display: block;margin: 0 auto;border: 1px solid #222;}input {display: block;margin: 20px auto;width: 800px}</style> </head> <body><div id="app"><canvas id="my-canvas"></canvas><input type="range" value="1.0" min="0.5" max="3.0" step="0.1"><canvas id="watermark-canvas" style="display: none;"></canvas></div><script type="text/javascript">window.onload = function () {var canvas = document.querySelector("#my-canvas")var watermarkCanvas = document.querySelector("#watermark-canvas")var slider = document.querySelector("input")var scale = slider.valuevar ctx = canvas.getContext('2d')var watermarkCtx = watermarkCanvas.getContext("2d")/* 給第二個(gè)canvas獲取的Context對象添加水印 */watermarkCanvas.width = 300watermarkCanvas.height = 100watermarkCtx.font = "bold 20px Arial"watermarkCtx.lineWidth = "1"watermarkCtx.fillStyle = "rgba(255 , 255 , 255, 0.5)"watermarkCtx.fillText("=== yuanxin.me ===", 50, 50)/****************************************/var img = new Image()img.src = "./img/photo.jpg"/* 加載圖片后執(zhí)行操作 */img.onload = function () {canvas.width = img.width;canvas.height = img.height;drawImageByScale(canvas, ctx, img, scale, watermarkCanvas);// 監(jiān)聽input標(biāo)簽的mousemove事件// 注意:mousemove實(shí)時(shí)監(jiān)聽值的變化,內(nèi)存消耗較大slider.onmousemove = function () {scale = slider.valuedrawImageByScale(canvas, ctx, img, scale, watermarkCanvas);}}/******************/}/**** @param {Object} canvas 畫布對象* @param {Object} ctx* @param {Object} img* @param {Number} scale 縮放比例* @param {Object} watermark 水印對象*/function drawImageByScale(canvas, ctx, img, scale, watermark) {// 圖像按照比例進(jìn)行縮放var width = img.width * scale,height = img.height * scale// (dx, dy): 畫布上繪制img的起始坐標(biāo)var dx = canvas.width / 2 - width / 2,dy = canvas.height / 2 - height / 2ctx.clearRect(0, 0, canvas.width, canvas.height) // No1 清空畫布ctx.drawImage(img, dx, dy, width, height) // No2 重新繪制圖像if (watermark) {// No3 判斷是否有水印: 有, 繪制水印ctx.drawImage(watermark, canvas.width - watermark.width, canvas.height - watermark.height)}}</script> </body> </html>實(shí)現(xiàn)效果如下圖所示:
拖動(dòng)滑竿,即可放大和縮小圖像。然后右鍵保存圖像。保存后的圖像,就有已經(jīng)有了水印,如下圖所示:
3. 實(shí)現(xiàn)放大鏡
在上述中心縮放的基礎(chǔ)上,實(shí)現(xiàn)放大鏡主需要注意以下 2 個(gè)部分:
代碼如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Document</title><style>canvas {display: block;margin: 0 auto;border: 1px solid #222;}</style> </head> <body><canvas id="my-canvas"></canvas><canvas id="off-canvas" style="display: none;"></canvas><script>var isMouseDown = false,scale = 1.0var canvas = document.querySelector("#my-canvas")var offCanvas = document.querySelector("#off-canvas") // 離屏 canvasvar ctx = canvas.getContext("2d")var offCtx = offCanvas.getContext("2d") // 離屏 canvas 的 Context對象var img = new Image()window.onload = function () {img.src = "./img/photo.jpg"img.onload = function () {canvas.width = img.widthcanvas.height = img.heightoffCanvas.width = img.widthoffCanvas.height = img.height// 計(jì)算縮放比例scale = offCanvas.width / canvas.width// 初識(shí)狀態(tài)下, 兩個(gè)canvas均繪制Imagectx.drawImage(img, 0, 0, canvas.width, canvas.height)offCtx.drawImage(img, 0, 0, canvas.width, canvas.height)}// 鼠標(biāo)按下canvas.onmousedown = function (event) {event.preventDefault() // 禁用默認(rèn)事件var point = windowToCanvas(event.clientX, event.clientY) // 獲取鼠標(biāo)相對于 canvas 標(biāo)簽的坐標(biāo)isMouseDown = truedrawCanvasWithMagnifier(true, point) // 繪制在離屏canvas上繪制放大后的圖像}// 鼠標(biāo)移動(dòng)canvas.onmousemove = function (event) {event.preventDefault() // 禁用默認(rèn)事件if (isMouseDown === true) {var point = windowToCanvas(event.clientX, event.clientY)drawCanvasWithMagnifier(true, point)}}// 鼠標(biāo)松開canvas.onmouseup = function (event) {event.preventDefault() // 禁用默認(rèn)事件isMouseDown = falsedrawCanvasWithMagnifier(false) // 不繪制離屏放大鏡}// 鼠標(biāo)移出canvas標(biāo)簽canvas.onmouseout = function (event) {event.preventDefault() // 禁用默認(rèn)事件isMouseDown = falsedrawCanvasWithMagnifier(false) // 不繪制離屏放大鏡}}/*** 返回鼠標(biāo)相對于canvas左上角的坐標(biāo)* @param {Number} x 鼠標(biāo)的屏幕坐標(biāo)x* @param {Number} y 鼠標(biāo)的屏幕坐標(biāo)y*/function windowToCanvas(x, y) {var bbox = canvas.getBoundingClientRect() // bbox中存儲(chǔ)的是canvas相對于屏幕的坐標(biāo)return {x: x - bbox.x,y: y - bbox.y}}function drawCanvasWithMagnifier(isShow, point) {ctx.clearRect(0, 0, canvas.width, canvas.height) // 清空畫布ctx.drawImage(img, 0, 0, canvas.width, canvas.height) // 在畫布上繪制圖像/* 利用離屏,繪制放大鏡 */if (isShow) {var { x, y } = pointvar mr = 50 // 正方形放大鏡邊長// (sx, sy): 待放大圖像的開始坐標(biāo)var sx = x - mr / 2,sy = y - mr / 2// (dx, dy): 已放大圖像的開始坐標(biāo)var dx = x - mr,dy = y - mr// 將offCanvas上的(sx,sy)開始的長寬均為mr的正方形區(qū)域// 放大到// canvas上的(dx,dy)開始的長寬均為 2 * mr 的正方形可視區(qū)域// 由此實(shí)現(xiàn)放大效果ctx.drawImage(offCanvas, sx, sy, mr, mr, dx, dy, 2 * mr, 2 * mr)}/*********************/}</script> </body> </html>放大鏡效果如下圖所示(被紅筆標(biāo)出的區(qū)域就是我們的正方形放大鏡):
歡迎入群:857989948 。IT 技術(shù)深度交流和分享,涉及方面包括但不限于:網(wǎng)站制作、運(yùn)營、UI 設(shè)計(jì)、算法分析、大數(shù)據(jù)、人工智能等。本群主打有深度、有態(tài)度的技術(shù)交流,歡迎熱衷記錄知識(shí)的您的加入。
本文轉(zhuǎn)載于:猿2048https://www.mk2048.com/blog/blog.php?id=k2ihkj&title=canvas離屏技術(shù)與放大鏡實(shí)現(xiàn)
總結(jié)
以上是生活随笔為你收集整理的canvas离屏技术与放大镜实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 本地存储之sessionStorage
- 下一篇: 使用bootstrap的dropdown