深入学习Canvas鼠标事件处理,掌握点击、移动、滚轮等鼠标事件的监听和响应方法。鼠标事件是Canvas交互的基础,通过监听鼠标的各种操作实现丰富的交互功能。
| 事件 | 说明 | 触发时机 |
|---|---|---|
| click | 点击 | 鼠标按下并释放 |
| dblclick | 双击 | 快速连续点击两次 |
| mousedown | 按下 | 鼠标按钮按下 |
| mouseup | 释放 | 鼠标按钮释放 |
| mousemove | 移动 | 鼠标在元素上移动 |
| mouseenter | 进入 | 鼠标进入元素 |
| mouseleave | 离开 | 鼠标离开元素 |
| mouseover | 悬停 | 鼠标悬停在元素上 |
| mouseout | 移出 | 鼠标移出元素 |
| contextmenu | 右键菜单 | 右键点击 |
| wheel | 滚轮 | 鼠标滚轮滚动 |
const canvas = document.getElementById('myCanvas')
canvas.addEventListener('click', (e) => {
console.log('点击事件')
})
canvas.addEventListener('mousedown', (e) => {
console.log('鼠标按下, 按钮:', e.button)
})
canvas.addEventListener('mouseup', (e) => {
console.log('鼠标释放')
})
canvas.addEventListener('mousemove', (e) => {
console.log('鼠标移动')
})
canvas.addEventListener('mousedown', (e) => {
switch (e.button) {
case 0:
console.log('左键按下')
break
case 1:
console.log('中键按下')
break
case 2:
console.log('右键按下')
break
}
})
buttons属性表示当前按下的按钮组合:
canvas.addEventListener('mousemove', (e) => {
if (e.buttons & 1) console.log('左键按下')
if (e.buttons & 2) console.log('右键按下')
if (e.buttons & 4) console.log('中键按下')
})
移动鼠标或点击查看事件信息
canvas.addEventListener('contextmenu', (e) => {
e.preventDefault()
showCustomMenu(e.clientX, e.clientY)
})
function showCustomMenu(x, y) {
const menu = document.createElement('div')
menu.className = 'context-menu'
menu.style.left = x + 'px'
menu.style.top = y + 'px'
menu.innerHTML = `
<div class="menu-item" data-action="copy">复制</div>
<div class="menu-item" data-action="paste">粘贴</div>
<div class="menu-item" data-action="delete">删除</div>
`
document.body.appendChild(menu)
menu.addEventListener('click', (e) => {
const action = e.target.dataset.action
console.log('执行操作:', action)
menu.remove()
})
document.addEventListener('click', () => {
menu.remove()
}, { once: true })
}
canvas.addEventListener('wheel', (e) => {
e.preventDefault()
const delta = e.deltaY
if (e.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
console.log('像素模式, 滚动:', delta)
} else if (e.deltaMode === WheelEvent.DOM_DELTA_LINE) {
console.log('行模式, 滚动:', delta)
} else if (e.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
console.log('页模式, 滚动:', delta)
}
})
let scale = 1
const minScale = 0.5
const maxScale = 3
canvas.addEventListener('wheel', (e) => {
e.preventDefault()
const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1
const newScale = scale * zoomFactor
if (newScale >= minScale && newScale <= maxScale) {
const rect = canvas.getBoundingClientRect()
const mouseX = e.clientX - rect.left
const mouseY = e.clientY - rect.top
scale = newScale
console.log(`缩放: ${scale.toFixed(2)}x`)
}
})
let isDragging = false
let dragStartX = 0
let dragStartY = 0
let offsetX = 0
let offsetY = 0
canvas.addEventListener('mousedown', (e) => {
isDragging = true
const rect = canvas.getBoundingClientRect()
dragStartX = e.clientX - rect.left - offsetX
dragStartY = e.clientY - rect.top - offsetY
})
canvas.addEventListener('mousemove', (e) => {
if (!isDragging) return
const rect = canvas.getBoundingClientRect()
offsetX = e.clientX - rect.left - dragStartX
offsetY = e.clientY - rect.top - dragStartY
redraw()
})
canvas.addEventListener('mouseup', () => {
isDragging = false
})
canvas.addEventListener('mouseleave', () => {
isDragging = false
})
let isDrawing = false
let lastX = 0
let lastY = 0
canvas.addEventListener('mousedown', (e) => {
isDrawing = true
const rect = canvas.getBoundingClientRect()
lastX = e.clientX - rect.left
lastY = e.clientY - rect.top
})
canvas.addEventListener('mousemove', (e) => {
if (!isDrawing) return
const rect = canvas.getBoundingClientRect()
const x = e.clientX - rect.left
const y = e.clientY - rect.top
ctx.beginPath()
ctx.moveTo(lastX, lastY)
ctx.lineTo(x, y)
ctx.stroke()
lastX = x
lastY = y
})
canvas.addEventListener('mouseup', () => {
isDrawing = false
})
const cursorStates = {
default: 'default',
pointer: 'pointer',
move: 'move',
crosshair: 'crosshair',
text: 'text',
wait: 'wait',
notAllowed: 'not-allowed',
grab: 'grab',
grabbing: 'grabbing'
}
function setCursor(type) {
canvas.style.cursor = cursorStates[type] || 'default'
}
canvas.addEventListener('mousemove', (e) => {
const shape = findShapeAt(e.offsetX, e.offsetY)
if (shape) {
if (shape.draggable) {
setCursor('move')
} else {
setCursor('pointer')
}
} else {
setCursor('default')
}
})
function setCustomCursor(imageUrl, x = 0, y = 0) {
const img = new Image()
img.src = imageUrl
img.onload = () => {
canvas.style.cursor = `url(${imageUrl}) ${x} ${y}, auto`
}
}
function throttle(fn, delay) {
let lastTime = 0
return function(...args) {
const now = Date.now()
if (now - lastTime >= delay) {
lastTime = now
fn.apply(this, args)
}
}
}
canvas.addEventListener('mousemove', throttle((e) => {
console.log('节流后的鼠标位置:', e.offsetX, e.offsetY)
}, 16))
function debounce(fn, delay) {
let timer = null
return function(...args) {
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
canvas.addEventListener('mousemove', debounce((e) => {
console.log('防抖后的鼠标位置:', e.offsetX, e.offsetY)
}, 100))