2016-07-07 6 views
4

Я новичок в работе с <canvas> и ужасно в математике. Я рисую простой равносторонний треугольник на холсте с помощью этой функции, которая заимствованный код от кого-то еще (не ненавидит меня):Как повернуть треугольник, не поворачивая весь холст?

drawTriangle(PosX, PosY, SideLength, Orientation) { 
    context.beginPath(); 

    var sides = 3; 

    var a = ((Math.PI * 2)/sides); 

    context.moveTo(PosX + SideLength, PosY); 

    for (var i = 1; i < sides + 1; i++) { 
     context.lineTo(PosX + SideLength * Math.cos(a*i), PosY + SideLength * Math.sin(a*i)); 
    } 

    context.closePath(); 

    return true; 
} 

Функция будет знать только центральные координаты треугольника и ориентация, чтобы указать на нее, ничего больше.

В настоящее время он рисует треугольник успешно, но «указывает» на восток.

Как поворачивать треугольник, используя параметр Orientation (в градусах) без поворота всего холста, как предлагают другие ответы?

+0

Если вращать холст, затем нарисуйте треугольник, затем повернуть холст * назад *, не будет, что достичь желаемого результата и позволит вам идти с дальнейшей отрисовки? (Вы не говорите о вращении существующего треугольника, который был нарисован ранее?) – nnnnnn

+0

Треугольник рисует каждый кадр с остальной частью холста, который содержит другие фигуры, если это помогает. – Jared

+0

Правильно, так почему же вращение холста, рисование фигуры, а затем поворот назад проблемы? Это то, что делает работающее решение внизу.(Не то, что это решение * только *, но если оно простое и оно работает ...) – nnnnnn

ответ

4

Вот функция, которая рисует любой правильный многоугольник и заданный угол:

var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 

 
var sideCount=3; 
 
var size=40; 
 
var centerX=50; 
 
var centerY=50; 
 
var strokeWidth=4; 
 
var strokeColor='purple'; 
 
var fillColor='skyblue'; 
 
var rotationDegrees=0; 
 
var rotationIncrement=1; 
 
var nextTime=0; 
 
var delay=1000/60*1; 
 

 
requestAnimationFrame(animate); 
 

 
function animate(time){ 
 
    if(time<nextTime){requestAnimationFrame(animate);return;} 
 
    nextTime=time+delay; 
 
    ctx.clearRect(0,0,cw,ch); 
 
    drawPolygon(centerX,centerY,sideCount,size,strokeWidth,strokeColor,fillColor,rotationDegrees); 
 
    rotationDegrees+=rotationIncrement; 
 
    requestAnimationFrame(animate); 
 
} 
 

 
function drawPolygon(centerX,centerY,sideCount,size,strokeWidth,strokeColor,fillColor,rotationDegrees){ 
 
    var radians=rotationDegrees*Math.PI/180; 
 
    ctx.translate(centerX,centerY); 
 
    ctx.rotate(radians); 
 
    ctx.beginPath(); 
 
    ctx.moveTo (size * Math.cos(0), size * Math.sin(0));   
 
    for (var i = 1; i <= sideCount;i += 1) { 
 
     ctx.lineTo (size * Math.cos(i * 2 * Math.PI/sideCount), size * Math.sin(i * 2 * Math.PI/sideCount)); 
 
    } 
 
    ctx.closePath(); 
 
    ctx.fillStyle=fillColor; 
 
    ctx.strokeStyle = strokeColor; 
 
    ctx.lineWidth = strokeWidth; 
 
    ctx.stroke(); 
 
    ctx.fill(); 
 
    ctx.rotate(-radians); 
 
    ctx.translate(-centerX,-centerY); }
<canvas id="canvas" width=512 height=512></canvas>
<canvas id="canvas" width=512 height=512></canvas>

+0

Я попытался добавить бит функции 'drawPolygon()'. Я где-то читал, что холсты используют восток как 0 градусов. Когда я добавил этот код, чтобы преобразовать градусы в градусы холста, треугольник прекратил рисование: «Ориентация = Ориентация - 90; if (Ориентация <0) {Ориентация = 360 + Ориентация; } '. Когда я не добавляю этот код, он рисует успешно. – Jared

+1

@ Jared. Верный! По умолчанию нулевые градусы указывают на «восток». В функции 'drawPolygon', если вы хотите, чтобы' rotationDegrees' указывал север при установке на ноль, вы можете 'rotationDegrees- = 90;' ** перед ** 'var radians ...'. BTW, вам не нужно нормализовать угол, добавив 360 градусов ... javascript нормализует значения вне 0-360 в этом диапазоне. Примечание. Я редактировал демо, чтобы включить перемещение центра треугольника в [centerX, centerY] внутри 'drawPolygon'. Ура! – markE

+0

Спасибо за ответ. Когда я добавляю 'rotationDegrees = = 90' в мой код, полигоны не нарисованы. Это моя собственная (довольно многословная) функция с изменениями, основанными на вашей функции: http://pastebin.com/htbNrWNg Без кода -90 он отлично работает. 'Orientation' обычно' 0', а после '- = 90' он становится' -90', который ожидается. – Jared

1

Чтобы повернуть треугольник

drawTriangle(PosX, PosY, SideLength, Orientation) { 
    context.setTransform(1,0,0,1,PosX,PosY); // Set position 
    context.rotate(Orientation); // set rotation in radians 
    context.beginPath(); 
    var sides = 3; 
    var a = ((Math.PI * 2)/sides); 
    context.moveTo(SideLength,0); 

    for (var i = 1; i < sides + 1; i++) { 
     context.lineTo(SideLength * Math.cos(a*i), SideLength * Math.sin(a*i)); 
    } 

    context.closePath(); 
    context.fill() 
    context.setTransform(1,0,0,1,0,0);// reset the transform 

    return true; 
} 
4

Пожалуйста, посмотрите на это fiddle. Вы можете отправить ориентацию как дополнительный параграф. Он принимает «восток», «запад», «север», «юг». Пожалуйста, подтвердите.

` функция drawTriangle (PosX, Пози, длиной стороны, ориентация) {

if (!Orientation) { 
    Orientation = 'east'; 
} 

context.beginPath(); 

var sides = 3; 

var a = ((Math.PI * 2)/sides); 
// the components have negative contributions 
if (Orientation === 'west' || Orientation === 'north') { 
    SideLength *= -1; 
} 

if (Orientation === 'east' || Orientation === 'west') { 
    context.moveTo(PosX + SideLength, PosY); 

    for (var i = 1; i < sides + 1; i++) { 
     context.lineTo(PosX + SideLength * Math.cos(a*i), PosY + SideLength * Math.sin(a*i)); 
    } 
} 
else if (Orientation === 'south' || Orientation === 'north') { 
    context.moveTo(PosY, PosX + SideLength); 

    for (var i = 1; i < sides + 1; i++) { 
     context.lineTo(PosY + SideLength * Math.sin(a*i), PosX + SideLength * Math.cos(a*i)); 
    } 
} 
context.stroke(); 
context.closePath(); 

}`

+0

Когда я устанавливаю ориентацию на север или юг, треугольник рисуется очень далеко. Когда это восток или запад, это выглядит так, как ожидалось. Вы знаете, что может быть причиной этого? – Jared

2

Математика здесь очень просто. Мы рисуем линии между равноугольными точками, взятыми из круга с радиусом радиусом (см. Приведенный ниже аргумент). Кроме того, мы должны иметь в виду, что SideLength не является реальной стороной длины многоугольника. Я упростил начальный код и добавил функцию поворота фигуры. Полученная функция вместе с примером представлена ​​ниже:

 /* here, radius means the radius of circle, inside of which polygon is drawn */ 
 
     function drawTriangle(context, PosX, PosY, radius, rotate) { 
 
      context.beginPath(); 
 

 
      /* number of vertices for polygon */ 
 
      var sides = 3; 
 
      /* angle between vertices of polygon */ 
 
      var a = ((Math.PI * 2)/sides); 
 

 
      for (var i = 0; i < sides; i++) { 
 
       context.lineTo(PosX + radius * Math.cos(a*i+rotate), PosY + radius * Math.sin(a*i+rotate)); 
 
      } 
 

 
      context.closePath(); 
 
      context.stroke(); 
 

 
      return true; 
 
     } 
 

 
     var canvas = document.getElementById("demo") 
 
     if (canvas.getContext) { 
 
      var ctx = canvas.getContext('2d'); 
 
      var PosX = 50; 
 
      var PosY = 50; 
 
      var radius = 40; 
 
      drawTriangle(ctx, PosX, PosY, radius, Math.PI/4); 
 
     }
canvas#demo 
 
{ 
 
    border: thin solid green; 
 
}
<canvas id="demo" width="200" height="200"> 
 
    This browser or document mode doesn't support canvas 
 
</canvas>

2

Чтобы повернуть только конкретную форму, но не весь холст - вы должны вращать вручную каждую точку она состоит затем сделать его с повернутыми точками ,

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

var ctx = document.getElementById("cnv").getContext('2d'); 
 
var id = 0; 
 

 
var Point2d = function(x, y) { 
 
    this.x = x || 0; 
 
    this.y = y || 0; 
 
} 
 

 
Point2d.prototype.set = function(x, y) { 
 
    this.x = x; 
 
    this.y = y; 
 
}; 
 

 
Point2d.prototype.translate = function(p) { 
 
    this.x += p.x; 
 
    this.y += p.y; 
 
    return this; 
 
}; 
 

 
//rotation around origin 
 
Point2d.prototype.rotate = function(phi) { 
 
    this.set(
 
    this.x*Math.cos(phi) - this.y*Math.sin(phi), 
 
    this.x*Math.sin(phi) + this.y*Math.cos(phi) 
 
); 
 
    return this; 
 
}; 
 

 

 
function getRegularPolygonPoints(center, numSides, sideLength) { 
 
    var points = []; 
 
    var alpha = 2*Math.PI/numSides; 
 
    for (var i = 0; i < numSides; i++) { 
 
    points.push(new Point2d( 
 
     center.x + sideLength*Math.cos(alpha*i), 
 
     center.y + sideLength*Math.sin(alpha*i)) 
 
    ) 
 
    } 
 
    return points; 
 
} 
 

 

 
function drawPolygon(points) { 
 
    ctx.beginPath(); 
 
    ctx.moveTo(points[0].x, points[0].y); 
 
    for (var i = 1; i < points.length; i++) { 
 
    ctx.lineTo(points[i].x, points[i].y); 
 
    } 
 
    ctx.lineTo(points[0].x, points[0].y);// close the shape 
 
    ctx.lineWidth = 1; 
 
    ctx.fillStyle = "#899"; 
 
    ctx.fill(); 
 
    ctx.stroke(); 
 
    ctx.closePath(); 
 
} 
 

 
function rotatePolygon(polygonPoints, phi, pointAround) { 
 
    var pointAroundInv= new Point2d(-pointAround.x, -pointAround.y); 
 
    
 
    for (var i = 0; i < polygonPoints.length; i++) { 
 
    polygonPoints[i].translate(pointAroundInv);// translate to origin 
 
    polygonPoints[i].rotate(phi);// rotate 
 
    polygonPoints[i].translate(pointAround);// translate back to it's original position 
 
    } 
 
} 
 

 
var center = new Point2d(250, 120); 
 
var regPolPoints = getRegularPolygonPoints(center, 3, 50); 
 
var currentFrame = (new Date).getTime(); 
 
var lastFrame = currentFrame; 
 
var dt = 0; 
 

 
var render = function() { 
 
    ctx.clearRect(0, 0, 400, 400); 
 
    currentFrame = (new Date).getTime(); 
 
    dt = currentFrame - lastFrame; 
 
    lastFrame = currentFrame; 
 
    
 
    rotatePolygon(regPolPoints, -dt/600, center); 
 
    drawPolygon(regPolPoints); 
 
    id = requestAnimationFrame(render); 
 
} 
 

 
id = requestAnimationFrame(render);
<canvas id="cnv" width="400" height="400"></canvas>

Смежные вопросы