网站首页 > 知识剖析 正文
任何一个画板软件都有绘制直线的功能,如果想要基于web实现鼠标画直线该怎么做哪?本文基于html canvas介绍一种实现鼠标绘制直线的方法,最终效果如下。
画一条直线
首先,我们来尝试先做到画单条直线,html canvas提供了画线的方法,这里稍作封装,draw_line方法使用canvas上下文提供的方法绘制一条直线,start_vector、end_vector使用向量来表示起点和终点。
// 构造向量[x,y]
function make_vect(x, y) {
return [x ,y];
}
// 获取向量x坐标
function xcor_vect(vector) {
return vector[0];
}
// 获取向量y坐标
function ycor_vect(vector) {
return vector[1];
}
function draw_line(start_vector, end_vector) {
ctx.beginPath();
//移动到起点
ctx.moveTo(xcor_vect(start_vector), ycor_vect(start_vector));
//绘制起点到终点的直线段
ctx.lineTo(xcor_vect(end_vector), ycor_vect(end_vector));
ctx.stroke();
}
有了上面的draw_line方法,只要通过监听鼠标按下事件获取鼠标按下时的坐标点作为起点,再获取鼠标释放时的坐标点作为终点,然后调用draw_line方法就可以做到画一条直线了,示例代码如下。
...以上代码省略
// container为html中canvas元素id
var canvas = document.getElementById("container");
var ctx = canvas.getContext("2d");
// 监听鼠标按下事件
canvas.onmousedown = function(event) {
//按下鼠标获取起点
let start_point = make_vect(event.clientX, event.clientY);
// 监听鼠标松开事件
canvas.onmouseup = function(event) {
// 释放鼠标获取终点
let end_point = make_vect(event.clientX, event.clientY);
draw_line(start_point, end_point);
}
}
开启web服务后访问页面,选择canvas合适位置点击鼠标并拖动可以绘制一条直线,但是只有鼠标释放时直线才会绘制出来,这样的体验显然是不好的,我们希望直线能够一直跟踪鼠标的轨迹。
跟踪鼠标轨迹
要跟踪鼠标轨迹,还需要监听鼠标移动事件,在鼠标拖动的每个时刻都将鼠标位置作为终点进行画线,代码如下:
// container为html中canvas元素id
var canvas = document.getElementById("container");
var ctx = canvas.getContext("2d");
var pressed = false;
// 监听鼠标按下事件
canvas.onmousedown = function(event) {
//按下鼠标获取起点
let start_point = make_vect(event.clientX, event.clientY);
pressed = true;
// 监听鼠标移动事件
canvas.onmousemove = function(event) {
//只有鼠标按下时拖动才需要画线
if (pressed) {
let end_point = make_vect(event.clientX, event.clientY);
draw_line(start_point, end_point);
}
}
// 监听鼠标松开事件
canvas.onmouseup = function(event) {
let end_point = make_vect(event.clientX, event.clientY);
draw_line(start_point, end_point);
pressed = false;
}
}
再次测试发现结果很离谱,竟然画出了很多条线,但值得肯定的是这样做到了跟踪鼠标的拖动轨迹,之所以会出现很多条线,是因为每个鼠标拖动位置的直线都已经画在画布上了,只要每次鼠标移动事件处理前把之前已画的线擦除掉就可以了。
// container为html中canvas元素id
var canvas = document.getElementById("container");
var ctx = canvas.getContext("2d");
var pressed = false;
// 监听鼠标按下事件
canvas.onmousedown = function(event) {
//按下鼠标获取起点
let start_point = make_vect(event.clientX, event.clientY);
pressed = true;
// 监听鼠标移动事件
canvas.onmousemove = function(event) {
//只有鼠标按下时推动才需要画线
if (pressed) {
// 先擦除画布
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
let end_point = make_vect(event.clientX, event.clientY);
draw_line(start_point, end_point);
}
}
// 监听鼠标松开事件
canvas.onmouseup = function(event) {
let end_point = make_vect(event.clientX, event.clientY);
draw_line(start_point, end_point);
pressed = false;
}
}
再次测试发现可以很方便的使用鼠标画一条直线了,而且可以实时跟踪鼠标的位置来调整直线直到鼠标释放才会确定绘制哪条直线。
保留痕迹
还有一个问题需要解决,现在画完一条直线后,继续画下一条直线就会把之前的清掉,画布上始终只有一条直线,这样的画板是没什么价值的,我们需要画布既要能够实时跟踪当前绘制直线的样子,还要能够保留以前绘制好的直线,就像本文开头展示的效果一样。显然,可以通过定义一个数组来存放历史直线的坐标数据,每次清空画布后再把它们绘制出来就可以轻松做到想要的功能了。完整代码如下:
// 构造向量[x,y]
function make_vect(x, y) {
return [x ,y];
}
// 获取向量x坐标
function xcor_vect(vector) {
return vector[0];
}
// 获取向量y坐标
function ycor_vect(vector) {
return vector[1];
}
function draw_line(start_vector, end_vector) {
ctx.beginPath();
//移动到起点
ctx.moveTo(xcor_vect(start_vector), ycor_vect(start_vector));
//绘制起点到终点的直线段
ctx.lineTo(xcor_vect(end_vector), ycor_vect(end_vector));
ctx.stroke();
}
// 构造一条线段
function make_segment(start, end) {
return [start, end];
}
// 获取线段的起点
function start_segment(segment) {
return segment[0];
}
// 获取线段的终点
function end_segment(segment) {
return segment[1];
}
// 绘制线段列表中的所有直线段
function segments_painter(segment_list) {
for (let i = 0; i < segment_list.length; i++) {
let segment = segment_list[i];
draw_line(start_segment(segment), end_segment(segment));
}
}
var canvas = document.getElementById("container");
var ctx = canvas.getContext("2d");
var pressed = false;
// 存放所有绘制的直线数据
var segment_list = [];
// 监听鼠标按下事件
canvas.onmousedown = function(event) {
pressed = true;
let start_point = make_vect(event.clientX, event.clientY);
let current_line;
// 监听鼠标移动事件
canvas.onmousemove = function(event) {
if (pressed) {
// 擦除画布
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
let end_point = make_vect(event.clientX, event.clientY);
current_line = make_segment(start_point, end_point);
// 画当前直线
segments_painter([current_line]);
// 画历史直线
segments_painter(segment_list);
}
}
// 监听鼠标松开事件
canvas.onmouseup = function(event) {
pressed = false;
// 鼠标释放表示当前直线确定,存放到直线列表中
segment_list.push(current_line);
}
}
- 上一篇: leaferjs,全新的 Canvas 渲染引擎
- 下一篇: HTML DOM Meta 对象
猜你喜欢
- 2025-01-05 leaferjs,全新的 Canvas 渲染引擎
- 2025-01-05 「从头到脚」WebRTC + Canvas 实现一个双人协作的共享画板
- 2025-01-05 一文解读前端实现电子签名
- 2025-01-05 Javascript图形(一):阿基米德螺线
- 2025-01-05 有趣的分形(二):六边形雪花
- 2025-01-05 HTML5学习笔记-绘制变形图形之组合效果
- 2025-01-05 游戏开发之旅-JavaScript绘制图形
- 2025-01-05 用三角函数sin和cos画模拟雷达示意图的html代码解析
- 2025-01-05 如何用2 KB代码实现3D赛车游戏?2kPlus Jam大赛了解一下
- 2025-01-05 贝塞尔曲线是什么?如何用 Canvas 绘制三阶贝塞尔曲线?
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)