【问题标题】:How to clear part of canvas?如何清除部分画布?
【发布时间】:2013-07-06 03:26:07
【问题描述】:

Here is an example!

我正在尝试重置drawValueArc() 内的绿色弧线,以便每次单击更改按钮时,绿色弧线都会被删除并重新绘制。如何在不移除整个画布的情况下将其移除?另外,顺便说一句,我注意到Math.random() * 405 * Math.PI / 180 实际上并不总是产生适合灰色弧线的弧线,有时它比灰色弧线大,这是为什么呢?

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var cx = 150;
var cy = 150;
var startRadians = 135 * Math.PI / 180;
var endRadians = 405 * Math.PI / 180;

//main arc
ctx.beginPath();
ctx.arc(cx, cy, 58, startRadians, endRadians, false);
ctx.strokeStyle="rgb(220,220,220)";
ctx.lineWidth = 38;
ctx.stroke();

$('#setRandomValue').click(function(){
  drawValueArc(Math.random() * 405 * Math.PI / 180);
});


function drawValueArc(val){
  //ctx.clearRect(0, 0, W, H);
  ctx.beginPath();
  ctx.arc(cx, cy, 58, startRadians, val, false);
  ctx.strokeStyle = "green";
  ctx.lineWidth = 38;
  ctx.stroke();
}

【问题讨论】:

  • 这可能有点矫枉过正,但您可以考虑尝试 EaselJS createjs.com/#!/EaselJS 或其他一些画布库。这将对正在绘制的每个元素提供非常好的控制。许多简单的形状/多边形已经构建出来并且易于实现。

标签: javascript canvas


【解决方案1】:

绘制过去的边界

您面临的问题首先是您在圆上 0 度之前和之后绘制的事实。这处理起来可能很复杂,因为您需要分成两次绘制:一张用于最多 0 (360) 的部分,另一张用于剩余部分。

有一个简单的技巧可以让你更容易处理,那就是处理从 0 开始的所有角度,并在绘制时使用偏移量。

使用重绘基础的演示(我将其移至 jsfiddle,因为 jsbin 不适合我):

http://jsfiddle.net/3dGLR/

使用离屏画布演示

http://jsfiddle.net/AbdiasSoftware/Dg9Jj/

首先,对offset的一些优化和设置:

var startRadians = 0;        //just deal with angles
var endRadians = 300;
var deg2rad = Math.PI / 180; //pre-calculate this to save some cpu cycles
var offset = 122;            //adjust this to modify rotation

我们现在让主函数drawArc() 为我们完成所有计算,这样我们就可以专注于数字 - 这里我们还偏移了值:

function drawArc(color, start, end) {
    ctx.beginPath();

    ctx.arc(cx, cy, 58,
        (startRadians + offset) * deg2rad,
        (end + offset) * deg2rad, false);

    ctx.strokeStyle = color;
    ctx.lineWidth = 38;
    ctx.stroke();
}

清除上一个弧

清除之前绘制的弧线有几种技巧:

  1. 您可以将基本弧线绘制到屏幕外的画布上,然后使用drawImage() 擦除旧的。
  2. 你可以像下面的例子那样做,只是用基色重新绘制它
  3. 与 2 一样。但减去绿色弧线并从绿色弧线的末端到基础弧线的末端绘制基色。
  4. 使用fillRectclearRect 清除整个画布。

1 和 3 最快,4 最慢。

没有重构函数 (drawArc) 就这么简单:

function drawValueArc(val) {
    drawArc("rgb(220,220,220)", startRadians, endRadians);
    drawArc("green", startRadians, val);
}

由于现在所有关于 start 的内容都是基于 0 的,我们真的不需要为 drawArc 而不是 startRadians 提供除 0 以外的任何其他参数。使用新的偏移量来偏移起始位置并将endRadians 调整到您希望它停止的位置。

正如您在演示中看到的那样,使用这种技术可以检查所有内容,而无需拆分绘制。

提示:如果您发现边缘出现绿色伪影:这是由于抗锯齿造成的。只需将绿色的线宽减少 2 个像素(参见演示 2,离屏画布)。

【讨论】:

  • 我有一些阴影和标记应该在这个的最终版本中使用,如下所示:jsbin.com/oqupis/4/edit 我正在考虑将它们放在另一个画布上,在绿色变化值的画布上。你认为这是个好主意,还是我应该每次都在同一个画布上重新绘制它们?感谢您的所有帮助。
  • @sherlock IMO 我会将所有静态部分绘制到底层,只在顶层绘制绿色条。这样维护起来就更少了。但是,在这种情况下,实际上并不需要第二层——您只需重新绘制仪表的底座即可。性能应该不错。如果有用,请不要忘记投票/接受答案。 ;)
  • 这是(大部分)最终产品,如果您想查看的话。如果您有任何提示,我们将不胜感激。再次感谢。 jsfiddle.net/watson/cUSBQ/6
  • @sherlock 实际上看起来很整洁。我可以在这里给出的唯一建议是将 setInterval 替换为 requestAnimationFrame。这将使动画超级流畅。但看起来也很棒。干得好!
  • 这是一个很好的提示,但我似乎无法让它发挥作用:jsfiddle.net/watson/cUSBQ/8 ?
猜你喜欢
  • 1970-01-01
  • 2013-09-14
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 2020-07-05
  • 1970-01-01
  • 2013-01-31
  • 2015-06-24
相关资源
最近更新 更多