Vue趣味【Vue3+Element Plus+Canvas实现一个简易画板;支持导出为图片】

news/2024/11/8 20:38:47/

目录

  • 🌟前言
  • 🌟粉丝先看
  • 🌟创建Vue3项目
  • 🌟引入Element Plus
  • 🌟实现代码(详细注释)
  • 🌟写在最后
  • 🌟JSON包里写函数,关注博主不迷路

🌟前言

哈喽小伙伴们,上一期给大家总结了一些常见的Vue实战中的经常用到的Vue小魔法,私下也收到了好多小伙伴的补充;小伙伴们实在是太强啦,和大家一起共同学习进步真的很开心。今天博主使用Vue3,结合ElementPlus和Canvas实现一个建议的画板,支持将绘画作品导出为图片哦;一起来看下吧。

🌟粉丝先看

博主实在没有绘画细胞大家别笑

🌟创建Vue3项目

1.使用vite构建一个vue3项目

npm create vite@latest

在这里插入图片描述

Project name:你的项目名;
Select a framework:框架选择Vue;
Select a variant:语言选择TypeSceript

cd vite-project
npm install
npm run dev

这样你的项目就创建好了

🌟引入Element Plus

Element-Plus官网国内站点

使用包管理器

我们建议您使用包管理器(如 NPM、Yarn 或 pnpm)安装 Element Plus,然后您就可以使用打包工具,例如 Vite 或 webpack。

# 选择一个你喜欢的包管理器# NPM
$ npm install element-plus --save# Yarn
$ yarn add element-plus# pnpm
$ pnpm install element-plus

如果您的网络环境不好,建议使用相关镜像服务 cnpm 或 中国 NPM 镜像

浏览器直接引入

直接通过浏览器的 HTML 标签导入 Element Plus,然后就可以使用全局变量 ElementPlus 了。 根据不同的 CDN 提供商有不同的引入方式, 我们在这里以 unpkg 和 jsDelivr 举例。 你也可以使用其它的 CDN 供应商。

unpkg

<head><!-- Import style --><link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" /><!-- Import Vue 3 --><script src="//unpkg.com/vue@3"></script><!-- Import component library --><script src="//unpkg.com/element-plus"></script>
</head>

jsDelivr

<head><!-- Import style --><linkrel="stylesheet"href="//cdn.jsdelivr.net/npm/element-plus/dist/index.css"/><!-- Import Vue 3 --><script src="//cdn.jsdelivr.net/npm/vue@3"></script><!-- Import component library --><script src="//cdn.jsdelivr.net/npm/element-plus"></script>
</head>

完整引入

// main.ts
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'const app = createApp(App)app.use(ElementPlus)
app.mount('#app')

按需导入

首先你需要安装unplugin-vue-components 和 unplugin-auto-import这两款插件

npm install -D unplugin-vue-components unplugin-auto-import

然后把下列代码插入到你的 Vite 的配置文件中

// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'export default defineConfig({// ...plugins: [// ...AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),],
})

🌟实现代码(详细注释)

<template><div id="content"><div class="toolBar"><el-button @click="clear">清空</el-button><el-button @click="exprot">导出</el-button><el-button @click="eraser">{{ text }}</el-button><div style="margin-left: 12px"><!-- Element-Plus 颜色选择器 --><el-color-picker  v-model="color1" @change="colorChange"/></div><div style="margin-left: 12px;width: 100px"><!-- Element-Plus 滑块 --><el-slider style="margin-left: 12px;width: 100px" v-model="value1" @change="numberChange"/></div><!-- 右上方关闭按钮 --><div class="light" @click="backIndex"><div></div><div></div><div></div><div></div>X</div></div><canvas id="myCanvas"></canvas></div>
</template><script setup lang="ts">import {reactive, ref, toRefs, onBeforeMount, onMounted, nextTick} from 'vue'import {useRouter} from "vue-router";import icon from '../../assets/pen2.png'// 初始文字const text = ref('橡皮擦')// 该变量用来记录按钮文本const textFlag = ref(true)// 初始颜色const color1 = ref('#409EFF')// 初始线条粗细const value1 = ref(6)// 光标自定义const cursorIcon = ref(`url(${icon}),default`);let myCanvas: HTMLElement | nulllet ctx: { scale: (arg0: number, arg1: number) => void; moveTo: (arg0: number, arg1: number) => void; beginPath: () => void; lineWidth: any; strokeStyle: any; lineTo: (arg0: number, arg1: number) => void; stroke: () => void; }let isMouseDown: booleanlet strokeStyle: stringlet lineWidth: numberonMounted(() => {nextTick(() => {initCanvas()})})//返回首页const router = useRouter();function backIndex() {router.push('/')}// 初始化canvasfunction initCanvas() {// 线条细节处理,分辨率let dpr = window.devicePixelRatio || 1;myCanvas = document.getElementById('myCanvas')// 设置canvas实际尺寸myCanvas.width = window.innerWidth - 20myCanvas.height = window.innerHeight - 50// 让canvas坐标系统使用css像素ctx = myCanvas.getContext('2d');ctx.scale(dpr, dpr);// 监听canvas的鼠标按下时间myCanvas.addEventListener('mousedown', function (e) {// console.log(e);isMouseDown = true // 变量记录是否按下鼠标ctx.moveTo(e.pageX, e.pageY) // 将绘制起始点设置为鼠标按下的点// 设置绘制图形的样式:线条宽度和颜色;开始画线ctx.beginPath();ctx.lineWidth =  lineWidth || value1.value;ctx.strokeStyle = strokeStyle || color1.value;})// 监听鼠标松开事件myCanvas.addEventListener('mousemove', function (e) {if (isMouseDown) { // 如果鼠标按下ctx.lineTo(e.pageX, e.pageY) // 设置终点ctx.stroke() // 连接起点和终点并用设置好的样式描边}})// 监听鼠标松开事件,停止绘制myCanvas.addEventListener('mouseup', function () {// ctx.closePath();isMouseDown = false})}// 清空function clear() {// 1. 简单填充 使用一个新的背景色简单地填充整个画布,这样就可以清除当前内容// ctx.fillStyle = '#fff';// let rect = this.canvas.getBoundingClientRect();// ctx.fillRect(rect.x, rect.y, rect.width, rect.height)// 2.重置画布高度 当画布的宽或高被重置时,当前画布内容就会被移除。let rect = myCanvas.getBoundingClientRect();myCanvas.width = rect.width;myCanvas.height = rect.height;//3. 使用clearRect函数 clearRect() 函数可以指定起始点的x, y 位置以及宽度和高度来清除画布// let rect = this.canvas.getBoundingClientRect();// this.ctx.clearRect(rect.x, rect.y, rect.width, rect.height);}// 导出function exprot() {let link = document.createElement('a')link.href = myCanvas.toDataURL('image/png')link.download = 'draw.png'link.click()}// 改变颜色function colorChange(e: string | undefined) {console.log(e)strokeStyle = <string>e}// 改变线条粗细function numberChange(e: number) {lineWidth = e}// 橡皮擦,更换文本以及光标样式function eraser(e: string | undefined) {textFlag.value = !textFlag.valueconsole.log(textFlag.value)if (!textFlag.value){cursorIcon.value = "url(/src/assets/rubber.png),default"text.value = '画笔'strokeStyle = '#ffffff'}else{cursorIcon.value = 'url(/src/assets/pen2.png),default'text.value = '橡皮擦'colorChange(e)}}</script><style scoped lang="scss">html,body {width: 100%;height: 100%;margin: 0;box-sizing: border-box;overflow-y: hidden;overflow-x: hidden;}#content {width: 100%;height: 100%;position: relative;}.toolBar {width: 100vw;height: 50px;background-color: azure;box-shadow: 0 5px 2px #e8e8e8;position: absolute;top: 0;left: 0;display: flex;align-items: center;padding: 20px;box-sizing: border-box;}// 关闭按钮样式以及动画:霓虹灯效果.light {width: 40px;height: 30px;position: absolute;top: 30px;right: 30px;transform: translate(-50%, -50%);text-align: center;line-height: 30px;color: #03e9f4;font-size: 20px;text-transform: uppercase;transition: 0.5s;letter-spacing: 4px;cursor: pointer;overflow: hidden;}.light:hover {background-color: #03e9f4;color: #050801;box-shadow: 0 0 5px #03e9f4,0 0 25px #03e9f4,0 0 50px #03e9f4,0 0 200px #03e9f4;}.light div {position: absolute;}.light div:nth-child(1) {width: 100%;height: 2px;top: 0;left: -100%;background: linear-gradient(to right, transparent, #03e9f4);animation: animate1 1s linear infinite;}.light div:nth-child(2) {width: 2px;height: 100%;top: -100%;right: 0;background: linear-gradient(to bottom, transparent, #03e9f4);animation: animate2 1s linear infinite;animation-delay: 0.25s;}.light div:nth-child(3) {width: 100%;height: 2px;bottom: 0;right: -100%;background: linear-gradient(to left, transparent, #03e9f4);animation: animate3 1s linear infinite;animation-delay: 0.5s;}.light div:nth-child(4) {width: 2px;height: 100%;bottom: -100%;left: 0;background: linear-gradient(to top, transparent, #03e9f4);animation: animate4 1s linear infinite;animation-delay: 0.75s;}@keyframes animate1 {0% {left: -100%;}50%,100% {left: 100%;}}@keyframes animate2 {0% {top: -100%;}50%,100% {top: 100%;}}@keyframes animate3 {0% {right: -100%;}50%,100% {right: 100%;}}@keyframes animate4 {0% {bottom: -100%;}50%,100% {bottom: 100%;}}#myCanvas {cursor: v-bind(cursorIcon) ;overflow-y: hidden;overflow-x: hidden;}
</style>

🌟写在最后

以上就是实现简易画板的全部代码了,画出来的作品实在有点丑小伙伴们不要介意哈哈哈;大家也可以去试试,后续我会把一些图形加入进去实现拖拽等效果。喜欢的小伙伴们可以支持一下博主;你们的支持就是我创作的动力。各位小伙伴让我们 let’s be prepared at all times!

🌟JSON包里写函数,关注博主不迷路

原创不易,还希望各位大佬支持一下!
👍 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!


http://www.ppmy.cn/news/34603.html

相关文章

Java开发一年不到,来面试居然敢开口要20K,面完连8K都不想给~

前言 我的好朋友兼大学同学老伍家庭经济情况不错&#xff0c;毕业之后没两年自己存了点钱加上家里的支持&#xff0c;自己在杭州开了一家网络公司。由于公司不是很大所以公司大部分的开发人员都是自己面试的&#xff0c;近期公司发展的不错&#xff0c;打算扩招也面试了不少人…

NVM,一个管理nodejs版本的工具

目录 一、前言 二、NVM简介 三、下载、安装 四、检查安装是否成功 五、常见命令 六、安装的nodejs的位置 一、前言 作为一个后端开发者&#xff0c;在前端开发中&#xff0c;时常遇到一个问题&#xff1a; 就是node版本过高或过低的情况。这个时候它就会要求你卸载当前…

使用ArcGIS为科研论文制作正确、美观、详细的插图

科研论文中的插图&#xff0c;如果图中包含地理信息&#xff0c;那么首先需要在图中标明指北针、比例尺、图例&#xff0c;然后在此基础上再对作的图进一步的美化和修改。 来源&#xff1a;https://doi.org/10.1016/j.uclim.2022.101326 这种就是属于是最常见的研究区概况图&a…

vue更高效的工具-vite

目录 1.webpack 2.vite是什么 3.使用vite创建项目 4.最后总结 &#x1f43c;webpack 简单来说&#xff0c;Webpack是一个打包工具。 站在2018年的角度&#xff0c;成为一个优秀的前端工程师&#xff0c;除了要会写页面样式和动态效果之外&#xff0c;还需要会用主流的单页…

chatGPT爆火,什么时候中国能有自己的“ChatGPT“

目录 引言 一、ChatGPT爆火 二、中国何时能有自己的"ChatGPT" 三、为什么openai可以做出chatGPT? 四、结论 引言 随着人工智能技术的不断发展&#xff0c;自然语言处理技术也逐渐成为了研究的热点之一。其中&#xff0c;ChatGPT作为一项领先的自然语言处理技术…

裸机条件下写一个基于时间片轮转的多任务并发程序

目录前言A. 使用RTOSB.裸机多任务并发前言 在学习各种MCU的时候&#xff0c;都是用在main函数里写一个while(1){/* 执行代码 */}&#xff0c;这种方式只能一个函数运行完以后再运行另一个函数。 假设需求控制多个模块&#xff0c;如显示屏幕信息的同时控制电机&#xff0c;还要…

蓝桥杯倒计时 | 倒计时17天

作者&#x1f575;️‍♂️&#xff1a;让机器理解语言か 专栏&#x1f387;&#xff1a;蓝桥杯倒计时冲刺 描述&#x1f3a8;&#xff1a;蓝桥杯冲刺阶段&#xff0c;一定要沉住气&#xff0c;一步一个脚印&#xff0c;胜利就在前方&#xff01; 寄语&#x1f493;&#xff1a…

Redis缓存穿透、击穿、雪崩问题及解决方法

系列文章目录 Spring Cache的使用–快速上手篇 分页查询–Java项目实战篇 全局异常处理–Java实战项目篇 完善登录功能–过滤器的使用 上述只是部分文章&#xff0c;对该系列文章感兴趣的可以查看我的主页哦 文章目录系列文章目录前言一、缓存穿透1.1 问题引入1.2 解决方法1.…