代码之家  ›  专栏  ›  技术社区  ›  Derk Jan Speelman

移除矩形HTML5画布之间的间距

  •  0
  • Derk Jan Speelman  · 技术社区  · 6 年前

    我用 For Loop HTMLCanvasElement .

    但是当 变焦 输入或输出(使用鼠标或触摸板上的滚动功能)。现在,向矩形添加一个笔划将解决该区域,但是矩形将不再完全对齐。

    rectangles with white space

    有人知道怎么解决这个问题吗?


    我也看了一下 Uint8ClampedArray 创建自定义 ImageData Object . 但我的结论是 Uint8ClampedArray 不会解决这个问题的。

    var canvas = $('#canvas'),
      ctx = canvas.get(0).getContext("2d"),
      win = $(window),
      ww = win.outerWidth(),
      wh = win.outerHeight(),
      scale = 1,
      pixelSize = 10 * scale,
      wx = 0,
      wy = 0,
      sx = 0,
      sy = 0;
    
    var settings = {
      grid: true
    }
    
    var mouse = {
      x: 0,
      y: 0,
      rx: 0,
      ry: 0,
      button: 0
    };
    
    function zoom(f) {
      return Math.floor(f * scale);
    }
    
    function zoomX(x) {
      return Math.floor((x - wx) * scale + sx);
    }
    
    function zoomY(y) {
      return Math.floor((y - wy) * scale + sy);
    }
    
    function zoomX_INV(x) {
      return Math.floor((x - sx) * (1 / scale) + wx);
    }
    
    function zoomY_INV(y) {
      return Math.floor((y - sy) * (1 / scale) + wy);
    }
    
    function setBackground(color) {
      ctx.beginPath();
      ctx.rect(0, 0, ww, wh);
      ctx.fillStyle = color;
      ctx.fill();
    }
    
    function drawPixel(x1, y1, fill) {
      ctx.beginPath();
      ctx.rect(zoomX(x1 * pixelSize), zoomY(y1 * pixelSize), zoom(pixelSize), zoom(pixelSize));
      ctx.fillStyle = fill;
      ctx.fill();
      // 	below wont fix it
      // ctx.strokeStyle = fill;
      // ctx.lineWidth = 2;
      // ctx.stroke();
    }
    
    function drawGrid() {
      // 	var offsetX = Math.floor(wx / pixelSize) * pixelSize - wx,
      // 		offsetY = Math.floor(wy / pixelSize) * pixelSize - wy;
    
      // 	ctx.beginPath();
    
      // 	ctx.moveTo(0, pixelSize);
      // 	ctx.lineTo(0, wh);
    
      // // 	for(var x = 0; x < ww; x += pixelSize * scale) {
      // // 		ctx.moveTo(zoomX(x), zoomY(0));
      // // 		ctx.lineTo(zoomX(x), zoomY(wh));
      // // 	}
    
      // // 	for(var y = 0; y < wh; y += pixelSize * scale) {
      // // 		ctx.moveTo(zoomX(0), zoomY(y));
      // //         ctx.lineTo(zoomX(ww), zoomY(y));
      // // 	}
    
      // 	ctx.strokeStyle = 'black';
      // 	ctx.lineWidth = .5;
      //     ctx.stroke();
    }
    
    function draw() {
      ctx.clearRect(0, 0, ww, wh);
    
      setBackground('white');
    
      for (var x = 0; x < 10; x++) {
        for (var y = 0; y < 10; y++) {
          drawPixel(x, y, 'green');
          drawPixel(x + 12, y + 12, 'skyblue');
        }
      }
      drawPixel(11, 11, 'green');
    
      // if (settings.grid) {
      // 	drawGrid();
      // }
    }
    
    function resize() {
    
      ww = win.outerWidth();
      wh = win.outerHeight();
    
      canvas.get(0).width = ww;
      canvas.get(0).height = wh;
    
      draw();
    }
    
    function init() {
      resize();
    }
    
    canvas.on('mousemove mousedown mouseup mouseout', function(e) {
      if (e.type === "mousedown") {
        mouse.button = 1;
      } else if (e.type === "mouseup" || event.type === "mouseout") {
        mouse.button = 0;
      }
    
      mouse.bounds = canvas.get(0).getBoundingClientRect();
    
      mouse.x = e.clientX - mouse.bounds.left;
      mouse.y = e.clientY - mouse.bounds.top;
    
      var xx = mouse.rx;
      var yy = mouse.ry;
    
      mouse.rx = zoomX_INV(mouse.x);
      mouse.ry = zoomY_INV(mouse.y);
    
      if (mouse.button === 1) {
        wx -= mouse.rx - xx;
        wy -= mouse.ry - yy;
        mouse.rx = zoomX_INV(mouse.x);
        mouse.ry = zoomY_INV(mouse.y);
      }
    
      draw();
    });
    
    canvas.on('wheel', function(e) {
      e.preventDefault();
    
      if (e.originalEvent.wheelDelta / 120 > 0) {
        scale = Math.min(2, scale * 1.1);
      } else {
        scale = Math.max(0.5, scale * (1 / 1.1));
      }
    
      wx = mouse.rx;
      wy = mouse.ry;
      sx = mouse.x;
      sy = mouse.y;
    
      mouse.rx = zoomX_INV(mouse.x);
      mouse.ry = zoomY_INV(mouse.y);
    
      draw();
    });
    
    win.on('load resize', function() {
      init();
    });
    *,
    *:after,
    *:before {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      overflow: hidden;
    }
    
    #wrapper #controls {
      position: absolute;
    }
    
    #wrapper #canvas {
      image-rendering: -moz-crisp-edges;
      image-rendering: -webkit-crisp-edges;
      -ms-interpolation-mode: nearest-neighbor;
      image-rendering: -o-pixelated;
      image-rendering: pixelated;
      image-rendering: crisp-edges;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
    
    <div id="wrapper">
      <div id="controls"></div>
      <canvas id="canvas"></canvas>
    </div>
    2 回复  |  直到 5 年前
        1
  •  1
  •   Derk Jan Speelman    5 年前

    我想空白是你的 Math.floor 在所有的缩放函数中,这些函数为绘图提供近似值。

    我不知道你的代码到底出了什么问题,但我能用 ctx.scale(x, y) . 然而,它似乎并不完全适用于你的代码…

    https://jsfiddle.net/amrg2d3s/

        2
  •  -1
  •   Namig Ismayilov    6 年前

    我会补充评论,但我没有足够的声誉。试试这个

    for(var x = 0; x < 10; x++) {
        for(var y = 0; y < 10; y++) {
            drawPixel(x, y, 'green');
            drawPixel(x + 11, y + 11, 'skyblue');
        }
    }
    drawPixel(10, 10, 'green');
    

    只是操纵了一些数字