Вращающиеся прямоугольники по периметру круга на холсте - PullRequest
0 голосов
/ 01 октября 2018

Я пытаюсь создать небольшой круговой эффект «эквалайзера» с использованием JavaScript и HTML canvas для небольшого проекта, над которым я работаю, и он прекрасно работает, за исключением одной мелочи.Это просто серия прямоугольных полос, перемещающихся во времени в mp3 - ничего особенного, но в данный момент все полосы указывают в одном направлении (то есть 0 радиан или 90 градусов).

Я хочу, чтобы каждый соответствующий прямоугольник вокруг края круга указывал прямо от центральной точки, а не вправо.У меня 360 баров, поэтому, естественно, каждый должен быть повернут на 1 градус больше, чем предыдущий.

Я думал, что выполнение angle = i * Math.PI / 180 исправит это, но, похоже, не имеет значения, что я делаю с функцией поворота - они всегда заканчивают тем, что указывают странными и чудесными направлениями,и перевод в миллион миль от того места, где они были.И я не понимаю почему.Кто-нибудь может увидеть, где я иду не так?

Код моей рамки, для справки, выглядит следующим образом:

function frames() {

  // Clear the canvas and get the mp3 array
  window.webkitRequestAnimationFrame(frames);
  musicArray = new Uint8Array(analyser.frequencyBinCount);
  analyser.getByteFrequencyData(musicArray);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  bars = 360;


  for (var i = 0; i < bars; i++) {

    // Find the rectangle's position on circle edge
    distance = 100;
    var angle = i * ((Math.PI * 2) / bars);
    var x = Math.cos(angle) * distance + (canvas.width / 2);
    var y = Math.sin(angle) * distance + (canvas.height / 2);
    barWidth = 5;
    barHeight = (musicArray[i] / 4);

    // Fill with a blue-green gradient
    var grd = ctx.createLinearGradient(x, 0, x + 40, 0);
    grd.addColorStop(0, "#00CCFF");
    grd.addColorStop(1, "#00FF7F");
    ctx.fillStyle = grd;

    // Rotate the rectangle according to position
    // ctx.rotate(i*Math.PI/180); - DOESN'T WORK

    // Draw the rectangle
    ctx.fillRect(x, y, barHeight, barWidth);

  }

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Вот еще одно решение, я сохраняю ваш первоначальный подход к тригонометрии.
Но вместо прямоугольников я использовал линии, я не думаю, что для вас будет иметь значение, если вам нужно, чтобы смещение баровкак раз к mp3 все, что вам нужно сделать, это изменить var v = Math.random() + 1; на показание с амплитуды, и эти полосы будут танцевать.

const canvas = document.getElementById("c");
canvas.width = canvas.height = 170;
const ctx = canvas.getContext("2d");
ctx.translate(canvas.width / 2, canvas.height / 2)
ctx.lineWidth = 2;

let r = 40;
let bars = 180;

function draw() {
  ctx.clearRect(-100, -100, 200, 200)

  for (var i = 0; i < 360; i += (360 / bars)) {
    var angle = i * ((Math.PI * 2) / bars);
    var x = Math.cos(angle) * r;
    var y = Math.sin(angle) * r;

    ctx.beginPath();
    var v = Math.random() + 1;
    ctx.moveTo(x, y);
    ctx.lineTo(x * v, y * v)

    grd = ctx.createLinearGradient(x, y, x*2, y*2);
    grd.addColorStop(0, "blue");
    grd.addColorStop(1, "red");
    ctx.strokeStyle = grd;
    ctx.stroke();
  }
}

setInterval(draw, 100)
<canvas id="c"></canvas>
0 голосов
/ 02 октября 2018

Для ясности я удалил часть вашего кода.Я использую rotate, как вы и предполагали.Также я использую barHeight = (Math.random()* 50); вместо вашего (musicArray[i]/4);, потому что я хотел что-то показать.

Также я изменил ваши бары на 180. Очень вероятно, что у вас не будет 360 баров, но32 или 64 или 128 или 256.,,Теперь вы можете изменить числа голых на одно из этих чисел, чтобы увидеть результат.

Я рисую все вокруг начала холста и переводю контекст в центре.

Iнадеюсь, это поможет.

const canvas = document.getElementById("c");
const ctx = canvas.getContext("2d");
let cw = canvas.width = 400;
let ch = canvas.height = 400;


let bars = 180;
let r = 100;

ctx.translate(cw / 2, ch / 2)

for (var i = 0; i < 360; i += (360 / bars)) {

  // Find the rectangle's position on circle edge

  var angle = i * ((Math.PI * 2) / bars);
  //var x = Math.cos(angle)*r+(canvas.width/2);
  //var y = Math.sin(angle)*r+(canvas.height/2);
  barWidth = 2 * Math.PI * r / bars;
  barHeight = (Math.random() * 50);


  ctx.fillStyle = "green";

  // Rotate the rectangle according to position
  // ctx.rotate(i*Math.PI/180); - DOESN'T WORK

  // Draw the rectangle
  ctx.save();
  ctx.rotate(i * Math.PI / 180);

  ctx.fillRect(r, -barWidth / 2, barHeight, barWidth);

  //ctx.fillRect(r ,0, barHeight, barWidth);

  ctx.restore();
}
canvas {
  border: 1px solid
}
<canvas id="c"></canvas>
...