使用JavaScript实现一个在线画板
一、引言
随着Web技术的发展,网页上的交互性变得越来越重要。一个在线画板是一个很好的例子,它允许用户在网页上自由创作。在这篇博客中,我们将使用HTML5的Canvas元素和JavaScript来实现一个简单的在线画板
二、HTML结构
首先,我们需要构建HTML结构来容纳画板的内容。
<!DOCTYPE html>
<html>
<head> <title>在线画板</title> <style> #canvas { border: 1px solid black; } </style>
</head>
<body> <canvas id="canvas" width="800" height="600"></canvas> <script src="script.js"></script>
</body>
</html>
这里我们有一个Canvas元素,用于绘制内容。我们将使用JavaScript来处理用户的交互。
三、JavaScript代码
接下来,我们来编写JavaScript代码来实现画板的功能。首先,我们需要获取Canvas元素并获取其上下文
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
然后,我们可以添加事件监听器来处理鼠标的移动和点击事件:
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
接下来,我们需要定义几个函数来处理绘图逻辑:
startDrawing(event): 当鼠标按下时触发,记录起始点。draw(event): 当鼠标移动时触发,绘制线条。stopDrawing(): 当鼠标抬起或移出画板时触发,停止绘制。
这些函数的代码如下:
let isDrawing = false;
let lastX = 0;
let lastY = 0; function startDrawing(event) { isDrawing = true; [lastX, lastY] = [event.clientX, event.clientY];
} function draw(event) { if (!isDrawing) return; ctx.beginPath(); ctx.moveTo(lastX, lastY); [lastX, lastY] = [event.clientX, event.clientY]; ctx.lineTo(lastX, lastY); ctx.stroke();
} function stopDrawing() { isDrawing = false;
}
最后,为了让画板支持多种颜色和线条粗细,我们可以添加一些额外的功能:选择颜色和线条粗细,以及清除画板。以下是实现这些功能的代码:
setColor(color): 设置画笔颜色。setLineWidth(width): 设置线条粗细。clearCanvas(): 清除画板。
// 设置画笔颜色
function setColor(color) { ctx.strokeStyle = color;
} // 设置线条粗细
function setLineWidth(width) { ctx.lineWidth = width;
} // 清除画板
function clearCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// 获取canvas元素,并将其引用赋值给变量canvas
const canvas = document.getElementById('canvas'); // 获取canvas元素的2d渲染上下文,并将其引用赋值给变量ctx
const ctx = canvas.getContext('2d'); // 声明一个变量isDrawing,并设置其初始值为false。这个变量用于判断用户是否正在画板上绘制
let isDrawing = false; // 声明一个变量lastX,并设置其初始值为0。这个变量用于存储上一个点的x坐标
let lastX = 0; // 声明一个变量lastY,并设置其初始值为0。这个变量用于存储上一个点的y坐标
let lastY = 0; // 声明一个变量lineColor,并设置其初始值为'black'。这个变量用于存储线条的颜色
let lineColor = 'black'; // 声明一个变量lineWidth,并设置其初始值为1。这个变量用于存储线条的宽度
let lineWidth = 1; // 声明一个变量lineStyle,并设置其初始值为'solid'。这个变量用于存储线条的样式(实线、虚线等)
let lineStyle = 'solid'; // 声明一个变量fillStyle,并设置其初始值为'transparent'。这个变量用于存储填充样式(颜色或透明)
let fillStyle = 'transparent'; // 声明一个变量isErasing,并设置其初始值为false。这个变量用于判断用户是否正在使用橡皮擦功能
let isErasing = false; // 声明一个临时上下文tempCtx,用于在清除画板时绘制与原画板相同的内容以进行擦除操作
let tempCtx; // 临时上下文用于擦除操作 // 定义startDrawing函数,该函数在用户按下鼠标时被调用。它设置isDrawing为true并存储当前鼠标位置作为上一个点的坐标
function startDrawing(event) { isDrawing = true; [lastX, lastY] = [event.clientX, event.clientY];
} // 定义draw函数,该函数在用户移动鼠标时被调用。它根据isDrawing的值绘制线条,并根据需要设置线条的颜色、宽度和样式等属性
function draw(event) { if (!isDrawing) return; // 如果用户没有在画板上绘制,则不执行任何操作 ctx.beginPath(); // 开始绘制新的路径或线段 ctx.moveTo(lastX, lastY); // 将画笔移动到上一个点的位置 ctx.lineTo(event.clientX, event.clientY); // 将画笔移动到当前鼠标位置,并创建一条线段连接这两个点 ctx.strokeStyle = lineColor; // 设置线条的颜色为lineColor变量的值 ctx.lineWidth = lineWidth; // 设置线条的宽度为lineWidth变量的值 ctx.lineStyle = lineStyle; // 设置线条的样式为lineStyle变量的值(例如实线、虚线等) ctx.stroke(); // 绘制线条(执行上一步设置的线条属性) ctx.fillStyle = fillStyle; // 设置填充样式为fillStyle变量的值(例如颜色或透明) ctx.fill(); // 填充形状(如果设置了填充样式) [lastX, lastY] = [event.clientX, event.clientY]; // 更新上一个点的坐标为当前鼠标位置,以便下次绘制时使用正确的起点
} // 定义stopDrawing函数,该函数在用户释放鼠标按钮时被调用。它设置isDrawing为false,表示用户已经停止绘制操作
function stopDrawing() { isDrawing = false;
} // 定义clearCanvas函数,该函数在用户点击“清除画板”按钮时被调用。它使用clearRect方法清除画板上的所有内容,并重新初始化所有绘图相关的变量和状态(例如上一个点的坐标、线条颜色、线条宽度等)
function clearCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除整个画板区域的内容和所有绘制的线条和形状等图形元素,恢复到初始状态
}
相关文章:
使用JavaScript实现一个在线画板
一、引言 随着Web技术的发展,网页上的交互性变得越来越重要。一个在线画板是一个很好的例子,它允许用户在网页上自由创作。在这篇博客中,我们将使用HTML5的Canvas元素和JavaScript来实现一个简单的在线画板 二、HTML结构 首先,…...
微信小程序如何自定义导航栏,怎么确定导航栏及状态栏的高度?导航栏被刘海、信号图标给覆盖了怎么办?
声明:本文为了演示效果,颜色采用的比较显眼,可根据实际情况修改颜色 问题描述 当我们在JSON中将navigationStyle设置成custom后,当前页面的顶部导航栏就需要我们制作了,但出现了一下几个问题: 导航栏的高…...
Spring Boot “How-to“ 指南中文文档-上
本文为官方文档直译版本。原文链接 篇幅较长,遂分两篇 Spring Boot "How-to" 指南中文文档-上 引言Spring Boot Application创建自己的FailureAnalyzer(故障分析器)自动配置故障诊断启动前自定义环境或应用程序上下文构建 Applicat…...
快速了解spring boot中的@idempotent注解
目的:一定时间内,同样的请求(业务参数相同)访问同一个接口,则只能成功一次,其余被拒绝 幂等实现原理就是利用AOP面向切面编程,在执行业务逻辑之前插入一个方法,生成一个token,存入redis并插入到…...
【手把手带你玩转MyBatis】基础篇:挥洒自如的Java接口与注解
目录 1. MyBatis接口与Mapper接口 2. 注解属性解析 3. 使用接口实现数据访问 内容: 在MyBatis框架中,除了传统的XML映射文件方式之外,还支持使用Java接口和注解进行SQL映射。这种方式简化了开发流程,使得代码更简洁、直观&a…...
uniapp中u-switch子组件点击触发到父组件(阻止事件冒泡)
解决方法:在u-switch 外面包一个view标签,并使用tap.stop.prevent 可以阻止事件冒泡 .stop 阻止事件继续传播到父元素,prevent阻止事件默认行为 <view tap.stop.prevent><u-switch v-model"val_switch" change"cha…...
2024“华数杯”(A题)|放射性废水扩散|国际大学生数学建模竞赛建模解析,小鹿学长带队指引全代码文章与思路
我是小鹿学长,就读于上海交通大学,截至目前已经帮200人完成了建模与思路的构建的处理了~ 完整内容可以在文章末尾领取! 这回带大家体验一下2024“华数杯”国际大学生数学建模竞赛呀! 此题涉及到放射性废水从日本排放…...
EtherCAT主站SOEM -- 16 --Qt-Soem通过界面按键控制电机转圈圈PV模式
EtherCAT主站SOEM -- 16 --Qt-Soem通过界面按键控制电机转圈圈 0 QT-SOEM视频预览及源代码下载:0.1 QT-SOEM视频预览0.2 QT-SOEM源代码下载1 程序文件修改替换1.1 allvalue.h1.2 motrorcontrol.h1.3 mainwindow.cpp1.4 motrorcontrol.cpp2 ui界面显示该文档修改记录:总结上下…...
芯品荟 | 电脑机箱键盘副屏市场调研报告
一.产品简介 1.带TFT彩屏电脑机箱 2.带小TFT彩屏电脑键盘 为什么电脑机箱&键盘,要带屏? 带屏的电脑机箱&键盘客户群体? 电竞玩家、设计师、电子发烧友、股民...... 二、市场规模 中国电脑机箱年产量约6000万台,键盘年产量约3亿…...
Mysql root 密码重置详解
文章目录 1 概述1.1 前言1.2 mysql 版本查询 2 windows 操作系统2.1 mysql 8 及以上版本2.1.1 关闭 mysql 服务2.1.2 通过无认证方式启动 mysql2.1.3 新开窗口,登录 mysql,重置密码 1 概述 1.1 前言 不同的操作系统(如:windows、…...
微信小程序:发送小程序订阅消息
文档:小程序订阅消息(用户通过弹窗订阅)开发指南 目录 步骤一:获取模板 ID步骤二:小程序端获取参数2.1、获取消息下发权限2.2、获取登录凭证(code) 步骤三:后端调用接口下发订阅消息…...
ROS第 6 课 编写简单的订阅器 Subscriber
文章目录 第 6 课 编写简单的订阅器 Subscriber1. 编写订阅者节点2. 测试发布者和订阅者 第 6 课 编写简单的订阅器 Subscriber 订阅器是基于编辑了发布器的基础上创建的,只有发布了消息,才有可能订阅。若未编辑发布器,可前往"ROS第5课 …...
网络安全技术新手入门:利用永恒之蓝获取靶机控制权限
目录 前言 一、搜索永恒之蓝可用模块 二、使用攻击模块 三、配置攻击模块 四、攻击 五、总结 前言 相关法律声明:《中华人民共和国网络安全法》第二十七条 任何个人和组织不得从事非法侵入他人网络、干扰他人网络正常功能、窃取网络数据等危害网络安全的活动&…...
MYSQL高性能索引
正确的选择和创建索引是实现高性能查询的基础,以下是高效使用索引的方法 演示的sql 独立的列 独立的列指的是索引既不是表达式的一部分也不是函数的参数。 mysql> select actor_id from actor where actor_id 1 5;mysql> SELECT actor_id FROM actor WHER…...
2024年华数杯国际赛A题赛题
问题A:来自日本的放射性废水 背景 2011年3月,日本东海岸发生的地震引发了福岛第一核电站的事故。一场大规模海啸摧毁了该核电站的冷却系统,导致三个核反应堆熔毁,核燃料碎片熔化。为了冷却熔化的核燃料,海水不断地注入…...
EMC整改
生产的工艺一致性,所使用元器件的一致性,实验室测试设备不确定度,传导骚扰的整改至少要有4dB的裕量;辐射骚扰的整改至少要有6dB的裕量。 电压波动和闪烁: 对一般开关电源来说很少出现电压波动和闪烁项目超标。若该项目出问题,很大…...
uniCloud ---- uni-captch实现图形验证码
目录 用途说明 组成部分 目录结构 原理时序 云端一体组件介绍 验证码配置(可选): 普通验证码组件 公共模块 云函数公用模块 项目实战 创建云函数 创建注册页 创建云函数 关联公用模块 uni-captcha 刷新验证码 自定义实现 验…...
LLaMa2 Chat gpt 大模型本地部署初体验
一直想在自己电脑或者测试环境随便找台服务器尝试部署一下“大模型”,但“大模型”对于内存和GPU的要求令人望而却步,层出不穷的各种术语也令人困惑,有点难以下手。 经过一段时间,在百度千帆大模型平台、讯飞星火大模型平台、魔搭…...
leetcode-344. 反转字符串、9. 回文数
题目1: 解题方法 直接用reverse()即可 代码: class Solution(object):def reverseString(self, s):""":type s: List[str]:rtype: None Do not return anything, modify s in-place instead."""return s.reverse()如果不…...
卖二手的教训:坏了要及时售后
自去年12月开始,把手头闲置或坏的电子产品(CPU风扇,充电宝,台灯等),统统卖掉了。每个还是赚钱了,不多,主要就是想卖掉,好的继续发挥余热,坏的有人修好利用。 …...
UVa 275 Expanding Fractions
题目分析 本题要求计算两个正整数的除法的小数展开形式,其中分子小于分母,分母小于 100010001000。输入以 0 0 结束。 对于每个分数,需要输出其小数部分(从小数点开始),并且: 如果小数是有限的&…...
实测:把Ubuntu 22.04装进移动固态硬盘,读写速度到底怎么样?附性能优化技巧
移动固态硬盘上的Ubuntu 22.04性能实测与深度调优指南 当我们将完整的Ubuntu系统装进移动固态硬盘时,最令人忐忑的莫过于性能表现——这个装在口袋里的系统能否像内置硬盘一样流畅?本文将通过一系列严谨测试,揭示移动固态硬盘运行Ubuntu的真…...
3大突破性技术:如何实现Cursor AI编程助手永久免费使用
3大突破性技术:如何实现Cursor AI编程助手永久免费使用 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your tr…...
GPT5.5怎么切中文界面设置教程一看就会
做多模型中文能力对比测试时用了AI模型聚合平台,一站接入多个模型方便对比不同模型的中文输出质量。GPT-5.5上线快一个月了。注册完打开一看全是英文界面,切了半天没找到在哪改。搜了一圈教程要么过时要么步骤不全。这次把2026年5月最新的中文设置全流程…...
国产芯片独角兽IPO热潮来袭,百度昆仑芯与阿里平头哥角逐RISC-V弯道超车机遇
国产芯片好消息不断,长鑫科技与长江存储启动IPO,百度昆仑芯、阿里平头哥也有相关动作。互联网大厂钟情自研AI芯片,昆仑芯与平头哥发展路径不同,RISC-V或是弯道超车关键。国产芯片独角兽登场被誉为“存储双雄”的长鑫科技与长江存储…...
JMeter接口测试实战:登录态、参数化、业务链路与签名处理
1. 为什么接口测试不能只靠“点点点”——JMeter不是高级版Postman,而是压测与验证的双刃剑很多人第一次听说JMeter,是在同事甩来一句“你那个接口要压测,用JMeter跑一下”。结果打开软件,看到满屏英文、树形结构、线程组、监听器…...
视频硬字幕提取革命:87种语言本地OCR识别,让字幕提取从未如此简单
视频硬字幕提取革命:87种语言本地OCR识别,让字幕提取从未如此简单 【免费下载链接】video-subtitle-extractor 视频硬字幕提取,生成srt文件。无需申请第三方API,本地实现文本识别。基于深度学习的视频字幕提取框架,包含…...
Rust 语言特性:impl 与 方法
在其他语言里,我们通常不会特别区分“函数”和“方法”两个术语,特别是在 Java 这类纯面向对象编程语言里。因为“函数”和“方法”是一回事。在 C 里,情形稍有不同,因为它是面向对象和面向过程的多范式语言,即有独立存…...
英特尔现代代码开发挑战:实战性能优化与工具链应用指南
1. 项目概述:一场面向开发者的实战演练最近深度参与并复盘了英特尔举办的“现代代码开发挑战”网络研讨会,感触颇深。这远不止是一场普通的技术分享会,而是一个精心设计的、让开发者亲手“触摸”现代硬件性能潜力的实战沙盒。如果你是一名C/C…...
昇腾CANN ops-blas 仓:GEMM 算子的高性能实现
前言 矩阵乘法是深度学习里最核心的操作,没有之一。Transformer 的 Attention 要做 QK.T 和 PV,FFN 要做两 个 MatMul。GEMM(General Matrix Multiply)就是专门优化矩阵乘的算子。ops-blas 仓是 CANN 的线性代数基础算子库&#x…...
