You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome下可调整大小绘图Canvas异常问题求助

Fixing Canvas Resize Issues: Content Loss & Chrome Compatibility

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: MutationObserver watches 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:42:46