50天50個小項目 (Vue3 + Tailwindcss V4) ? | DrawingApp(畫板組件)

📅 我們繼續 50 個小項目挑戰!—— DrawingApp組件

倉庫地址:https://github.com/SunACong/50-vue-projects

項目預覽地址:https://50-vue-projects.vercel.app/

在這里插入圖片描述


使用 Vue 3 的 Composition API(<script setup> 和 HTML5 <canvas> 元素,結合 TailwindCSS 構建一個簡單的在線畫板應用。用戶可以自由繪制圖形、調節畫筆粗細、選擇顏色,并支持一鍵清空畫布。

🎯 組件目標

  • 創建一個固定尺寸的畫布區域
  • 支持鼠標點擊拖動進行繪畫
  • 提供按鈕控制畫筆粗細(+ / -)
  • 使用原生 <input type="color"> 選擇畫筆顏色
  • 提供“清空”按鈕重置畫布內容
  • 使用 TailwindCSS 快速構建現代 UI 界面

?? 技術實現點

技術點描述
Vue 3 Composition API (<script setup>)使用響應式變量管理畫筆狀態
ref 響應式變量控制畫筆大小、顏色、是否正在繪圖等
onMounted 生命周期鉤子初始化 Canvas 上下文
canvas.getContext('2d')獲取 2D 渲染上下文用于繪圖
鼠標事件監聽包括 mousedownmousemovemouseupmouseleave
TailwindCSS 布局類實現居中布局、按鈕樣式、工具欄設計

🧱 組件實現

模板結構 <template>

<template><div class="flex min-h-screen items-center justify-center bg-gray-900"><div class="flex flex-col items-center"><!-- 🎨 畫板區域 --><canvasref="canvasRef"class="aspect-square w-[800px] border-2 border-gray-300 bg-white"@mousedown="startDrawing"@mousemove="draw"@mouseup="stopDrawing"@mouseleave="stopDrawing"@contextmenu.prevent></canvas><!-- 🛠? 工具欄 --><divclass="mt-4 flex w-[800px] items-center justify-between rounded-lg bg-gray-800 p-3"><!-- 粗細調節 --><div class="flex items-center"><button@click="decreaseBrushSize"class="rounded p-2 text-white hover:bg-gray-700">-</button><span class="mx-3 text-white">{{ brushSize }}</span><button@click="increaseBrushSize"class="rounded p-2 text-white hover:bg-gray-700">+</button></div><!-- 🎨 顏色選擇 --><input type="color" v-model="brushColor" class="h-10 w-10 cursor-pointer" /><!-- 清空畫布 --><button@click="clearCanvas"class="rounded bg-red-600 p-2 text-white hover:bg-red-700">清空</button></div></div></div>
</template>

腳本邏輯 <script setup>

<script setup>
import { ref, onMounted } from 'vue'// 🖼? 畫布引用
const canvasRef = ref(null)
// ?? 是否正在繪圖
const isDrawing = ref(false)
// 畫筆粗細 & 顏色
const brushSize = ref(5)
const brushColor = ref('#000000')let lastX = 0
let lastY = 0
let ctx = null// 初始化畫布
onMounted(() => {const canvas = canvasRef.valuecanvas.width = canvas.offsetWidthcanvas.height = canvas.offsetHeightctx = canvas.getContext('2d')ctx.lineCap = 'round'ctx.lineJoin = 'round'
})// 開始繪制
const startDrawing = (e) => {if (e.button === 0) {isDrawing.value = truelastX = e.offsetXlastY = e.offsetY}
}// 繪制中
const draw = (e) => {if (!isDrawing.value) returnctx.beginPath()ctx.moveTo(lastX, lastY)ctx.lineTo(e.offsetX, e.offsetY)ctx.strokeStyle = brushColor.valuectx.lineWidth = brushSize.valuectx.stroke()lastX = e.offsetXlastY = e.offsetY
}// 停止繪制
const stopDrawing = () => {isDrawing.value = false
}// 控制畫筆大小
const increaseBrushSize = () => {if (brushSize.value < 50) brushSize.value += 1
}
const decreaseBrushSize = () => {if (brushSize.value > 1) brushSize.value -= 1
}// 清除畫布
const clearCanvas = () => {const canvas = canvasRef.valuectx.clearRect(0, 0, canvas.width, canvas.height)
}
</script>

自定義樣式 <style scoped>

<style scoped>
[draggable='true'] {transition: all 0.2s ease;
}
</style>

🔍 重點效果實現

? 鼠標事件綁定機制

我們通過以下事件監聽器實現了完整的繪圖交互:

事件名觸發時機作用
mousedown鼠標按下時標記為開始繪制,并記錄初始坐標
mousemove鼠標移動時如果處于繪制狀態,則根據當前坐標繪制線條
mouseup鼠標釋放時結束繪制
mouseleave鼠標移出畫布安全結束繪制,防止懸停后繼續繪制
contextmenu.prevent右鍵菜單阻止防止右鍵彈出默認菜單影響操作

💡 Canvas 繪圖基礎設置

ctx.lineCap = 'round'
ctx.lineJoin = 'round'

這兩行代碼設置了線條兩端為圓角,使繪制效果更自然流暢。

🎨 動態畫筆顏色與粗細

我們通過響應式變量 brushColorbrushSize 來動態更新畫筆屬性:

ctx.strokeStyle = brushColor.value
ctx.lineWidth = brushSize.value

這樣就能實時反映用戶的選擇變化。

🗑? 清空畫布功能

ctx.clearRect(0, 0, canvas.width, canvas.height)

調用 clearRect 方法一次性清除整個畫布,實現“清空”功能。


🎨 TailwindCSS 樣式重點講解

類名作用
min-h-screen設置最小高度為視口高度
items-center, justify-centerFlexbox 居中對齊布局
bg-gray-900設置深色背景
aspect-square保持畫布為正方形比例
w-[800px]固定寬度為 800px
border-2, border-gray-300邊框樣式
bg-white畫布背景色
rounded-lg, p-3工具欄圓角與內邊距
hover:bg-gray-700按鈕懸停變色
text-white白色文字
cursor-pointer鼠標懸停變為手型
h-10, w-10設置顏色選擇器大小

這些 TailwindCSS 類幫助我們快速構建了一個美觀、響應式的畫板界面。


📁 常量定義 + 組件路由

constants/index.js 添加組件預覽常量:

{id: 22,title: 'Drawing App',image: 'https://50projects50days.com/img/projects-img/22-drawing-app.png',link: 'DrawingApp',},

router/index.js 中添加路由選項:

{path: '/DrawingApp',name: 'DrawingApp',component: () => import('@/projects/DrawingApp.vue'),},

📁 擴展建議

你可以進一步擴展此組件的功能,例如:

  • ? 支持保存畫布內容為圖片(canvas.toDataURL()
  • ? 添加撤銷/重做功能(記錄歷史快照)
  • ? 支持觸控設備(如 iPad 或觸摸屏)
  • ? 封裝為獨立組件(支持 props 傳入默認顏色或大小)

🏁 總結

基于 Vue 3 和 Canvas 的畫板組件不僅實現了基本的繪圖功能,還提供了友好的交互體驗和清晰的視覺反饋。無論是作為學習項目還是實際開發中的組件模塊,都非常實用。

感謝閱讀,歡迎點贊、收藏和分享 😊


👉 下一篇,我們將完成KineticLoader組件,一個很有意思的旋轉加載動畫。🚀

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

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

相關文章

Eureka、Nacos、LoadBalance、OpenFeign?之間的區別聯系和協作 (附代碼講解)

這篇文章聊聊微服務里的這幾個老伙計&#xff1a;Eureka、Nacos、LoadBalance、OpenFeign。咱們做微服務開發&#xff0c;總會跟這幾個組件打交道&#xff1a;Eureka、Nacos、Spring Cloud LoadBalancer、OpenFeign。它們各司其職又互相配合&#xff0c;今天就把它們的關系、用…

JavaSE-繼承

繼承&#xff08;inheritance&#xff09;繼承的意義我們首先來看下面兩個類&#xff1a;public class Dog {public String name;public int age;public void eat(){System.out.println(this.name"正在吃飯");}public void bark(){System.out.println(this.name"…

第二屆虛擬現實、圖像和信號處理國際學術會議(VRISP 2025)

重要信息 官網&#xff1a;www.icvisp.net 時間&#xff1a;2025年8月1-3日 地點&#xff1a;中國-長沙 簡介 近年來&#xff0c;虛擬現實技術取得了顯著進步&#xff0c;與5G、云計算和物聯網等新一代信息技術的融合加速&#xff0c;推動了其在硬件、軟件和內容應用等方面…

SpringBoot+Mybatis+MySQL+Vue+ElementUI前后端分離版:整體布局、架構調整(二)

目錄 一、前言 二、后端調整 1.實體類調整 2.菜單相關接口 3.用戶相關接口 4.新增工具類 5.新增菜單樹返回類 6.配置類、攔截器 三、前端調整 1.請求調整 2.頁面布局、樣式調整 1.user.vue 2.index.vue 3.請求攔截 四、開發過程中的問題 五、附&#xff1a…

vue3官方文檔學習心得

這幾天抽空把vue3的文檔整個看了一遍。簡介 | Vue.js 23年寫過一個vue2的項目&#xff0c;24年寫了一個vue3的項目&#xff0c;頁面功能比較簡單&#xff0c;用幾個簡單的API&#xff0c;watch、watchEffect、ref、reactive就能實現的業務功能。 寫了幾年的react的&#xff0…

Pycharm恢復默認設置,配置導致復制粘貼等不能使用

在file 種找到manage IDE settings在manage IDE settings中找到restore default settings

【王樹森推薦系統】召回12:曝光過濾 Bloom Filter

概述 曝光過濾通常是在召回階段做&#xff0c;具體的方法就是用 Bloom Filter 曝光過濾問題 如果用戶看過某個物品&#xff0c;則不再把該物品曝光給用戶。原因是同一個物品重復曝光給用戶會損害用戶體驗&#xff0c;但也不是所有推薦系統都有曝光過濾&#xff0c;像 youtube 這…

基于STM32單片機的心率血氧監測系統設計(STM32代碼編寫+手機APP設計+PCB設計+Proteus仿真)

系列文章目錄 文章目錄 系列文章目錄前言1 資料獲取與演示視頻1.1 資料介紹1.2 資料獲取1.3 演示視頻 2 系統框架3 硬件3.1 主控制器3.2 顯示屏3.3 WIFI模塊3.4心率血氧傳感器 4 設計PCB4.1 安裝下載立創EDA專業版4.2 畫原理圖4.4 使用嘉立創下單助手進行下單&#xff0c;打板。…

main(int argc,char **agrv)的含義

今天和大家討論一個常見的但是不容易深入了解的知識點。那就是 main 函數聲明中使用到的 argc 和 argv 的含義。通常我們寫主函數的時候一般都是直接使用int main() 或者 void main() 來聲明 main 函數。但是你知道嗎&#xff1f;在c89/c99的語言標準中&#xff0c;main函數的聲…

如何簡單實現發版不影響客戶使用?nginx負載

nginx負載發版不影響客戶使用 1.需要二臺服務器 2.二臺服務器均是正式環境配置 3.服務器Nginx配置修改 發版順序&#xff1a;先在服務器2發版&#xff0c;發布成功后&#xff0c;再改服務器Nginx配置&#xff0c;重新加載nginx&#xff1b;然后在服務器再發版&#xff0c;發布成…

qt筆記(1)——Qtablewidget使用

1.基礎使用方法 &#xff08;略&#xff09; 2.坑和注意點 2.1 設置一個單元格的編輯屬性 在代碼中&#xff0c;想要修改一個單元格的編輯屬性&#xff0c;需要對這個item的flags進行設置&#xff1b;注意對一個tablewidget的一個item成員進行設置后&#xff0c;進行一次編…

字符串的模糊匹配方法介紹

字符串的模糊匹配方法介紹 目錄字符串的模糊匹配方法介紹一、編輯距離&#xff08;Levenshtein Distance&#xff09;復雜度分析二、Jaro-Winkler 距離復雜度分析三、最長公共子序列&#xff08;LCS&#xff09;復雜度分析四、模糊搜索&#xff08;Fuzzy Search&#xff09;復雜…

ActiveMQ在Spring Boot中的詳細使用指南

?? 目錄 ?? ActiveMQ簡介 什么是ActiveMQ? 核心概念 ??? 基礎架構組件 ?? 重要概念解釋 ActiveMQ vs 其他消息中間件 ?? 環境搭建 1. ActiveMQ服務端安裝 Docker方式(推薦初學者) 手動安裝方式 2. 驗證安裝 訪問Web管理界面 連接參數 測試連接 ?…

二元一次方程

前言 最近剛學二元一次方程&#xff0c;想寫一篇專欄熟悉一下本文寫給初一的同學看&#xff0c;學過的就劃了吧二元一次方程 兩個未知數最高項次數為 111 次為整式方程二元一次方程的解不唯一&#xff0c;但是二元一次方程可以用一個未知數來表達另一個未知數eg:eg:eg: xy1x y…

AI編程的未來是智能體原生開發?

目錄 前言 一、從“串行”到“并行”&#xff1a;什么是智能體原生開發&#xff1f; 1.1 傳統模式&#xff08;串行思維&#xff09; 1.2 智能體原生模式&#xff08;并行思維&#xff09; 二、程序員的新角色&#xff1a;從代碼手藝人到系統思想家 三、軟件開發的終局&a…

【牛客刷題】小紅的與運算

文章目錄 一、題目介紹1.1 題目描述1.2 輸入描述1.3 輸出描述1.4 示例二、 解題思路2.1 核心算法設計2.2 性能優化關鍵2.3 算法流程圖三、解法實現3.1 解法一:基礎實現3.1.1 初級版本分析3.2 解法二:優化版本(推薦)3.2.1 優化版本分析四、總結與拓展4.1 關鍵優化技術4.2 算…

spring中 方法上@Transation實現原理

Spring中Transactional注解方法實現原理Spring的Transactional注解在方法級別實現事務管理的原理主要基于動態代理和攔截器機制&#xff0c;以下是其核心實現流程&#xff1a;1. 代理創建階段當Spring容器啟動時&#xff0c;會為帶有Transactional注解的類創建代理對象&#xf…

qt-C++語法筆記之Stretch與Spacer的關系分析

qt-C語法筆記之Stretch與Spacer的關系分析 code review! 文章目錄qt-C語法筆記之Stretch與Spacer的關系分析1. Stretch&#xff08;拉伸因子&#xff09;2. Horizontal Spacer 和 Vertical Spacer3. Stretch 和 Spacer 的關系4. 實際應用中的選擇5. 注意事項6. 代碼與 Qt Desig…

Qwen3技術綜述

1. 引入 2025年5月&#xff0c;qwen推出了旗艦模型&#xff08;flagship model&#xff09;Qwen3-235B-A22B。并以Apache 2.0版權發布&#xff08;可自由商業使用&#xff0c;修改代碼和商用要包含原始版權&#xff09;。本文對其技術報告中提到的數據處理技術與模型結構進行綜…

[特殊字符] Excel 讀取收件人 + Outlook 批量發送帶附件郵件 —— Python 自動化實戰

許多公司定期需要將不同部門或客戶的報告發送給指定人員。手動操作容易出錯、耗時且繁瑣。今天這篇文章教你如何利用 Python 實現&#xff1a; &#x1f9e9; 從 Excel 中讀取“收件人 抄送人 附件文件路徑”&#xff1b; &#x1f4e4; 使用 win32com.client 調用 Outlook …