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

Canvas绘制缩放图片失真,疑JS获取画布尺寸异常求助

问题

我希望在Canvas中按比例缩放绘制发型图片,但绘制后的图片出现失真。我认为比例计算逻辑无误,猜测失真原因是Canvas实际高度为400,但JavaScript中获取到的画布尺寸为150,特此咨询该猜测是否为失真的真正原因?

效果截图

输入图片描述
输入图片描述
输入图片描述
输入图片描述
输入图片描述

HTML代码
<!doctype html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>A Basic HTML5 Template</title>

  <link rel="stylesheet" href="css/main-1.css">
  <section id="fitting-room-section">
    <canvas class="n-canvas" id="fitting-room-canvas"></canvas>
  </section>  
  
  
  <button type="button" class="n-button">Click Me!</button>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
  
  
</head>

<body>
  <!-- your content here... -->
  
  <script src="js/script-1.js"></script>
</body>
</html>
CSS代码
.n-canvas {
    width: 100%;
    height: 100%;
    max-width: 300px;
    min-height: 400px;  
    background-color: red;
}
JS代码
$( document ).ready(function() {    

    function drawImageScaled() {    
        let canvas = document.getElementById('fitting-room-canvas');    
        let ctx = canvas.getContext('2d');
    
        let img = new Image();
        img.src = 'img/bob.png';    
    
        img.onload = function(){
          let imgWidth = canvas.width * (2 / 3); // 图片宽度占画布宽度的三分之二
          var ratio = imgWidth / img.width; // 图片缩放比例
          let imgHeight = img.height * ratio; // 按比例计算图片高度       
          ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
        }
      }
    
    jQuery( ".n-button" ).on( "click", drawImageScaled);
    
    console.log( "ready!" );
});
回答

你的猜测完全正确,这就是图片失真的核心原因。

Canvas有两个独立的尺寸属性:

  • 绘图像素尺寸:由canvas.width和canvas.height属性控制,这是Canvas内部的绘图画布大小,默认值为300x150
  • 页面显示尺寸:由CSS的width/height控制,仅决定Canvas在页面上的视觉展示大小

你只通过CSS把Canvas的显示高度设为400px,但没有设置Canvas本身的height属性,导致:

  1. JS中获取到的canvas.height是默认的150px,绘图时是在300x150的像素画布上绘制
  2. 绘制完成后,CSS把这个300x150的画布拉伸到400px高度显示,自然会出现拉伸失真

解决方法有两种:

  1. 在HTML中直接给Canvas设置宽高属性:
<canvas class="n-canvas" id="fitting-room-canvas" width="300" height="400"></canvas>
  1. 在JS初始化时同步绘图尺寸和显示尺寸:
$( document ).ready(function() {    
    const canvas = document.getElementById('fitting-room-canvas');
    // 获取Canvas的实际显示尺寸
    const rect = canvas.getBoundingClientRect();
    // 同步绘图尺寸
    canvas.width = rect.width;
    canvas.height = rect.height;

    function drawImageScaled() {    
        let ctx = canvas.getContext('2d');
    
        let img = new Image();
        img.src = 'img/bob.png';    
    
        img.onload = function(){
          let imgWidth = canvas.width * (2 / 3); 
          var ratio = imgWidth / img.width; 
          let imgHeight = img.height * ratio;       
          ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
        }
      }
    
    jQuery( ".n-button" ).on( "click", drawImageScaled);
    
    console.log( "ready!" );
});

两种方法都能让Canvas的绘图尺寸和显示尺寸一致,避免拉伸失真。

内容的提问来源于stack exchange,提问作者Kifsif

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:07:53