每日一题:canvas绘制矩形/拖动绘制的矩形
代码不再赘述,直接复制到文件直接运行即可
逻辑很简单,在画布上进行绘制,对js基础有一定要求。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<input type="color">
<canvas>
</canvas>
<script src="index.js"></script>
</body>
</html>
css
body{
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
canvas {
margin: 50px;
background-color: #b1b3b8;
}
javascript
console.log(devicePixelRatio)
// 原始尺寸 = 样式尺寸 * 缩放倍率
const cvs = document.querySelector('canvas') // 画布
const colorPicker = document.querySelector('input') // 颜色选择器
const ctx = cvs.getContext('2d')// 2d绘图环境
function init() {
const w = 500 // 画布宽度
const h = 300 // 画布高度
cvs.width = w * devicePixelRatio
cvs.height = h * devicePixelRatio
cvs.style.width = w + 'px'
cvs.style.height = h + 'px'
}
init()
const shapes = []
class Rectangle {
constructor(color, startX, startY) {
this.color = color
this.startX = startX
this.startY = startY
this.endX = startX
this.endY = startY
}
get minX() {
return Math.min(this.startX, this.endX)
}
get minY() {
return Math.min(this.startY, this.endY)
}
get maxX() {
return Math.max(this.startX, this.endX)
}
get maxY() {
return Math.max(this.startY, this.endY)
}
draw(ctx) {
ctx.beginPath()
ctx.moveTo(this.minX* devicePixelRatio, this.minY* devicePixelRatio)
ctx.lineTo(this.maxX* devicePixelRatio, this.minY* devicePixelRatio)
ctx.lineTo(this.maxX* devicePixelRatio, this.maxY* devicePixelRatio)
ctx.lineTo(this.minX* devicePixelRatio, this.maxY* devicePixelRatio)
ctx.lineTo(this.minX* devicePixelRatio, this.minY* devicePixelRatio)
ctx.fillStyle = this.color
ctx.fill()
ctx.strokeStyle = '#fff'
ctx.lineCap = 'square'
ctx.lineWidth = 2* devicePixelRatio
ctx.stroke()
}
}
cvs.onmousedown= e => {
console.log(e.offsetX, e.offsetY)
const bounding = cvs.getBoundingClientRect()
const rect = new Rectangle(colorPicker.value, e.offsetX, e.offsetY)
const shape = getShape(e.offsetX, e.offsetY)
if(shape){
const { startX, startY,endX,endY} = shape
const mouseX = e.offsetX
const mouseY = e.offsetY
window.onmousemove = e => {
const distX = e.clientX - bounding.left - mouseX
const distY = e.clientY - bounding.top - mouseY
shape.startX = startX + distX
shape.startY = startY + distY
shape.endX = endX + distX
shape.endY = endY + distY
}
console.log('拖动')
}else {
shapes.push(rect)
window.onmousemove = e => {
rect.endX = e.clientX - bounding.left
rect.endY = e.clientY - bounding.top
}
}
window.onmouseup = () => {
window.onmousemove = null
window.onmouseup = null
}
}
function draw() {
requestAnimationFrame(draw)
ctx.clearRect(0, 0, cvs.width, cvs.height) // 清空画布
shapes.forEach(item => {
item.draw(ctx)
}
)
}
draw()
function getShape(x,y) {
return shapes.find(item => {
return item.minX <= x && item.maxX >= x && item.minY <= y && item.maxY >= y
})
}
长风破浪会有时,直挂云帆济沧海
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)