朋友们,美好的一天!前言
网上冲浪使我想到了这一点。后来我发现了一篇关于它如何工作的文章。看起来没什么特别的-用CSS绘制的皮卡丘。这种技术称为像素艺术(pixel art?)。让我震惊的是过程的复杂性。每个单元都是手工绘制的(嗯,差不多;因为有预处理器,在这种情况下是Sass)。当然,美丽需要牺牲。但是,开发人员是懒惰的动物。因此,我想到了自动化。因此出现了我所谓的Pixel Art Maker。条件
我们想要得到什么?我们需要一个程序,该程序可以生成给定数量的单元格,并可以使用任意颜色对其进行着色。以下是网上的一些示例:附加功能:- 单元格形状-正方形或圆形
- 像元宽度(以像素为单位)
- 单元数
- 背景颜色
- 着色的颜色
- 画布创建功能
- 手机号码显示功能
- 图像保存/删除功能
- 帆布清洁功能
- 帆布清除功能
我们将在编码过程中讨论较小的细节。所以走吧标记
为了实现必要的功能,我们的HTML应该如下所示:
<div class="tools">
<div>
<p>Shape Form</p>
<select>
<option value="squares">Square</option>
<option value="circles">Circle</option>
</select>
</div>
<div class="numbers">
<div>
<p>Shape Width <br> <span>(from 10 to 50)</span></p>
<input type="number" value="20" class="shapeWidth">
</div>
<div>
<p>Shape Number <br> <span>(from 10 to 50)</span></p>
<input type="number" value="30" class="shapeNumber">
</div>
</div>
<div class="colors">
<div>
<p>Background Color</p>
<input type="color" value="#ffff00" required class="backColor">
</div>
<div>
<p>Shape Color</p>
<input type="color" value="#0000ff" class="shapeColor">
</div>
</div>
<div class="buttons">
<input type="button" value="Generate Canvas" class="generate">
<input type="button" value="Show/Hide Numbers" class="show">
<input type="button" value="Save/Delete Image" class="save">
<input type="button" value="Clear Canvas" class="clear">
<input type="button" value="Delete Canvas" class="delete">
</div>
</div>
<canvas></canvas>
凭经验确定单元格的宽度和数量的值的范围(极限)。实验表明,由于细节过多(对于宽度<10的值),性能下降(对于数量> 50的值)等原因,较小/较大的值是不切实际的。款式
我们没有什么特别的风格。CSS:* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
align-content: flex-start;
}
h1 {
width: 100%;
text-align: center;
font-size: 2.4em;
color: #222;
}
.tools {
height: 100%;
display: inherit;
flex-direction: column;
margin: 0;
font-size: 1.1em;
}
.buttons {
display: inherit;
flex-direction: column;
align-items: center;
}
div {
margin: .25em;
text-align: center;
}
p {
margin: .25em 0;
user-select: none;
}
select {
padding: .25em .5em;
font-size: .8em;
}
input,
select {
outline: none;
cursor: pointer;
}
input[type="number"] {
width: 30%;
padding: .25em 0;
text-align: center;
font-size: .8em;
}
input[type="color"] {
width: 30px;
height: 30px;
}
.buttons input {
width: 80%;
padding: .5em;
margin-bottom: .5em;
font-size: .8em;
}
.examples {
position: absolute;
top: 0;
right: 0;
}
a {
display: block;
}
span {
font-size: .8em;
}
canvas {
display: none;
margin: 1em;
cursor: pointer;
box-shadow: 0 0 1px #222;
}
Java脚本
定义画布及其上下文(2D绘图上下文):let c = document.querySelector('canvas'),
$ = c.getContext('2d')
我们找到用于创建画布的按钮,并将click事件处理程序挂在其上:document.querySelector('.generate').onclick = generateCanvas
所有其他代码将在generateCanvas函数中:function generateCanvas(){
...
}
我们确定形状,宽度,水平量和总量(画布在水平和垂直方向上代表相同数量的单元格),以及背景色:
let shapeForm = document.querySelector('select').value
let shapeWidth = parseInt(document.querySelector('.shapeWidth').value)
let shapeNumber = parseInt(document.querySelector('.shapeNumber').value)
let shapeAmount = Math.pow(shapeNumber, 2)
let backColor = document.querySelector('.backColor').value
我们确定画布的大小并为其设置适当的属性(请记住,通过属性设置了正确的画布大小):
let W = H = shapeWidth * shapeNumber
c.setAttribute('width', W)
c.setAttribute('height', H)
一些其他设置:
let border = 1
let borderColor = 'rgba(0,0,0,.4)'
let isShown = false
if (shapeWidth < 10 || shapeWidth > 50 || shapeNumber < 10 || shapeNumber > 50 || isNaN(shapeWidth) || isNaN(shapeNumber)) {
throw new Error(alert('wrong number'))
} else if (shapeForm == 'squares') {
c.style.display = 'block'
squares()
} else {
c.style.display = 'block'
circles()
}
这是squares函数的样子:function squares() {
let x = y = 0
let squares = []
let w = h = shapeWidth
addSquares()
function Square(x, y) {
this.x = x
this.y = y
this.color = backColor
this.isSelected = false
}
function addSquares() {
for (let i = 0; i < shapeAmount; i++) {
let square = new Square(x, y)
x += w
if (x == W) {
y += h
x = 0
}
squares.push(square)
}
drawSquares()
}
function drawSquares() {
$.clearRect(0, 0, W, H)
for (let i = 0; i < squares.length; i++) {
let square = squares[i]
$.beginPath()
$.rect(square.x, square.y, w, h)
$.fillStyle = square.color
$.lineWidth = border
$.strokeStyle = borderColor
$.fill()
$.stroke()
if (isShown) {
$.beginPath()
$.font = '8pt Calibri'
$.fillStyle = 'rgba(0,0,0,.6)'
$.fillText(i + 1, square.x, (square.y + 8))
}
}
}
c.onclick = select
function select(e) {
let clickX = e.pageX - c.offsetLeft,
clickY = e.pageY - c.offsetTop
for (let i = 0; i < squares.length; i++) {
let square = squares[i]
if (clickX > square.x && clickX < (square.x + w) && clickY > square.y && clickY < (square.y + h)) {
if (square.isSelected == false) {
square.isSelected = true
square.color = document.querySelector('.shapeColor').value
} else {
square.isSelected = false
square.color = backColor
}
drawSquares()
}
}
}
document.querySelector('.show').onclick = showNumbers
function showNumbers() {
if (!isShown) {
isShown = true
for (let i = 0; i < squares.length; i++) {
let square = squares[i]
$.beginPath()
$.font = '8pt Calibri'
$.fillStyle = 'rgba(0,0,0,.6)'
$.fillText(i + 1, square.x, (square.y + 8))
}
} else {
isShown = false
}
drawSquares()
}
}
圆函数与平方函数非常相似。JavaScript:function circles() {
let r = shapeWidth / 2
let x = y = r
let circles = []
addCircles()
function Circle(x, y) {
this.x = x
this.y = y
this.color = backColor
this.isSelected = false
}
function addCircles() {
for (let i = 0; i < shapeAmount; i++) {
let circle = new Circle(x, y)
x += shapeWidth
if (x == W + r) {
y += shapeWidth
x = r
}
circles.push(circle)
}
drawCircles()
}
function drawCircles() {
$.clearRect(0, 0, W, H)
for (let i = 0; i < circles.length; i++) {
let circle = circles[i]
$.beginPath()
$.arc(circle.x, circle.y, r, 0, Math.PI * 2)
$.fillStyle = circle.color
$.strokeStyle = borderColor
$.lineWidth = border
$.fill()
$.stroke()
if (isShown) {
$.beginPath()
$.font = '8pt Calibri'
$.fillStyle = 'rgba(0,0,0,.6)'
$.fillText(i + 1, (circle.x - 8), circle.y)
}
}
}
c.onclick = select
function select(e) {
let clickX = e.pageX - c.offsetLeft,
clickY = e.pageY - c.offsetTop
for (let i = 0; i < circles.length; i++) {
let circle = circles[i]
let distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2))
if (distanceFromCenter <= r) {
if (circle.isSelected == false) {
circle.isSelected = true
circle.color = document.querySelector('.shapeColor').value
} else {
circle.isSelected = false
circle.color = backColor
}
drawCircles()
}
}
}
document.querySelector('.show').onclick = showNumbers
function showNumbers() {
if (!isShown) {
isShown = true
for (let i = 0; i < circles.length; i++) {
let circle = circles[i]
$.beginPath()
$.font = '8pt Calibri'
$.fillStyle = 'rgba(0,0,0,.6)'
$.fillText(i + 1, (circle.x - 8), circle.y)
}
} else {
isShown = false
}
drawCircles()
}
}
我们找到用于保存/删除结果(图像)的按钮,并将点击事件处理程序挂在其上:document.querySelector('.save').onclick = () => {
let img = document.querySelector('img')
img == null ? document.body.appendChild(document.createElement('img')).src = c.toDataURL() : document.body.removeChild(img)
}
我们找到了清洁画布的按钮,并...:document.querySelector('.clear').onclick = () => {
$.clearRect(0, 0, W, H)
generateCanvas()
}
查找按钮以删除画布并...:document.querySelector('.delete').onclick = () => {
$.clearRect(0, 0, W, H)
c.style.display = 'none'
}
结果如下所示:
Codepen(添加了几个用例)Github感谢您的关注。