Chrome下可调整大小绘图Canvas异常问题求助
Hey there! Let's work through your two canvas problems step by step—keeping your drawn content when resizing, and getting the resize functionality working properly in Chrome.
1. Preventing Drawn Content from Being Cleared on Resize
The core issue here is that setting a canvas's width or height property automatically wipes all existing content. To fix this, we'll add a quick step to save the current canvas state before resizing, then restore it afterward using a temporary canvas as a buffer.
2. Fixing Resize Functionality in Chrome
Your current mouseup event listener on #canvaSizer doesn't reliably trigger in Chrome (especially if your mouse ends up outside the element after dragging the resize handle). Instead, we'll use a MutationObserver to detect style changes on the resizer element, which works consistently across browsers. We'll also clean up duplicate CSS properties and avoid re-binding event listeners every time the canvas resizes.
Modified Full Code
HTML
<!DOCTYPE html> <html lang="en"> <body> <div id="canvasWrapper"> <div id="canvaSizer"> <canvas id="screen"></canvas> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> </body> </html>
CSS
* { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; overflow: hidden; } #canvasWrapper { width: 95.6%; height: 100%; position: absolute; z-index: 1; overflow: hidden; } #canvaSizer { padding: 0; display: block; width: 35%; border-style: solid; height: 35%; position: absolute; resize: both; max-width: 95%; min-width: 35%; max-height: 95%; min-height: 35%; overflow: hidden; } #screen { cursor: crosshair; display: block; /* Remove extra default spacing */ }
JavaScript
$(document).ready(function() { let canvaWidth = document.getElementById('canvaSizer').clientWidth; let canvaHeight = document.getElementById('canvaSizer').clientHeight; const myscreen = document.getElementById("screen"); const ctx = myscreen.getContext("2d"); // Initialize canvas on load initialize(); // Watch for size changes on the resizer element (works for Chrome) const observer = new MutationObserver(function(mutations) { const newWidth = document.getElementById('canvaSizer').clientWidth; const newHeight = document.getElementById('canvaSizer').clientHeight; if (newWidth !== canvaWidth || newHeight !== canvaHeight) { canvaWidth = newWidth; canvaHeight = newHeight; initialize(); } }); observer.observe(document.getElementById('canvaSizer'), { attributes: true, attributeFilter: ['style'] }); function initialize() { // Save current drawing to a temporary canvas const tempCanvas = document.createElement('canvas'); const tempCtx = tempCanvas.getContext('2d'); tempCanvas.width = myscreen.width; tempCanvas.height = myscreen.height; tempCtx.drawImage(myscreen, 0, 0); // Resize main canvas to match the sizer myscreen.width = canvaWidth; myscreen.height = canvaHeight; // Restore background and saved drawing ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, myscreen.width, myscreen.height); ctx.drawImage(tempCanvas, 0, 0); // Reset line width (gets cleared when canvas resizes) ctx.lineWidth = 5; } // Mouse event handlers (bind once, not on every resize) let isDown = false; let canvasX, canvasY; $(myscreen) .mousedown(function(e) { isDown = true; ctx.beginPath(); canvasX = e.pageX - myscreen.offsetLeft; canvasY = e.pageY - myscreen.offsetTop; ctx.moveTo(canvasX, canvasY); }) .mousemove(function(e) { if (isDown !== false) { canvasX = e.pageX - myscreen.offsetLeft; canvasY = e.pageY - myscreen.offsetTop; ctx.lineTo(canvasX, canvasY); ctx.strokeStyle = "#000"; ctx.stroke(); } }) .mouseup(function(e) { isDown = false; ctx.closePath(); }); // Touch event handlers with fixed position calculation const draw = { started: false, start: function(evt) { ctx.beginPath(); const rect = myscreen.getBoundingClientRect(); ctx.moveTo(evt.touches[0].pageX - rect.left, evt.touches[0].pageY - rect.top); this.started = true; }, move: function(evt) { if (this.started) { const rect = myscreen.getBoundingClientRect(); ctx.lineTo(evt.touches[0].pageX - rect.left, evt.touches[0].pageY - rect.top); ctx.strokeStyle = "#000"; ctx.lineWidth = 5; ctx.stroke(); } }, end: function(evt) { this.started = false; } }; // Attach touch events myscreen.addEventListener('touchstart', draw.start, false); myscreen.addEventListener('touchend', draw.end, false); myscreen.addEventListener('touchmove', draw.move, false); // Prevent page scrolling on touch devices document.body.addEventListener('touchmove', function(evt) { evt.preventDefault(); }, false); });
Key Improvements Breakdown
- Content Preservation: The temporary canvas captures your drawing before resizing, then we draw it back onto the resized canvas so nothing gets lost.
- Chrome Resize Fix:
MutationObserverwatches for style changes on the resizer element, so we catch size adjustments reliably across all browsers. - Efficient Event Binding: Mouse/touch events are bound only once, avoiding duplicate listeners that could cause lag or unexpected behavior.
- Touch Position Fix: Updated touch coordinates to account for the canvas's on-screen position, making touch drawing accurate.
内容的提问来源于stack exchange,提问作者Redmar

