mirror of
https://github.com/tsl0922/EPD-nRF5.git
synced 2025-12-06 15:42:48 +08:00
add cursor for brush
This commit is contained in:
114
html/js/paint.js
114
html/js/paint.js
@@ -19,6 +19,9 @@ class PaintManager {
|
|||||||
this.textBold = false;
|
this.textBold = false;
|
||||||
this.textItalic = false;
|
this.textItalic = false;
|
||||||
|
|
||||||
|
// Brush cursor indicator
|
||||||
|
this.brushCursor = null;
|
||||||
|
|
||||||
// Undo/Redo functionality
|
// Undo/Redo functionality
|
||||||
this.historyStack = [];
|
this.historyStack = [];
|
||||||
this.historyStep = -1;
|
this.historyStep = -1;
|
||||||
@@ -33,6 +36,8 @@ class PaintManager {
|
|||||||
this.onTouchMove = this.onTouchMove.bind(this);
|
this.onTouchMove = this.onTouchMove.bind(this);
|
||||||
this.onTouchEnd = this.onTouchEnd.bind(this);
|
this.onTouchEnd = this.onTouchEnd.bind(this);
|
||||||
this.handleKeyboard = this.handleKeyboard.bind(this);
|
this.handleKeyboard = this.handleKeyboard.bind(this);
|
||||||
|
this.updateBrushCursor = this.updateBrushCursor.bind(this);
|
||||||
|
this.hideBrushCursor = this.hideBrushCursor.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveToHistory() {
|
saveToHistory() {
|
||||||
@@ -132,8 +137,9 @@ class PaintManager {
|
|||||||
this.brushColor = e.target.value;
|
this.brushColor = e.target.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('brush-size').addEventListener('change', (e) => {
|
document.getElementById('brush-size').addEventListener('input', (e) => {
|
||||||
this.brushSize = parseInt(e.target.value);
|
this.brushSize = parseInt(e.target.value);
|
||||||
|
this.updateBrushCursorSize();
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('add-text-btn').addEventListener('click', () => this.startTextPlacement());
|
document.getElementById('add-text-btn').addEventListener('click', () => this.startTextPlacement());
|
||||||
@@ -167,6 +173,14 @@ class PaintManager {
|
|||||||
// Keyboard shortcuts for undo/redo
|
// Keyboard shortcuts for undo/redo
|
||||||
document.addEventListener('keydown', this.handleKeyboard);
|
document.addEventListener('keydown', this.handleKeyboard);
|
||||||
|
|
||||||
|
// Mouse move for brush cursor
|
||||||
|
this.canvas.addEventListener('mousemove', this.updateBrushCursor);
|
||||||
|
this.canvas.addEventListener('mouseenter', this.updateBrushCursor);
|
||||||
|
this.canvas.addEventListener('mouseleave', this.hideBrushCursor);
|
||||||
|
|
||||||
|
// Create brush cursor element
|
||||||
|
this.createBrushCursor();
|
||||||
|
|
||||||
// Initialize history with blank canvas state
|
// Initialize history with blank canvas state
|
||||||
this.saveToHistory();
|
this.saveToHistory();
|
||||||
}
|
}
|
||||||
@@ -204,6 +218,104 @@ class PaintManager {
|
|||||||
|
|
||||||
// Cancel any pending text placement
|
// Cancel any pending text placement
|
||||||
this.cancelTextPlacement();
|
this.cancelTextPlacement();
|
||||||
|
|
||||||
|
// Update brush cursor visibility
|
||||||
|
this.updateBrushCursorVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
createBrushCursor() {
|
||||||
|
// Create a div element to show as brush cursor
|
||||||
|
this.brushCursor = document.createElement('div');
|
||||||
|
this.brushCursor.id = 'brush-cursor';
|
||||||
|
this.brushCursor.style.position = 'fixed';
|
||||||
|
this.brushCursor.style.border = '2px solid rgba(0, 0, 0, 0.5)';
|
||||||
|
this.brushCursor.style.borderRadius = '50%';
|
||||||
|
this.brushCursor.style.pointerEvents = 'none';
|
||||||
|
this.brushCursor.style.display = 'none';
|
||||||
|
this.brushCursor.style.zIndex = '10000';
|
||||||
|
this.brushCursor.style.transform = 'translate(-50%, -50%)';
|
||||||
|
this.brushCursor.style.willChange = 'transform';
|
||||||
|
this.brushCursor.style.left = '0';
|
||||||
|
this.brushCursor.style.top = '0';
|
||||||
|
document.body.appendChild(this.brushCursor);
|
||||||
|
this.updateBrushCursorSize();
|
||||||
|
|
||||||
|
// For requestAnimationFrame throttling
|
||||||
|
this.cursorUpdateScheduled = false;
|
||||||
|
this.pendingCursorX = 0;
|
||||||
|
this.pendingCursorY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBrushCursorSize() {
|
||||||
|
if (!this.brushCursor) return;
|
||||||
|
|
||||||
|
const rect = this.canvas.getBoundingClientRect();
|
||||||
|
const scaleX = rect.width / this.canvas.width;
|
||||||
|
const scaleY = rect.height / this.canvas.height;
|
||||||
|
const scale = Math.min(scaleX, scaleY);
|
||||||
|
|
||||||
|
const size = this.brushSize * scale;
|
||||||
|
this.brushCursor.style.width = size + 'px';
|
||||||
|
this.brushCursor.style.height = size + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBrushCursorVisibility() {
|
||||||
|
if (!this.brushCursor) return;
|
||||||
|
|
||||||
|
if (this.currentTool === 'brush' || this.currentTool === 'eraser') {
|
||||||
|
this.brushCursor.style.display = 'block';
|
||||||
|
this.canvas.style.cursor = 'none';
|
||||||
|
} else {
|
||||||
|
this.brushCursor.style.display = 'none';
|
||||||
|
this.canvas.style.cursor = 'default';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBrushCursor(e) {
|
||||||
|
if (!this.brushCursor) return;
|
||||||
|
|
||||||
|
if (this.currentTool === 'brush' || this.currentTool === 'eraser') {
|
||||||
|
this.brushCursor.style.display = 'block';
|
||||||
|
this.canvas.style.cursor = 'none';
|
||||||
|
|
||||||
|
// Store the pending position
|
||||||
|
this.pendingCursorX = e.clientX;
|
||||||
|
this.pendingCursorY = e.clientY;
|
||||||
|
|
||||||
|
// Schedule update using requestAnimationFrame for smooth movement
|
||||||
|
if (!this.cursorUpdateScheduled) {
|
||||||
|
this.cursorUpdateScheduled = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
this.brushCursor.style.transform = `translate(${this.pendingCursorX}px, ${this.pendingCursorY}px) translate(-50%, -50%)`;
|
||||||
|
this.cursorUpdateScheduled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update color to match brush or show white for eraser (only needs to happen once or when tool changes)
|
||||||
|
if (this.currentTool === 'eraser') {
|
||||||
|
if (this.brushCursor.getAttribute('data-tool') !== 'eraser') {
|
||||||
|
this.brushCursor.style.border = '2px solid rgba(255, 0, 0, 0.7)';
|
||||||
|
this.brushCursor.style.backgroundColor = 'rgba(255, 255, 255, 0.2)';
|
||||||
|
this.brushCursor.style.boxShadow = 'none';
|
||||||
|
this.brushCursor.setAttribute('data-tool', 'eraser');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.brushCursor.getAttribute('data-tool') !== 'brush') {
|
||||||
|
// Use a contrasting border - white with black outline for visibility
|
||||||
|
this.brushCursor.style.border = '1px solid white';
|
||||||
|
this.brushCursor.style.boxShadow = '0 0 0 1px black, inset 0 0 0 1px black';
|
||||||
|
this.brushCursor.style.backgroundColor = 'transparent';
|
||||||
|
this.brushCursor.setAttribute('data-tool', 'brush');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hideBrushCursor() {
|
||||||
|
if (this.brushCursor) {
|
||||||
|
this.brushCursor.style.display = 'none';
|
||||||
|
}
|
||||||
|
this.canvas.style.cursor = 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
startPaint(e) {
|
startPaint(e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user