Canvas:實現在線畫板操作

想象一下,用幾行代碼就能創造出如此逼真的圖像和動畫,仿佛將藝術與科技完美融合,前端開發的Canvas技術正是這個數字化時代中最具魔力的一環,它不僅僅是網頁的一部分,更是一個無限創意的畫布,一個讓你的想象力自由馳騁的平臺。

目錄

基礎頁面搭建

繪畫操作

按鈕點擊事件

最后總結


基礎頁面搭建

接下來借助canvas實現一個簡易的畫版操作,首先這里我們設置一下畫布的一些基礎布局樣式:

<body><canvas id="canvas" width="800" height="600" style="border: 1px solid #ccc;"></canvas><hr><button id="boldBtn" type="button">粗線條</button><button id="thinBtn" type="button">細線條</button><button id="saveBtn" type="button">保持簽名</button><input type="color" name="" id="color" value=""><button class="clearBtn">橡皮擦</button><button id="nullBtn">清空畫布</button>
</body>

實現的效果如下所示,一個比較簡陋的畫布,以及一些基礎操作的按鈕:

繪畫操作

接下來我們開始實現繪畫操作的功能,通過監聽鼠標不同情況的事件來實現畫布上書寫內容的操作,首先這里我們先繪制畫布以及獲取對應的dom元素進行操作:

<script>// 獲取canvas畫布繪制上下文對象以及獲取2d畫筆對象let canvas = document.getElementById("canvas");      let ctx = canvas.getContext("2d");ctx.lineJoin = 'round'; // 線條連接處為圓角ctx.lineCap = 'round'; // 線條端點為圓角// 獲取DOM元素let boldBtn = document.getElementById("boldBtn");let thinBtn = document.getElementById("thinBtn");let saveBtn = document.getElementById("saveBtn");let color = document.getElementById("color");let clearBtn = document.getElementsByClassName("clearBtn")[0];let nullBtn = document.getElementById("nullBtn");
</script>

接下來開始開始監聽鼠標的按下、彈起、移動以及離開畫布的四種情況的操作,完整代碼如下:

<script>// 獲取canvas畫布繪制上下文對象以及獲取2d畫筆對象let canvas = document.getElementById("canvas");      let ctx = canvas.getContext("2d");ctx.lineJoin = 'round'; // 線條連接處為圓角ctx.lineCap = 'round'; // 線條端點為圓角// 獲取DOM元素let boldBtn = document.getElementById("boldBtn");let thinBtn = document.getElementById("thinBtn");let saveBtn = document.getElementById("saveBtn");let color = document.getElementById("color");let clearBtn = document.getElementsByClassName("clearBtn")[0];let nullBtn = document.getElementById("nullBtn");// 設置是否開始繪畫的變量let isDraw = false;// 鼠標按下去函數canvas.onmousedown = function(e) {isDraw = true; // 開始繪畫ctx.beginPath(); // 開始路徑// 獲取鼠標點擊的坐標let x = e.pageX - canvas.offsetLeft; let y = e.pageY - canvas.offsetTop; ctx.moveTo(x, y); // 移動到當前點}// 鼠標移動函數canvas.onmousemove = function(e) {if (isDraw) { // 如果開始繪畫let x = e.pageX - canvas.offsetLeft; let y = e.pageY - canvas.offsetTop; ctx.lineTo(x, y); // 繪制ctx.stroke()}}// 鼠標彈起函數canvas.onmouseup = function(e) {isDraw = false; // 結束繪畫ctx.closePath(); // 結束路徑}// 鼠標離開畫布函數canvas.onmouseleave = function(e) {isDraw = false; // 結束繪畫ctx.closePath(); // 結束路徑}
</script>

最終呈現的效果如下所示:

按鈕點擊事件

接下來給畫布下方的按鈕設置對應的點擊事件,讓其能夠實現對應的功能,如下:

粗線條:這里設置點擊事件函數如下,遮蓋策略設置在現有畫布上下文之上繪制新圖形,點擊之后寬度增加到20,并添加對應激活類名active,刪除其他按鈕可能存在的active類名:

// 粗線條函數
boldBtn.onclick = function(e) {ctx.globalCompositeOperation = 'source-over'; ctx.lineWidth = 20boldBtn.classList.add("active");thinBtn.classList.remove("active");clearBtn.classList.remove("active");
}

細線條:這里設置點擊事件函數如下,遮蓋策略設置在現有畫布上下文之上繪制新圖形,點擊之后寬度減少到2,并添加對應激活類名active,刪除其他按鈕可能存在的active類名:

// 細線條函數
thinBtn.onclick = function(e) {ctx.globalCompositeOperation = 'source-over'; ctx.lineWidth = 2thinBtn.classList.add("active");boldBtn.classList.remove("active");clearBtn.classList.remove("active");
}

保存簽名:獲取圖片數據并創建一個a標簽進行文件下載:

// 保存簽名函數
saveBtn.onclick = function(e) {let urlData = canvas.toDataURL(); // 獲取圖片數據// let img = new Image()// img.src = urlData; // 圖片地址// document.body.appendChild(img); // 添加圖片到bodylet downloadA = document.createElement("a"); // 創建a標簽downloadA.setAttribute("download", "簽名"); // 設置下載文件名downloadA.href = urlData; // 設置a標簽的地址downloadA.click(); // 點擊a標簽
}

修改顏色:設置監聽函數,動態修改canvas顏色:

// 顏色選擇函數
color.onchange = function(e) {ctx.strokeStyle = color.value; // 設置線條顏色
}

橡皮擦:這里設置點擊事件函數如下,遮蓋策略設置現有內容保持在新圖形不重疊的地方,點擊之后區域呈現空白,并添加對應激活類名active,刪除其他按鈕可能存在的active類名:

// 橡皮擦函數
clearBtn.onclick = function(e) {// 清除畫布ctx.globalCompositeOperation = 'destination-out';ctx.lineWidth = 30clearBtn.classList.add("active");boldBtn.classList.remove("active");thinBtn.classList.remove("active");
}

清空畫布:調用canvas函數直接清除整個畫布的內容:

// 清空畫布函數
nullBtn.onclick = function(e) {ctx.clearRect(0, 0, 800, 600);
}

最終呈現的效果如下所示:

最后總結

本次代碼實現了一個簡單的畫板功能,讓用戶可以在網頁上繪制、調整線條粗細、選擇顏色、保存簽名等操作。以下是代碼的實現思路:

1)HTML結構部分

在<body>中包含一個 <canvas> 元素,用于繪制圖形。

一組按鈕和一個顏色選擇器,用于控制畫筆的粗細、顏色以及清除和保存繪制的功能。

2)CSS部分

定義了一個按鈕的樣式 .active,用于表示當前選中狀態,例如粗線條、細線條、橡皮擦等按鈕會根據點擊狀態變化背景顏色。

3)JavaScript部分

《1》獲取元素:

使用 document.getElementById 和 document.getElementsByClassName 獲取 <canvas> 和各種控制按鈕。

《2》繪圖相關事件:

canvas.onmousedown:鼠標按下時開始繪畫,記錄起始點。
canvas.onmousemove:鼠標移動時,如果正在繪畫(isDraw為真),則根據當前鼠標位置繪制線條。
canvas.onmouseup 和 canvas.onmouseleave:鼠標抬起或離開畫布時結束繪畫路徑。

《3》功能按鈕事件:

粗線條 (boldBtn) 和 細線條 (thinBtn):設置線條寬度,并通過 classList 控制按鈕的選中狀態。
保存簽名 (saveBtn):使用 canvas.toDataURL() 獲取繪制內容的DataURL,創建一個下載鏈接,允許用戶保存簽名。
顏色選擇 (color):通過 color.onchange 設置繪制線條的顏色。
橡皮擦 (clearBtn):使用 ctx.globalCompositeOperation = 'destination-out' 實現擦除效果,清除畫布上的內容。
清空畫布 (nullBtn):使用 ctx.clearRect() 清除整個畫布的內容。

《4》繪圖上下文:

使用 getContext('2d') 獲取 Canvas 2D 渲染上下文對象 ctx,設置線條的樣式(圓角連接和端點)。

這段代碼整合了 HTML、CSS 和 JavaScript,提供了一個簡單而功能豐富的在線繪圖工具,用戶可以通過點擊不同的按鈕和操作來繪制、擦除、保存簽名等。完整代碼如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>button.active {color: #fff;background-color: orange;}</style>
</head><body><canvas id="canvas" width="800" height="600" style="border: 1px solid #ccc;"></canvas><hr><button id="boldBtn" type="button">粗線條</button><button id="thinBtn" type="button">細線條</button><button id="saveBtn" type="button">保存簽名</button><input type="color" name="" id="color" value=""><button class="clearBtn">橡皮擦</button><button id="nullBtn">清空畫布</button>
<script>// 獲取canvas畫布繪制上下文對象以及獲取2d畫筆對象let canvas = document.getElementById("canvas");      let ctx = canvas.getContext("2d");ctx.lineJoin = 'round'; // 線條連接處為圓角ctx.lineCap = 'round'; // 線條端點為圓角// 獲取DOM元素let boldBtn = document.getElementById("boldBtn");let thinBtn = document.getElementById("thinBtn");let saveBtn = document.getElementById("saveBtn");let color = document.getElementById("color");let clearBtn = document.getElementsByClassName("clearBtn")[0];let nullBtn = document.getElementById("nullBtn");// 設置是否開始繪畫的變量let isDraw = false;// 鼠標按下去函數canvas.onmousedown = function(e) {isDraw = true; // 開始繪畫ctx.beginPath(); // 開始路徑// 獲取鼠標點擊的坐標let x = e.pageX - canvas.offsetLeft; let y = e.pageY - canvas.offsetTop; ctx.moveTo(x, y); // 移動到當前點}// 鼠標移動函數canvas.onmousemove = function(e) {if (isDraw) { // 如果開始繪畫let x = e.pageX - canvas.offsetLeft; let y = e.pageY - canvas.offsetTop; ctx.lineTo(x, y); // 繪制ctx.stroke()}}// 鼠標彈起函數canvas.onmouseup = function(e) {isDraw = false; // 結束繪畫ctx.closePath(); // 結束路徑}// 鼠標離開畫布函數canvas.onmouseleave = function(e) {isDraw = false; // 結束繪畫ctx.closePath(); // 結束路徑}// 粗線條函數boldBtn.onclick = function(e) {ctx.globalCompositeOperation = 'source-over'; ctx.lineWidth = 20boldBtn.classList.add("active");thinBtn.classList.remove("active");clearBtn.classList.remove("active");}// 細線條函數thinBtn.onclick = function(e) {ctx.globalCompositeOperation = 'source-over'; ctx.lineWidth = 2thinBtn.classList.add("active");boldBtn.classList.remove("active");clearBtn.classList.remove("active");}// 保存簽名函數saveBtn.onclick = function(e) {let urlData = canvas.toDataURL(); // 獲取圖片數據// let img = new Image()// img.src = urlData; // 圖片地址// document.body.appendChild(img); // 添加圖片到bodylet downloadA = document.createElement("a"); // 創建a標簽downloadA.setAttribute("download", "簽名"); // 設置下載文件名downloadA.href = urlData; // 設置a標簽的地址downloadA.click(); // 點擊a標簽}// 顏色選擇函數color.onchange = function(e) {ctx.strokeStyle = color.value; // 設置線條顏色}// 橡皮擦函數clearBtn.onclick = function(e) {// 清除畫布ctx.globalCompositeOperation = 'destination-out';ctx.lineWidth = 30clearBtn.classList.add("active");boldBtn.classList.remove("active");thinBtn.classList.remove("active");}// 清空畫布函數nullBtn.onclick = function(e) {ctx.clearRect(0, 0, 800, 600);}
</script>
</body>
</html>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/44462.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/44462.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/44462.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python網絡爬蟲之Urllib

概述 urllib的request模塊提供了最基本的構造HTTP請求的方法&#xff0c;使用它可以方便地實現請求的發送并得到響應&#xff0c;同時它還帶有處理授權驗證&#xff08;authentication&#xff09;、重定向&#xff08;redirection&#xff09;、瀏覽器Cookies以及其他內容。 …

DELTA: DEGRADATION-FREE FULLY TEST-TIME ADAPTATION--論文筆記

論文筆記 資料 1.代碼地址 2.論文地址 https://arxiv.org/abs/2301.13018 3.數據集地址 https://github.com/bwbwzhao/DELTA 論文摘要的翻譯 完全測試時間自適應旨在使預訓練模型在實時推理過程中適應測試數據流&#xff0c;當測試數據分布與訓練數據分布不同時&#x…

算法中的基礎知識點,你知道多少呢!

遞歸 場景&#xff1a; ? 1&#xff09;斐波那契數列 遞推 場景&#xff1a; ? 1&#xff09;斐波那契數列 ? 2&#xff09;遞歸 回溯 棧 先進后出 場景&#xff1a; ? 1&#xff09;path.resolve /a/b/…/c/d —> /a/c/d ? 2&#xff09;JSX ? 3&#xff09;加減乘…

VBA實現Excel的數據透視表

前言 本節會介紹通過VBA的PivotCaches.Create方法實現Excel創建新的數據透視表、修改原有的數據透視表的數據源以及刷新數據透視表內容。 本節測試內容以下表信息為例 1、創建數據透視表 語法&#xff1a;PivotCaches.Create(SourceType, [SourceData], [Version]) 說明&am…

打卡第8天-----字符串

進入字符串章節了,我真的特別希望把leetcode上的題快點全部都給刷完,我是社招準備跳槽才選擇這個訓練營的,面試總是掛算法題和編程題,希望通過這個訓練營我的算法和編程的水平能有所提升,抓住機會,成功上岸。我現在的這份工作,真的是一天都不想干了,但是下家工作單位還…

Spring——配置說明

1. 別名 別名&#xff1a;如果添加了別名&#xff0c;也可以使用別名獲取這個對象 <alias name"user" alias"user2"/> 2. Bean的配置 id&#xff1a;bean 的唯一標識符&#xff0c;也就是相當于我們學的對象名class&#xff1a;bean 對象所對應的…

無法解析主機:mirrorlist.centos.org Centos 7

從 2024 年 7 月 1 日起&#xff0c;在 CentOS 7 上&#xff0c;請切換到 Vault 存檔存儲庫&#xff1a; vi /etc/yum.repos.d/CentOS-Base.repo 復制/粘貼以下內容并注意您的操作系統版本。如果需要&#xff0c;請更改。此配置中的版本為 7.9.2009&#xff1a; [base] name…

Mac虛擬機跑Windows流暢嗎 Mac虛擬機連不上網絡怎么解決 mac虛擬機網速慢怎么解決

隨著技術的發展&#xff0c;很多用戶希望能在Mac電腦上運行Windows系統&#xff0c;從而能夠使用那些僅支持Windows系統的軟件。使用虛擬機軟件可以輕松滿足這一需求。但是&#xff0c;很多人可能會有疑問&#xff1a;“Mac虛擬機跑Windows流暢嗎&#xff1f;”&#xff0c;而且…

【AI前沿】深度學習基礎:訓練神經網絡

文章目錄 &#x1f4d1;前言一、前向傳播與反向傳播1.1 前向傳播&#xff08;Forward Propagation&#xff09;1.2 反向傳播&#xff08;Backpropagation&#xff09; 二、損失函數和優化算法2.1 損失函數&#xff08;Loss Function&#xff09;2.2 優化算法&#xff08;Optimi…

極狐Gitlab使用

目錄 續接上篇&#xff1a;極狐Gitlab安裝部署-CSDN博客 1. 關閉注冊功能 2. 創建群組 3. 創建用戶 5. 邀請成員到群組 6. 設置導入導出項目源 7. 通過gitee導入庫 8. 通過倉庫URL導入 9. 自創建項目 10. 默認分支main的權限 11. 使用普通用戶進入自建庫 12. 創建用…

python的isinstance和type

class A:passclass B(A)passbB()#isinstance可以進行繼承關系的判斷 print(isinstance(b,B))#Trueprint(isinstance(b,A))#Trueprint(type(b) is B)#Trueprint(type(b) is A)#Falseprint(type(b),A,B,b)#<class __main__.B> <class __main__.A> <class __main__…

B. Corner Twist(cf956)

題意&#xff1a;給你兩個網格&#xff0c;a和b&#xff0c;都是n行和 m 列。網格中的所有數值都是 0 &#xff0c; 1 或 2 。 您可以多次對 a&#x1d44e; 執行以下操作&#xff1a; 選取網格中任意一個長寬的子矩形。您可以選擇整個網格作為子矩形。子矩形有四個角。取所選…

【Linux 線程】線程的基本概念、LWP的理解

文章目錄 一、ps -L 指令&#x1f34e;二、線程控制 一、ps -L 指令&#x1f34e; &#x1f427; 使用 ps -L 命令查看輕量級進程信息&#xff1b;&#x1f427; pthread_self() 用于獲取用戶態線程的 tid&#xff0c;而并非輕量級進程ID&#xff1b;&#x1f427; getpid() 用…

生成日志系統和監控

背景&#xff1a;已知某后臺服務將日志存放在本地硬盤的日志文件中&#xff0c;該服務也支持代碼熱更新&#xff0c;并在完成熱更新后輸出一條日志。我們需要對服務日志進行監控&#xff0c;以確保文件熱更新后的錯誤能被第一時間發現。 我們提供 Python 程序模擬&#xff08;…

matlab仿真 模擬調制(上)

&#xff08;內容源自詳解MATLAB&#xff0f;SIMULINK 通信系統建模與仿真 劉學勇編著第五章內容&#xff0c;有興趣的讀者請閱讀原書&#xff09; 1.幅度調制 clear all ts0.0025; %信號抽樣時間間隔 t0:ts:10-ts;%時間矢量 fs1/ts;%抽樣頻率 dffs/length(t); %fft的頻率分…

國內從事人機交互的團隊——浙江工業大學

一、背景 當我們選擇一個新的課題后&#xff0c;需要清楚的了解從事該方向的團隊都有哪些&#xff0c;這樣可以及時跟蹤和學習大牛團隊的最新進展&#xff0c;以免自己認為的good idea&#xff0c;其實早就已經研究過了。 隨著人形機器人的發展&#xff0c;機器人不僅需要在無…

人類遠未觸及自然規律的本質

我想知道上帝是如何創造這個世界的&#xff0c;對于這樣或那樣的現象我不感興趣&#xff0c;我想知道的是他的思想&#xff0c;其余的都是細枝末節。——愛因斯坦 人類對自然規律的研究已經取得了不少進展&#xff0c;但是看起來研究清楚了原理&#xff0c;其實只是發現了更深…

【Windows】實現窗口子類化(基于遠程線程注入)

目錄 前言 原理解釋 完整項目 相關文獻 文章出處鏈接&#xff1a;[https://blog.csdn.net/qq_59075481/article/details/140334106] 前言 眾所周知&#xff0c;DLL 注入有多種用途&#xff0c;如熱修補、日志記錄、子類化等。本文重點介紹使用 DLL 注入對窗口進行子類化。…

mysql中count的區別

count(1)和count(*) 從執行計劃來看&#xff0c;count(1)和count(*)的效果是一樣的當表的數據量大些時&#xff0c;對表分析之后&#xff0c;使用count(1)還要比使用count(*)用時多當數據量在1W以內時&#xff0c;count(1)會比count(*)的用時少&#xff0c;不過也差不多如果cou…

GOLLIE : ANNOTATION GUIDELINES IMPROVE ZERO-SHOT INFORMATION-EXTRACTION

文章目錄 題目摘要引言方法實驗消融 題目 Gollie&#xff1a;注釋指南改進零樣本信息提取 論文地址&#xff1a;https://arxiv.org/abs/2310.03668 摘要 大型語言模型 (LLM) 與指令調優相結合&#xff0c;在泛化到未見過的任務時取得了重大進展。然而&#xff0c;它們在信息提…