HTML5 Canvas:缩放

问题描述 投票:0回答:7

有没有简单的方法可以在画布(JavaScript)中放大和缩小?基本上我有一个 400x400px 的画布,我希望能够使用“mousedown”(2x)放大并使用“mouseup”返回。

过去两天用谷歌搜索,但到目前为止还没有运气。 :(

javascript canvas
7个回答
87
投票

基于使用drawImage的建议,您还可以将其与缩放功能结合起来。

因此,在绘制图像之前,请将上下文缩放到您想要的缩放级别:

ctx.scale(2, 2) // Doubles size of anything draw to canvas.

我在这里创建了一个小示例http://jsfiddle.net/mBzVR/4/,它使用drawImage和scale在mousedown时放大,在mouseup时缩小。


40
投票

试试这个:

<!DOCTYPE HTML>
<html>

<head>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
  <style>
    body {
      margin: 0px;
      padding: 0px;
    }
    
    #wrapper {
      position: relative;
      border: 1px solid #9C9898;
      width: 578px;
      height: 200px;
    }
    
    #buttonWrapper {
      position: absolute;
      width: 30px;
      top: 2px;
      right: 2px;
    }
    
    input[type="button"] {
      padding: 5px;
      width: 30px;
      margin: 0px 0px 2px 0px;
    }
  </style>
  <script>
    function draw(scale, translatePos) {
      var canvas = document.getElementById("myCanvas");
      var context = canvas.getContext("2d");

      // clear canvas
      context.clearRect(0, 0, canvas.width, canvas.height);

      context.save();
      context.translate(translatePos.x, translatePos.y);
      context.scale(scale, scale);
      context.beginPath(); // begin custom shape
      context.moveTo(-119, -20);
      context.bezierCurveTo(-159, 0, -159, 50, -59, 50);
      context.bezierCurveTo(-39, 80, 31, 80, 51, 50);
      context.bezierCurveTo(131, 50, 131, 20, 101, 0);
      context.bezierCurveTo(141, -60, 81, -70, 51, -50);
      context.bezierCurveTo(31, -95, -39, -80, -39, -50);
      context.bezierCurveTo(-89, -95, -139, -80, -119, -20);
      context.closePath(); // complete custom shape
      var grd = context.createLinearGradient(-59, -100, 81, 100);
      grd.addColorStop(0, "#8ED6FF"); // light blue
      grd.addColorStop(1, "#004CB3"); // dark blue
      context.fillStyle = grd;
      context.fill();

      context.lineWidth = 5;
      context.strokeStyle = "#0000ff";
      context.stroke();
      context.restore();
    }

    window.onload = function() {
      var canvas = document.getElementById("myCanvas");

      var translatePos = {
        x: canvas.width / 2,
        y: canvas.height / 2
      };

      var scale = 1.0;
      var scaleMultiplier = 0.8;
      var startDragOffset = {};
      var mouseDown = false;

      // add button event listeners
      document.getElementById("plus").addEventListener("click", function() {
        scale /= scaleMultiplier;
        draw(scale, translatePos);
      }, false);

      document.getElementById("minus").addEventListener("click", function() {
        scale *= scaleMultiplier;
        draw(scale, translatePos);
      }, false);

      // add event listeners to handle screen drag
      canvas.addEventListener("mousedown", function(evt) {
        mouseDown = true;
        startDragOffset.x = evt.clientX - translatePos.x;
        startDragOffset.y = evt.clientY - translatePos.y;
      });

      canvas.addEventListener("mouseup", function(evt) {
        mouseDown = false;
      });

      canvas.addEventListener("mouseover", function(evt) {
        mouseDown = false;
      });

      canvas.addEventListener("mouseout", function(evt) {
        mouseDown = false;
      });

      canvas.addEventListener("mousemove", function(evt) {
        if (mouseDown) {
          translatePos.x = evt.clientX - startDragOffset.x;
          translatePos.y = evt.clientY - startDragOffset.y;
          draw(scale, translatePos);
        }
      });

      draw(scale, translatePos);
    };



    jQuery(document).ready(function() {
      $("#wrapper").mouseover(function(e) {
        $('#status').html(e.pageX + ', ' + e.pageY);
      });
    })
  </script>
</head>

<body onmousedown="return false;">
  <div id="wrapper">
    <canvas id="myCanvas" width="578" height="200">
    </canvas>
    <div id="buttonWrapper">
      <input type="button" id="plus" value="+"><input type="button" id="minus" value="-">
    </div>
  </div>
  <h2 id="status">
    0, 0
  </h2>
</body>

</html>

这对我来说非常适合缩放和鼠标移动。您可以自定义它以使用鼠标滚轮向上和向下。

这是一把小提琴


7
投票

如果您有源图像或画布元素以及想要绘制的 400x400 画布,则可以使用 drawImage 方法来实现缩放。

例如,完整视图可能是这样的

ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);

缩放视图可能是这样的

ctx.drawImage(img, img.width / 4, img.height / 4, img.width / 2, img.height / 2, 0, 0, canvas.width, canvas.height);

drawImage 的第一个参数是要绘制的图像元素或画布元素,接下来的 4 个参数是从源中采样的 x、y、宽度和高度,最后 4 个参数是区域的 x、y、宽度和高度在画布上绘制。然后它会为您处理缩放。

您只需要根据缩放级别选择源样本的宽度和高度,并根据单击鼠标的位置减去计算的宽度和高度的一半来选择x和y(但您需要确保矩形是“ t 出界)。


7
投票

画布缩放和平移

var ox = 0,
  oy = 0,
  px = 0,
  py = 0,
  scx = 1,
  scy = 1;
var canvas = document.getElementById("myCanvas");
canvas.onmousedown = (e) => {
  px = e.x;
  py = e.y;
  canvas.onmousemove = (e) => {
    ox -= e.x - px;
    oy -= e.y - py;
    px = e.x;
    py = e.y;
  };
};

canvas.onmouseup = () => {
  canvas.onmousemove = null;
};
canvas.onwheel = (e) => {
  let bfzx, bfzy, afzx, afzy;
  [bfzx, bfzy] = StoW(e.x, e.y);
  scx -= (10 * scx) / e.deltaY;
  scy -= (10 * scy) / e.deltaY;
  [afzx, afzy] = StoW(e.x, e.y);
  ox += bfzx - afzx;
  oy += bfzy - afzy;
};
var ctx = canvas.getContext("2d");

function draw() {
  window.requestAnimationFrame(draw);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (let i = 0; i <= 100; i += 10) {
    let sx = 0,
      sy = i;
    let ex = 100,
      ey = i;
    [sx, sy] = WtoS(sx, sy);
    [ex, ey] = WtoS(ex, ey);
    ctx.beginPath();
    ctx.moveTo(sx, sy);
    ctx.lineTo(ex, ey);
    ctx.stroke();
  }
  for (let i = 0; i <= 100; i += 10) {
    let sx = i,
      sy = 0;
    let ex = i,
      ey = 100;
    [sx, sy] = WtoS(sx, sy);
    [ex, ey] = WtoS(ex, ey);
    ctx.beginPath();
    ctx.moveTo(sx, sy);
    ctx.lineTo(ex, ey);
    ctx.stroke();
  }
}
draw();
function WtoS(wx, wy) {
  let sx = (wx - ox) * scx;
  let sy = (wy - oy) * scy;
  return [sx, sy];
}
function StoW(sx, sy) {
  let wx = sx / scx + ox;
  let wy = sy / scy + oy;
  return [wx, wy];
}
<!DOCTYPE html>
<html>
  <body>
    <canvas id="myCanvas" width="" height="" style="border: 1px solid #d3d3d3">
      Your browser does not support the canvas element.
    </canvas>
  </body>
</html>


5
投票

IIRC Canvas 是一种光栅风格的位图。它无法缩放,因为没有存储的信息可供缩放。

您最好的选择是在内存中保留两个副本(缩放和非缩放)并在鼠标单击时交换它们。


0
投票

这是我的缩放功能:

Zoom(factor_x, factor_y, graph = this.graph, translate_x=this.ctx.canvas.width/2,translate_y=this.ctx.canvas.height/2){
            const new_scale_x = this.scale_x * factor_x
            const new_scale_y = this.scale_y * factor_y
            
            // Update values
            this.translate_x += translate_x * ((this.scale_x - new_scale_x))
            this.translate_y += translate_y * ((this.scale_y - new_scale_y))
            this.scale_x = new_scale_x
            this.scale_y = new_scale_y

            this.ctx.setTransform(this.scale_x, 0, 0, this.scale_y, this.translate_x, this.translate_y) // Transform

            DrawGraph(graph)
        },

例如,缩放系数可以是 1,3,缩小系数可以是 0,7


-2
投票

一种选择是使用 css 缩放功能:

$("#canvas_id").css("zoom","x%"); 
© www.soinside.com 2019 - 2024. All rights reserved.