这次要挑战的是比小画家还阳春的绘图app,会利用到canvas api,请看倌直接到CodePen里试试看。
实作逻辑
html
<canvas id="canvas"></canvas>
<div class="toolbox">
<button id="decrease">-</button>
<span id="size">10</span>
<button id="increase">+</button>
<input type="color" id="color">
<button id="clear">X</button>
</div>
CSS(节录)
canvas {
border: 2px solid steelblue;
width: 70vw;
height: 700px
}
.toolbox {
background-color: steelblue;
border: 1px solid slateblue;
display: flex;
width: 70vw;
height: 700px
padding: 1rem;
}
/* 指定.toolbox内的所有元素 */
.toolbox > * {
background-color: #fff;
border: none;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 2rem;
height: 50px;
width: 50px;
margin: 0.5rem;
padding: 0.25rem;
cursor: pointer;
}
/* 将最後一个元素推到最左侧 */
.toolbox > *:last-child {
margin-left: auto;
}
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');
// 取得二维绘图板
const ctx = canvas.getContext('2d');
let size = 10
let isPressed = false
colorEl.value = 'black'
let color = colorEl.value
let x
let y
// 滑鼠按下点击的时候,取得x与y的定位
canvas.addEventListener('mousedown', (e) => {
isPressed = true
x = e.offsetX
y = e.offsetY
})
// 滑鼠离开的时候就取消x与y的定位
document.addEventListener('mouseup', (e) => {
isPressed = false
x = undefined
y = undefined
})
// 滑鼠点击且移动的时候,表示正在进行绘图行为
canvas.addEventListener('mousemove', (e) => {
if(isPressed) {
// 取得最新的定位点x2与y2
const x2 = e.offsetX
const y2 = e.offsetY
// 先完成一维的圆点
drawCircle(x2, y2)
// 若滑鼠有位移动作,绘制二维线条
drawLine(x, y, x2, y2)
// 完成绘图後,将x与y赋值一开始取得的定位点(随着位移不断更新)
x = x2
y = y2
}
})
// 运用canvas api产生圆点
function drawCircle(x, y) {
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2)
ctx.fillStyle = color
ctx.fill()
}
// 运用canvas api产生线条
function drawLine(x1, y1, x2, y2) {
ctx.beginPath()
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
ctx.strokeStyle = color
// 因为是二维关系,size要以平方值来计算才行
ctx.lineWidth = size * 2
ctx.stroke()
}
// 更新sizeEl的size
function updateSizeOnScreen() {
sizeEL.innerText = size
}
// 将+按钮挂载监听器,控制size数值
increaseBtn.addEventListener('click', () => {
size += 5
if(size > 50) {
size = 50
}
// 做为参数引入函式中
updateSizeOnScreen()
})
// 将 - 按钮挂载监听器,控制size数值
decreaseBtn.addEventListener('click', () => {
size -= 5
if(size < 5) {
size = 5
}
updateSizeOnScreen()
})
// 透过html5提供的<input>选色模板,来控制变数color的值
colorEl.addEventListener('change', (e) => color = e.target.value)
// 将X按钮挂上监听器,带入canvas api所提供的清除指令,将绘图板清空
clearEl.addEventListener('click', () => ctx.clearRect(0,0, canvas.width, canvas.height))
活在前後端分离的年代,我觉得後端重要的工作之一就是写出好用、好沟通的API。 可以先看一下HTTP ...
今日题目 题目连结:108. Convert Sorted Array to Binary Sear...
如同前面所说,资料模型需要运用到实际环境中才会发挥价值 Initiation 延续之前模型的初始条件...
每年生日刚好是伊豆诸岛的旺季开始前一周,通常天气宜人,海水清澈到可以目视钓鱼,离东京只要搭船三小时,...
前面讲完官方的14种Contracts,但我们也能建立属於自己的Contracts,以下范例是实作一...