HTML 5 Canvas, вращайте все

Я сделал цилиндрический манометр, очень похожий на этот:

похоже на это

Он нарисован с использованием около 7 функций... мой немного отличается. Это очень гибко, так как я могу установить цвета, прозрачность, высоту, ширину, отображение текста в процентах и ​​множество других параметров. Но теперь мне нужно то же самое, но все повернуто на 90 градусов, чтобы я мог установить большую высоту и низкую ширину, чтобы создать что-то вроде этого:

горизонтальный

Я нашел ctx.rotate, но независимо от того, куда он идет, все фигуры разваливаются. Похоже, что ctx.save/restore ничего не делает, я попытался добавить это в каждую функцию рисования фигуры. Например, я попытался изменить функцию drawOval так, чтобы она сначала поворачивала холст, если горизонталь была установлена ​​на единицу; но казалось, что он вращал его каждую итерацию, даже с сохранением/восстановлением... так что верхний цилиндр вращался, а нижний вращался дважды или что-то в этом роде. Очень сложно сказать, что происходит на самом деле. Что я делаю неправильно? Я не хочу дублировать весь этот код и тратить часы на его настройку, просто чтобы создать что-то, что у меня уже есть, но стало горизонтальным. Эрг! Помощь.


person gunslingor    schedule 23.06.2015    source источник


Ответы (2)


Опция 1

Чтобы повернуть все, просто примените преобразование к самому элементу:

canvas.style.transform = "rotate(90deg)";         // or -90 depending on need
canvas.style.webkitTransform = "rotate(90deg)";

Вариант 2

Поворачивайте контекст перед рисованием чего-либо и перед использованием любой функции save(). В отличие от версии CSS, вам сначала нужно будет перевести в центр, затем повернуть и, наконец, перевести обратно.

Вам нужно будет убедиться, что ширина и высота холста поменялись местами, прежде чем это будет выполнено.

ctx.translate(ctx.canvas.width * 0.5, ctx.canvas.height * 0.5);    // center
ctx.rotate(Math.PI * 0.5);                                         // 90°
ctx.translate(-ctx.canvas.width * 0.5, -ctx.canvas.height * 0.5);

И конечно, как вариант 3, вы можете пересчитать все свои значения, чтобы они шли по другой оси.

person Community    schedule 24.06.2015

Посмотрите на функцию поворота в этом примере. Вы хотите сделать перевод в точку, вокруг которой хотите повернуться.

example1();
example2();

function rotate(ctx, degrees, x, y, fn) {
  ctx.save();
  ctx.translate(x, y);
  ctx.rotate(degrees * (Math.PI / 180));
  fn();
  ctx.restore();
}

function rad(deg) {
  return deg * (Math.PI / 180);
}

function example2() {
  var can = document.getElementById("can2");
  var ctx = can.getContext('2d');
  var w = can.width;
  var h = can.height;

  function drawBattery() {
      var percent = 60;
    
      ctx.beginPath();
    
      ctx.arc(35,50, 25,0,rad(360));
      ctx.moveTo(35+percent+25,50);
      ctx.arc(35+percent,50,25,0,rad(360));
      ctx.stroke();
    
      ctx.beginPath();
      ctx.fillStyle = "rgba(0,255,0,.5)";
      ctx.arc(35,50,25,0,rad(360));
      ctx.arc(35+percent,50,25,0,rad(360));
      ctx.rect(35,25,percent,50);
      ctx.fill();
          
      ctx.beginPath();
      ctx.lineWidth = 2;
      ctx.strokeStyle = "#666666";
      ctx.moveTo(135,25);
      ctx.arc(135,50,25, rad(270), rad(269.9999));
      //ctx.moveTo(35,75);
      ctx.arc(35,50,25,rad(270),rad(90), true);

      ctx.lineTo(135,75);
      ctx.stroke();
  }
  
  drawBattery();

  can = document.getElementById("can3");
  ctx = can.getContext('2d');
  w = can.width;
  h = can.height;
  rotate(ctx, -90, 0, h, drawBattery);
}


function example1() {
  var can = document.getElementById('can');
  var ctx = can.getContext('2d');
  var color1 = "#FFFFFF";
  var color2 = "#FFFF00";
  var color3 = "rgba(0,155,255,.5)"
  var text = 0;

  function fillBox() {
    ctx.save();
    ctx.fillStyle = color3;
    ctx.fillRect(0, 0, can.width / 2, can.height);
    ctx.restore();
  }

  function drawBox() {
    ctx.save();
    ctx.beginPath();
    ctx.strokeStyle = ctx.fillStyle = color1;
    ctx.rect(10, 10, 50, 180);
    ctx.font = "30px Arial";
    ctx.fillText(text, 25, 45);
    ctx.stroke();
    ctx.beginPath();
    ctx.strokeStyle = color2;
    ctx.lineWidth = 10;
    ctx.moveTo(10, 10);
    ctx.lineTo(60, 10);
    ctx.stroke();
    ctx.restore();
  }

  fillBox();
  rotate(ctx, 90, can.width, 0, fillBox);

  text = "A";
  drawBox();
  color1 = "#00FFFF";
  color2 = "#FF00FF";
  text = "B";
  rotate(ctx, 90, can.width, 0, drawBox);

  centerRotatedBox()

  function centerRotatedBox() {

    ctx.translate(can.width / 2, can.height / 2);
    for (var i = 0; i <= 90; i += 10) {
      var radians = i * (Math.PI / 180);
      ctx.save();
      ctx.rotate(radians);
      ctx.beginPath();
      ctx.strokeStyle = "#333333";
      ctx.rect(0, 0, 50, 50)
      ctx.stroke();
      ctx.restore();
    }
  }

}
#can,
#can2,
#can3 {
  border: 1px solid #333333
}
<canvas id="can" width="200" height="200"></canvas>
<canvas id="can2" width="200" height="100"></canvas>
<canvas id="can3" width="100" height="200"></canvas>

person wolfhammer    schedule 23.06.2015
comment
Спасибо, я думаю, что все это понимаю ... моя проблема в том, что я нарисовал около 10 таких примитивных фигур (например, круг или квадрат), которые меняются в зависимости от %, на который цилиндр должен быть заполнен; градиенты, где также добавлены. Итак, теперь мне нужно повернуть все на 90 градусов, чтобы оно вело себя на 100% так же, просто повернув. т.е. После рисования мне нужно повернуть весь холст, а не 10 или около того разных фигур. Я попытался повернуть каждую часть по отдельности, но это не работает, как описано. - person gunslingor; 24.06.2015
comment
@user2550940 user2550940 Я добавил еще один пример, который показывает, как вы можете поворачивать изображение от широкого к высокому. Инкапсулируйте свои процедуры рисования в функцию и передайте ее функции поворота вместе с холстом, ширина и высота которого поменялись местами. - person wolfhammer; 24.06.2015