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

Canvas调用putImageData绘制全白 除alpha外还有哪些实现错误?

问题现象
  • 基于二维数组在canvas上绘制图形,预期初始渲染全画布#808080灰色,实际始终显示纯白色
  • 参考同类问题的解决方案将像素alpha值设为255后,问题仍然存在

原有实现代码:

<!-- HTML部分 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container"></div>
// 原有问题JS代码
(function() {
  var context = null;
  var grid = [];
  var height = null;
  var image_data = null;
  var width = null;

  var draw = function() {
    var data = image_data.data;
    for (var index = 0; index < data.length; index += 4) {
      var x = Math.floor(Math.floor(index / 4) / width);
      var y = Math.floor(Math.floor(index / 4) * width);
      data[index] = grid[x][y][0];
      data[index + 1] = grid[x][y][1];
      data[index + 2] = grid[x][y][2];
      data[index + 3] = 255;
    }
    image_data.data = data;
    context.putImageData(image_data, 0, 0);
  };

  var init = function() {
    height = jQuery(window).height();
    width = jQuery(window).width();
    jQuery('#container').html('<canvas id="map" height="' + height + '" width="' + width + '"></canvas>')
    context = document.getElementById('map').getContext('2d');
    image_data = context.getImageData(0, 0, width, height);
    for (var outer = 0; outer < width; outer += 1) {
      grid[outer] = [];
      for (var inner = 0; inner < height; inner += 1) {
        grid[outer][inner] = [128, 128, 128];
      }
    }
  }

  var start_drawing = function() {
    draw();
    setTimeout(start_drawing, 1);
  };

  init();
  start_drawing();
})();
错误原因
  • 核心错误为像素坐标计算逻辑完全错误:ImageData的像素数据按行优先顺序存储(从上到下逐行、每行从左到右排列),原有代码计算x、y的公式不符合存储规则,坐标值严重超出二维数组grid的索引范围,触发类型错误导致draw函数直接中断执行,canvas始终保持初始透明状态,在页面默认白色背景下看起来就是全白。
  • 存在冗余无效代码:image_data.data是只读的Uint8ClampedArray引用,直接修改该数组的元素就会同步作用到ImageData上,不需要也不能手动给image_data.data重新赋值,该操作在严格模式下会直接抛出错误。
修正后代码
(function() {
  var context = null;
  var grid = [];
  var height = null;
  var image_data = null;
  var width = null;

  var draw = function() {
    var data = image_data.data;
    // 遍历每个像素(每4个值对应1个像素的R/G/B/A通道)
    for (var index = 0; index < data.length; index += 4) {
      // 计算当前像素的序号
      var pixelIndex = index / 4;
      // 按行优先规则正确计算坐标:y为像素序号除以画布宽度取整(行号),x为像素序号对画布宽度取模(列号)
      var y = Math.floor(pixelIndex / width);
      var x = pixelIndex % width;
      // 写入颜色值
      data[index] = grid[x][y][0];
      data[index + 1] = grid[x][y][1];
      data[index + 2] = grid[x][y][2];
      data[index + 3] = 255;
    }
    // 移除无效的data重新赋值操作,直接渲染
    context.putImageData(image_data, 0, 0);
  };

  var init = function() {
    height = jQuery(window).height();
    width = jQuery(window).width();
    jQuery('#container').html('<canvas id="map" height="' + height + '" width="' + width + '"></canvas>')
    var canvas = document.getElementById('map');
    context = canvas.getContext('2d');
    // 增加灰色填充兜底,避免首次渲染加载时的白屏闪烁
    context.fillStyle = '#808080';
    context.fillRect(0,0,width,height);
    image_data = context.getImageData(0, 0, width, height);
    // 初始化二维网格
    for (var x = 0; x < width; x += 1) {
      grid[x] = [];
      for (var y = 0; y < height; y += 1) {
        grid[x][y] = [128, 128, 128];
      }
    }
  }

  var start_drawing = function() {
    draw();
    setTimeout(start_drawing, 1);
  };

  init();
  start_drawing();
})();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:24:21