前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手写原生代码专题 | 简易手写画板(二)

手写原生代码专题 | 简易手写画板(二)

作者头像
前端达人
发布2021-07-16 16:59:54
1.4K0
发布2021-07-16 16:59:54
举报
文章被收录于专栏:前端达人
大家好,本篇文章,小编将和大家完成一个手写画板的示例,这个例子比较简单只能画简单的线条,并能调节线条的粗细和颜色,还有一个清除的功能,具体示例如下视频所示:

一、基础知识复习

如视频所示,在这个示例中,我们用到了画布 canvas 相关的知识,比如创建画布、画圆形、画直线的基础知识,有了这些基础后,我们就能轻松完成本示例,示例效果如下视频所示。

1.1 创建画布

在 Html 文档中创建一个<canvas width="xx" height="xx">的画布,然后使用document.getElementById('canvas') 方法获取画布,接下来调用 canvas.getContext('2d') 使用2D的模式渲染画布,然后我们就可以在画布里进行画直线画圆操作了。

1.2 画直线

画一条直线,首先调用 beginPath() 绘制路径的起始点,使用 moveTo() 移动画笔,然后再使用 lineTo() 连接子路径的终点到x,y坐标,最后调用 ctx.stroke() 方法设置样式,就这样我们完成了画直线,相关示例代码如下:

代码语言:javascript
复制
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(100, 100);
ctx.stroke();

1.3 绘制圆形

CanvasRenderingContext2D.arc() 是 Canvas 2D API 绘制圆弧路径的方法。圆弧路径的圆心在 (x, y) 位置,半径为 r ,根据 anticlockwise (默认为顺时针)指定的方向从 startAngle 开始绘制,到 endAngle 结束。具体语法如下所示:

代码语言:javascript
复制
void ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
  • x:圆心的x坐标
  • y:圆心的y坐标
  • r:圆的半径
  • start:开始角度,0度为水平向右
  • end:结束角度
  • bool:是否逆时针绘制图形

示例代码如下所示:

代码语言:javascript
复制
// 获得元素对象 
var canvas = document.querySelector('canvas'); 
// 获得对象ctx, 画笔 
var ctx = canvas.getContext('2d'); 
// 绘制圆 
ctx.arc(300, 200, 100, 0, Math.PI * 2); 
// 着色---填充颜色,整个图形都有颜色,另一种为描边,只是有线条的路径 
// 设置填充颜色 
ctx.fillStyle = 'orange'; 
// 填充 
ctx.fill();

二、编写HTML代码

复习完基础知识后,我们开始编写具体的代码,HTML 结构比较简单,如视频示例所示,一个画布、两个增加线条粗细的加减按钮、一个显示粗细数值的文本、一个调整颜色的 HTML5 控件、一个清除画布内容的按钮,由于代码比较简单,这里不过多解释,示例代码如下:

代码语言:javascript
复制
<canvasid="canvas"width="800"height="700"></canvas>
<divclass="toolbox">
  <buttonid="decrease">-</button>
  <spanid="size">10</span>
  <buttonid="increase">+</button>
  <inputtype="color"id="color">
  <buttonid="clear">X</button>
</div>

完成后的效果如下图所示:

三、编写CSS代码

接下来,我们来编写相关的CSS样式,代码很简单,这里只是简单说明下:

  • 首先定义全局为 box-sizing: border-box 的盒子模型,然后使用弹性布局让画布容器垂直水平居中
  • 定义画布的边框的粗细为2px和颜色为蓝色
  • 定义最下方工具栏的背景色、及其水平布局的位置,使用 margin-left: auto; 让清除按钮的工具居右对齐

示例代码如下:

代码语言:javascript
复制
@importurl('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');

* {
    box-sizing: border-box;
}

body {
    background-color: #f5f5f5;
    font-family: 'Roboto', sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    margin: 0;
}

canvas {
    border: 2px solid steelblue;
}

.toolbox{
    background-color: steelblue;
    border: 1px solid slateblue;
    display: flex;
    width: 804px;
    padding: 1rem;
}

.toolbox> * {
    background-color: #fff;
    border: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    height: 50px;
    width: 50px;
    margin: 0.25rem;
    padding: 0.25rem;
    cursor: pointer;
}

.toolbox> *:last-child{
    margin-left: auto;
}

完成后的效果如下所示:

四、编写JS脚本

最后进入代码的核心部分,编写 JS 脚本,这里我们只是简单的实现画直线,为啥会用画圆形的API,主要为了让线条更加有手绘的感觉,在画线停顿的地方,有停顿的点,以线条的粗细为半径的圆点。

具体的思路如下:

  • 定义DOM对象变量:获取画布、增减线条粗细的按钮、颜色控件、显示线条粗细值、清除按钮
  • 然后定义一些变量值:初始化线条粗细的长度、鼠标是否按下的状态、线条颜色的默认值、颜色变量、鼠标的位置x,y 变量
  • 然后我们定义画圆形、画直线的相关方法:drawCircle(x,y)、drawLine(x1,y1,x2,y2)
  • 接着在画布上定义监听 mousedown 的方法,初始化鼠标位置的X,Y的值,更改鼠标是否按下的状态值为true。
  • 接着继续定义鼠标松开的状态 mouseup 方法,更改鼠标按下的状态为 false ,然后将鼠标 x,y 的位置值更改为 undefined
  • 继续定义监听在画布鼠标移动的方法 mousemove ,捕捉当前鼠标的x,y值,先以线条的宽度绘制圆形,然后以鼠标按下时的 x,y 的值为直线的起点,鼠标移动时获取鼠标的 x,y 值为终点绘制直线。绘制完成后更改x,y的值为当前鼠标的位置(不断更新直线的起点),这样就可以一直拖动鼠标绘制直线。
  • 最后在定义下面工具栏相关的增加颜色、更改线条粗细、清空画布的相关方法,由于逻辑比较简单,这里不再描述。

思路就聊到这里,下面给出脚本相关的代码,示例代码如下:

代码语言:javascript
复制
const canvas = document.getElementById('canvas');
const increaseBtn= document.getElementById('increase');
const decreaseBtn= document.getElementById('decrease');
const sizeEl=document.getElementById('size');
const colorEl=document.getElementById('color');
const clearEl=document.getElementById('clear');

constctx = canvas.getContext('2d');

let size = 10;
let isPressed=false;
colorEl.value='black';
let color = colorEl.value;
let x;
let y;

canvas.addEventListener('mousedown', (e) => {
    isPressed =true
    x = e.offsetX
    y = e.offsetY
})

canvas.addEventListener('mouseup',(e)=>{
    isPressed=false;

    x=undefined;
    y=undefined;
});

canvas.addEventListener('mousemove',(e)=>{
if(isPressed){
constx2 = e.offsetX;
consty2 = e.offsetY;

drawCircle(x2,y2);
drawLine(x,y,x2,y2);

x=x2;
y=y2;
    }
});

function drawCircle(x,y){
    ctx.beginPath();
    ctx.arc(x, y, size, 0, Math.PI * 2)
    ctx.fillStyle = color
    ctx.fill();
}

function drawLine(x1,y1,x2,y2){
    ctx.beginPath()
    ctx.moveTo(x1, y1)
    ctx.lineTo(x2, y2)
    ctx.strokeStyle = color;
    ctx.lineWidth = size * 2
    ctx.stroke()
}

function updateSizeOnScreen(){
    sizeEl.innerText = size;
}

increaseBtn.addEventListener('click',()=>{
    size+=5;if(size>50){
        size=50;
    }

updateSizeOnScreen();
});

decreaseBtn.addEventListener('click',()=>{
    size -= 5;
if(size<5){
        size=5;
    }
updateSizeOnScreen();
});

colorEl.addEventListener('change',(e)=>color=e.target.value);
clearEl.addEventListener('click',()=>ctx.clearRect(0,0,canvas.width,canvas.height));

结束语

好了,今天的项目就到这里结束了,想必大家都熟悉了如何手写一个简易的画布,基于这个基础我们可以增加更多的功能,比如三角图形、椭圆等形状的绘制,并能拖动形状,大家可以抽空完善下。

点击阅读原文,大家可以在线体验下交互效果(在PC端体验),如果想获取源码,请公众号回复 “a2” 获取本项目源码。

相关阅读

手写原生代码专题 | 图片拖拽效果(一)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、基础知识复习
    • 1.1 创建画布
    • 1.2 画直线
    • 1.3 绘制圆形
    • 二、编写HTML代码
    • 三、编写CSS代码
    • 四、编写JS脚本
    • 结束语
    • 相关阅读
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档