持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
今天做需求时,遇到一个需要用户可进行签名,并且可以通过选择自己喜爱的颜色,让签名的线条颜色变成自己选择的颜色,首先我们需要来分析一下,签名肯定是通过canvas进行实现的,选择签名线条颜色,我们这里使用盒子做出一个颜料盒子的样式,当用户进行点击颜料盒子时,我们就改变掉canvas的绘制线条颜色
页面结构
我们先用一个大盒子把整个内容都包含起来,canvas作为签名板,ul元素作为颜料大盒子,最后我们通过js的方式把颜料小盒子追加进去
<div id="app">
<!-- 签名板 -->
<canvas id="canvas" width="700" height="400">当前浏览器不支持canvas,请更换浏览器!</canvas>
<!-- 颜料大盒子 -->
<ul id="palette"></ul>
</div>
样式
我们先将默认的所有元素的内边距外边距全部置为0,然后通过grid布局让里面的元素水平居中显示,然后在设置颜料盒子的样式,颜料盒子这里我们也使用到了grid布局,通过该方式让颜料小盒子在颜料盒子中一行展示并且和其他颜料小盒子拥有间隔
* {
margin: 0;
padding: 0;
}
//大盒子
#app {
margin-top: 100px;
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-gap: 30px;
justify-items: center;
}
#app canvas {
background: #7ff585;
}
//颜料盒子
#palette {
width: 700px;
padding: 10px 0;
border-radius: 10px;
background: #f0e87d;
display: grid;
grid-template-columns: repeat(auto-fit, 70px);
grid-gap: 20px;
justify-content: center;
}
//颜料小盒子
#palette li {
width: 70px;
height: 70px;
border-radius: 50%;
list-style: none;
user-select: none;
cursor: pointer;
}
逻辑实现
// 声明颜料盒子所有颜色
const COLOR = ['#000', 'red', 'blue', 'yellow'];
// 存放当前选择的是哪一个颜料小盒子
let colorIndex = 0;
// 根据颜料盒子数组中的颜色渲染出li元素然后放到颜料大盒子中
function Tinting() {
// 获取颜料大盒子
const PALETTE = document.getElementById('palette');
// 声明文档片段,用于存放颜料盒子元素
let COLORHTML = new DocumentFragment();
// 进行创建颜料小盒子,并追加到文档片段中
COLOR.map(R => {
// 创建li元素
let lis = document.createElement('li');
// 给li元素设置背景颜色
lis.style.background = R;
// 追加到文档片段中
COLORHTML.appendChild(lis);
});
// 将文档片段追加到颜料大盒子中
PALETTE.appendChild(COLORHTML);
// 给每个小盒子追加点击事件
TintingItemClick();
}
// 颜料小盒子进行点击
function TintingItemClick() {
// 获取到每一个颜料小盒子
const TINTINGITEM = document.querySelectorAll('#palette li');
// 通过循环的方式进行添加事件
TINTINGITEM.forEach((M, index) => {
// 给每个颜料小盒子添加点击事件
M.onclick = function () {
console.log(index);
colorIndex = index;
}
})
}
// 签名板函数
function autograph() {
// 获取canvas元素
const CANVAS = document.getElementById('canvas');
// 通过canvas下面的getContext属性进行判断当前的浏览器是否支持该元素,不支持则退出不进行执行
if (!CANVAS.getContext) return;
// 获取canvas绘制上下文
var CANVASCONTENT = CANVAS.getContext('2d');
// 当鼠标在canvas元素中按下
CANVAS.onmousedown = function (event) {
// 获取鼠标按下时的事件对象
let e = event || window.event;
// 开启绘制新路径
CANVASCONTENT.beginPath()
// 设置绘制开始点(鼠标相对于浏览器位置-事件对象相对于浏览器的位置)=当前鼠标在元素中的坐标位置
CANVASCONTENT.moveTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
// 当前页面中鼠标进行移动时
document.onmousemove = function (event) {
let e = event || window.event;
// 保存当前canvas画布状态
CANVASCONTENT.save()
console.log(COLOR[colorIndex], colorIndex);
// 设置绘制线条宽度
CANVASCONTENT.lineWidth = 5;
CANVASCONTENT.lineCap = 'round';
// 设置默认绘制线颜色
CANVASCONTENT.strokeStyle = COLOR[colorIndex];
// 绘制点(鼠标相对于浏览器位置-事件对象相对于浏览器的位置)=当前鼠标在元素中的坐标位置
CANVASCONTENT.lineTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop)
// 开始绘制线
CANVASCONTENT.stroke()
// 将canvas画布状态进行取出
CANVASCONTENT.restore()
}
// 当鼠标松开时,取消当前的移动事件
document.onmouseup = function () {
document.onmousemove = null
}
}
}
//当前页面加载完成后进行执行
window.onload = function () {
//添加颜料小盒子
Tinting()
//canvas签名功能执行
autograph()
}
代码我放到码上掘金上了,感兴趣的大家可以看一下!
坚持努力,无惧未来!