【问题标题】:Using Canvas via JavaScript, how can I change the radius of a circle after a button is clicked?通过 JavaScript 使用 Canvas,如何在单击按钮后更改圆的半径?
【发布时间】:2019-04-04 10:22:02
【问题描述】:

我正在尝试这样做,以便当我单击按钮更改半径大小时,它会将所有圆的半径大小更改为 5-10 之间的随机大小。

我已经尝试绘制 2 个圆(1 个黑色,1 个蓝色)并调用,然后尝试将半径更改为 5-10 之间的新随机半径大小。添加我的功能后,我看不到我画的 2 个圆圈。非常感谢任何反馈。

<canvas width="300" height="300" id="myCanvas" style="border: 1px solid black"></canvas>
<button id="changeRadius">Change Size</button>

<script>
var number = Math.min(Math.max(paraseInt(number), 5), 10);
let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
ctx.translate(100,120);
ctx.beginPath(); 
  ctx.arc(0, 0, 10, 0, 2 * Math.PI);
  ctx.fillStyle = "black";
  ctx.fill();
ctx.translate(140,120);
ctx.beginPath(); 
  ctx.arc(0, 0, 10, 0, 2 * Math.PI);
  ctx.fillStyle = "blue";
  ctx.fill();
document.getElementById("changeRadius").onclick = function() {
ctx.clearRect
ctx.translate(100,120);
ctx.beginPath(); 
  ctx.arc(0, 0, "number", 0, 2 * Math.PI);
  ctx.fillStyle = "black";
  ctx.fill();
ctx.translate(140,120);
ctx.beginPath(); 
  ctx.arc(0, 0, "number", 0, 2 * Math.PI);
  ctx.fillStyle = "blue";
  ctx.fill();
if (event.keycode == s){
ctx.translate(100,120);
ctx.beginPath(); 
  ctx.arc(0, 0, 5, 0, 2 * Math.PI);
  ctx.fillStyle = "black";
  ctx.fill();
ctx.translate(140,120);
ctx.beginPath(); 
  ctx.arc(0, 0, 5, 0, 2 * Math.PI);
  ctx.fillStyle = "blue";
  ctx.fill();
}else if (event.keycode == b) {
ctx.translate(100,120);
ctx.beginPath(); 
  ctx.arc(0, 0, 10, 0, 2 * Math.PI);
  ctx.fillStyle = "black";
  ctx.fill();
ctx.translate(140,120);
ctx.beginPath(); 
  ctx.arc(0, 0, 10, 0, 2 * Math.PI);
  ctx.fillStyle = "blue";
  ctx.fill();
}
}
</script>

【问题讨论】:

  • 您无法更改绘制到画布上的元素 - 一旦添加,它们就会成为整体的一部分。你必须重新绘制它。或者使用像 Fabric 这样的库,这样更容易处理。
  • 我试图清除上面的绘图,然后通过上面发布的代码重绘

标签: javascript html canvas


【解决方案1】:

代码中有很多简单的错误。

1.

在你调用 clearRect 的地方,你有:

ctx.clearRect

但它必须是:

ctx.clearRect(x, y, width, height);

其中 x、y、宽度和高度定义了您要清除的矩形。要清除整个画布,请使用:

ctx.clearRect(0, 0, canvas.width, canvas.height);

2.

您将parseInt 拼错为paraseInt

3.

您在ctx.arc 的调用中将"number" 作为半径...我什至不知道您要达到什么目的。它看起来像一个占位符?无论如何,它必须是一个实际的数字,而不仅仅是字符串"number"

也许您打算使用您在顶部创建但从不使用的变量number

ctx.arc(0, 0, "number", 0, 2 * Math.PI);

变成

ctx.arc(0, 0, number, 0, 2 * Math.PI);

(注意没有" 个字符)

4.

你从来没有真正更新number的值,所以即使上面的也不会做任何事情。

【讨论】:

    【解决方案2】:

    Michael,您的问题已经讨论了一段时间,但希望这个答案可能对您以及其他仍在学习 JavaScript 的人仍然有用。一旦我解决了Mat 列出的基本语法问题,缺失的圆圈就会变得可见。那时我发现了三件事。

    1. 在画布上绘制的图像可能不会出现在您预期的位置。

    2. 在你的第一个变量中声明并初始化为number 语句不会生成有效数字,更不用说随机数了。

    3. 你的代码有 ifif else 不会做任何事情的语句 没有事件处理程序。


    #1

    您的代码使用ctx.arc() 绘制一个基本圆,并使用ctx.translate() 将其移动到画布上的位置。用ctx.translate()两个参数x和y决定圆移动多远; x 是水平方向移动的距离; y 是在垂直方向上移动的距离。

    问题是你不再知道移动后画布上的位置坐标。因此,在进行下一个ctx.translate() 操作之前需要重置原点。

    要重置原点,请使用 CanvasRenderingContext2D.setTransform()e.g.

    ctx.setTransform(1, 0, 0, 1, 0, 0);
    

    from Mozilla MDN

    Canvas 2D 的 CanvasRenderingContext2D.setTransform() 方法 API 重置(覆盖)当前对身份的转换 矩阵,然后调用由参数描述的转换 这种方法。这使您可以缩放、旋转、平移(移动)和 扭曲上下文。

    此 API 专为动画绘图而设计,具有多种动态转换 2D 形状的方法。就您的代码而言,只需了解通过清除单位矩阵即可恢复 0,0(画布原点)作为随后任何绘图操作中使用的 x 和 y 值的参考。在使用 ctx.translate() 之前,请重置原点。观察代码启动时这将产生的影响。

    启动时原点重置的影响

    without / with

    每当绘制新图像时,必须首先使用 ctx.clearRect() 清除整个画布,并且在这样做之前重置原点很重要。单击每个示例中的“更改大小”按钮,以查看整个屏幕已通过原点重置清除。如果没有重置,清除矩形的原点将与最后绘制的圆的中心对齐,即清除的矩形进入圆的右下象限。

    原点重置对清除画布的影响

    without / with


    #2

    第二个问题可以通过在第一条指令之后插入alert(number) 来演示。当代码运行时,alert 报告 NaN 消息(即不是数字)。此外,随机值位于 0.0 到 1.0 的范围内,但出于您的目的可以缩放到 5.0 到 10.0 的范围内(更多信息请参见 herehere)。

    下面的代码显示了getNewRadius(), 一个函数,该函数在单击“更改大小”按钮时生成一个随机数。在函数被调用之前,常量和变量被声明和初始化。每次调用该函数时,即每次鼠标点击,它都会返回一个新的随机值radius,然后将其作为参数传递给下一个绘图函数。

    为清楚起见,我将您的变量 number 重命名为更不言自明的 radius,并将代码中的幻数替换为一些恰当命名的 constantvar


    #3

    您的ifelse if 测试范围内的语句将永远不会被执行。可测试的值可能在运行时由键盘事件(即event.keycode)创建。但是在您的代码中,没有设置处理程序来侦听此类事件。此外,Mozilla MDN 建议 keyCode is obsolete 并提出以下建议

    MDN 警告:此属性已弃用;你应该使用 改为 KeyboardEvent.key(如果可用)。

    有关键盘事件选项的更全面总结,请参阅here

    下面的代码包含一个名为setMaxOrMinRadius(e) 的基本函数,它允许通过在键盘上键入来选择最大或最小半径值。根据您的初始代码,输入s 将选择minRadius,输入b 将选择maxRadius。这个函数只有在按下一个键并且事件监听器已经被初始化时才会被识别。如果事件侦听器检测到击键,它现在将能够切换到该函数并识别按下了哪个键。

    致谢

    这个答案是退休人员、前同事鲍勃·道格拉斯和我自己的共同努力。我们已经一起学习 JavaScript 两个月了。我们欢迎提出改进建议。

    代码

    <canvas width="300" height="300" id="myCanvas" style="border: 1px solid black"></canvas>
    <button id="changeRadius">Change Size</button>
    
    <script>
    const maxRadius     = 10;
    const minRadius     = 5;
    var range           = maxRadius - minRadius;
    var radius          = maxRadius;
    
    let canvas          = document.getElementById("myCanvas");
    let ctx             = canvas.getContext("2d");
    
        document.addEventListener('keydown', setMaxOrMinRadius);
    
        drawCircles(maxRadius);
    
        document.getElementById("changeRadius").onclick = function() {
        clearCanvas();
        radius          = getNewRadius();
        drawCircles(radius);
    }
    
    function setMaxOrMinRadius(e) {
    clearCanvas();
    switch (e.which) {
        case 83:                                // type 's'
            drawCircles(minRadius);
        break;
    
        case 66:                                // type 'b'
            drawCircles(maxRadius);
        break;
        }
    }
    
    function getNewRadius() {
        var radius      = (Math.random() * minRadius) + range;
        return radius;
    }
    
    function drawCircles(radius) {
        drawBlueCircle(radius);
        drawBlackCircle(radius);
    }
    
    function clearCanvas(){
        ctx.setTransform(1, 0, 0, 1, 0, 0);     // reset origin
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
    
    function drawBlackCircle (radius) {
        ctx.setTransform(1, 0, 0, 1, 0, 0);     // reset origin
        ctx.translate(100,120);
        ctx.beginPath();
        ctx.arc(0, 0, radius, 0, 2 * Math.PI);
        ctx.fillStyle   = "black";
        ctx.fill();
    }
    
    function drawBlueCircle (radius) {
        ctx.setTransform(1, 0, 0, 1, 0, 0);     // reset origin
        ctx.translate(140,120);
        ctx.beginPath();
        ctx.arc(0, 0, radius, 0, 2 * Math.PI);
        ctx.fillStyle   = "blue";
        ctx.fill();
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 2020-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-30
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多