我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!
前言
终于等到了掘金的码上掘金活动!带着激动的心敲出了这个
我在敲代码之余也在做一些像素画,于是心想能不能将我们熟悉的PS界面取下一部分放到浏览器页面里呢?
像素画的重点在于概括,但一个好的像素画是需要一点颜色上的渐变来描述它的阴影,不过我迫于时间精力与个人技术不足等原因没有把调色板搞出来,仅放上了一些较为常用的颜色
演示
代码解读
正式开始解读代码前我们先画一个小熊,不为别的,就是觉得很可爱
HTML框架与CSS样式
HTML
<div id="main">
<div id="draw"></div> <!-- 画板 -->
<div id="tools"> <!-- 侧边工具栏(选色器) -->
<div id="now-color"></div> <!-- 展示现在选中的颜色 -->
<ul id="color-list"></ul> <!-- 展示所有可用颜色 -->
</div>
</div>
<div class="button-group">
<button id="show-hide-line">展示/隐藏网格</button>
<button id="clear">清空</button>
</div>
CSS
#main {
display: flex;
flex-direction: row;
width: 900px;
margin: 0 auto;
}
#draw {
width: 640px;
height: 640px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0 auto;
border: 1px solid rgb(211, 211, 211);
}
.pixel-line {
width: 38px;
height: 38px;
border: 1px solid rgb(211, 211, 211);
}
.pixel {
width: 40px;
height: 40px;
}
.button-group {
width: 200px;
margin: 0 auto;
}
.button-group button {
float: left;
}
#color-list {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
#tools {
width: 20%;
}
.color-item {
height: 20px;
width: 20px;
}
#now-color {
width: 80px;
height: 80px;
border: 1px solid rgb(147, 147, 147);
}
button {
height: 30px;
width: 100px;
border-radius: 15px;
}
li {
list-style: none;
margin-bottom: 3px;
display: block;
box-sizing: border-box;
}
- 整个HTML框架并没有太多的东西, 因为有太多的事件与重复的组件,因此大多步骤都在JS中完成
.pixel-line
为“显示网格”时添加的CSS样式,与此相对应的pixel
是“隐藏网格”时添加的CSS样式
创建像素画画板
let box = []
let color = '#000' //为color赋初值,后续仍会更改
var draw = document.getElementById('draw') //获取画板元素节点
for (let i = 0; i < 16; i++) { //创建像素点16*16
for (let j = 0; j < 16; j++) {
box.push(document.createElement("div"))
}
}
for (let i = 0; i < box.length; i++) {
box[i].className = 'pixel-line' //为元素添加class
box[i].onclick = function () {
box[i].style.backgroundColor = color //点击后将背景色改变为目前color的值
}
draw.appendChild(box[i]) //将像素块逐一挂载
}
- 整个画板是使用16 * 16个div所构成的,每个div上都被绑定了相应的点击事件
- 创建画板的流程大致为:开始 -> 创建元素节点 -> 将元素节点放入数组内方便后续管理 -> 为数组内的元素节点添加class名与点击事件 -> 将元素挂载至HTML中 -> 结束
- 点击事件也可仅为外层容器添加,我这里是给每个元素逐一添加,更加方便理解
box[i].style.backgroundColor = color
是指将背景色改为color
,其中color
的值初始为黑色,在下一模块“创建右侧色彩列表”中选中某一颜色后color
后会发生更改,以达到切换画笔颜色的效果box[i].className = 'pixel-line'
是指初始时默认网格是显示的,如上一部分“HTML框架与CSS”中所说的那样,该class会给元素加上border
与一个合适的宽高
其余详细内容请看代码注释
创建右侧色彩列表
var colorList = document.getElementById('color-list')//获取颜色列表结点
var nowColor = document.getElementById('now-color')//获取当前所选颜色元素节点
//color变量在上一模块已被创建
let colors = ['#FFF', '#000', '#FF0000', '#FFFF00', '#008B8B', '#7FFFD4', '#0000FF',
'#8A2BE2', '#A52A2A', '#7FFF00', '#FF7F50', '#6495ED', '#DC143C', '#00FFFF', '#B8860B',
'#A9A9A9', '#006400', '#FFDAB9', '#8B008B', '#FF00FF', '#483D8B', '#2F4F4F', '#D2B48C']
// ↑ 颜色列表 ↑
for (let i = 0; i < colors.length; i++) {
let colorItem = document.createElement("li") //创建元素节点li
colorItem.className = 'color-item' //为元素节点添加class
colorItem.style.backgroundColor = colors[i] //为元素节点添加背景色
colorItem.onclick = function () {
color = colors[i] //当选中该元素节点所代表的颜色时,将color的值变为当前所遍历到的colos[i]的值
nowColor.style.backgroundColor = colors[i]//当选中该元素节点所代表的颜色时,将展示目前所选中颜色的元素节点背景色改为当前所遍历到的colors[i]的值
}
if (i === 0) {
colorItem.style.border = '1px solid #000000'//如果是第一个,则需要添加板框,因为第一个是白色
}
colorList.appendChild(colorItem) //将颜色列表逐一挂载
}
- 因为没有做调色板,所以我们需要将所需要的颜色列出来,并存储为一个数组
colors
- 我认为将选中颜色高亮或添加边框的话不够突出,因此我使用了一般绘图软件所采用的方法:将所选颜色放大并展示在另一个醒目位置
- 白色与背景色相同,因此需要给白色添加一个边框以让它能被我们看见
- 选中颜色后,
color
将会发生改变,因此在上一模块“创建像素画板”中每个像素点所绑定的点击事件将会发生改变,以达到切换画笔颜色的效果
其余详细内容请看代码注释
为下方按钮组绑定事件
var lineButton = document.getElementById('show-hide-line')
var clearButton = document.getElementById('clear')
let showLine = true
lineButton.onclick = function () { //显示隐藏网格按钮
if (showLine) {
changeClass(box, 'pixel') //如果正在显示网格,则隐藏网格并将showLine复制为false
showLine = false
} else {
changeClass(box, 'pixel-line') //如果正在隐藏网格,则显示网格并将showLine赋值为true
showLine = true
}
}
clearButton.onclick = function () { //清空按钮
for (let i = 0; i < box.length; i++) {
box[i].style.backgroundColor = '#fff' //遍历box并将他们的背景色全部改为白色,box是存放所有像素点的数组
}
}
function changeClass(arr, className) { //遍历第一个形参并将每一项的className改为第二个形参的函数
for (let i = 0; i < arr.length; i++) {
arr[i].className = className
}
}
- 当点击显示隐藏网格按钮时,若正在显示网格则将所有像素点的class改为
pixel
,反之则改为pixel-line
- 当点击清空按钮时,将所有像素点的背景色统一改为白色
其余详细内容请看代码注释
这样所有的部分都已经介绍完啦~祝大家中秋节快乐!