2009-04-30 2 views
34

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

У кого есть ключ к этому вопросу?

Спасибо

ответ

1

Вы можете нажать вашу матрицу, вращать его, рисовать стрелу, а затем поп-матрицу.

7

Вы можете сделать:

ctx.save(); 
ctx.translate(xOrigin, yOrigin); 
ctx.rotate(angle); 
// draw your arrow, with its origin at [0, 0] 
ctx.restore(); 
1
function RTEShape() 
{ 
    this.x = 50; 
    this.y = 50; 
    this.w = 100; // default width and height? 
    this.h = 100; 
    this.fill = '#444444'; 
    this.text = "Test String"; 
    this.type; 
    this.color; 
    this.size = 6;  

    // The selection color and width. Right now we have a red selection with a small width 
    this.mySelColor = '#CC0000'; 
    this.mySelWidth = 2; 
    this.mySelBoxColor = 'darkred';// New for selection boxes 
    this.mySelBoxSize = 6; 
} 

RTEShape.prototype.buildArrow = function(canvas) 
{ 
    this.type = "arrow"; 

    // Make sure we don't execute when canvas isn't supported 
    if (canvas.getContext){ 

    // use getContext to use the canvas for drawing 
    var ctx = canvas.getContext('2d');   

    var oneThirdX = this.x + (this.w/3);    
    var twoThirdX = this.x + ((this.w*2)/3); 

    var oneFifthY = this.y - (this.y/5);  
    var twoFifthY = this.y - ((this.y*3)/5); 

    /**/ 
    //ctx.beginPath(); 
    ctx.moveTo(oneThirdX,this.y); // 125,125 
    ctx.lineTo(oneThirdX,oneFifthY); // 125,105 

    ctx.lineTo(this.x*2,oneFifthY); // 225,105  
    ctx.lineTo(this.x*2,twoFifthY); // 225,65 

    ctx.lineTo(oneThirdX,twoFifthY); // 125,65  
    ctx.lineTo(oneThirdX,(this.y/5)); // 125,45 

    ctx.lineTo(this.x,(this.y+(this.y/5))/2); // 45,85 

     ctx.fillStyle = "green"; 
    ctx.fill(); 

    ctx.fillStyle = "yellow"; 
    ctx.fillRect(this.x,this.y,this.w,this.h); 

    } else { 
    alert('Error on buildArrow!\n'+err.description); 
    } 
} 
63

Как просто, как я могу получить его. Вы должны предварять context.beginPath() и добавить context.stroke() самостоятельно:

function canvas_arrow(context, fromx, fromy, tox, toy){ 
    var headlen = 10; // length of head in pixels 
    var angle = Math.atan2(toy-fromy,tox-fromx); 
    context.moveTo(fromx, fromy); 
    context.lineTo(tox, toy); 
    context.lineTo(tox-headlen*Math.cos(angle-Math.PI/6),toy-headlen*Math.sin(angle-Math.PI/6)); 
    context.moveTo(tox, toy); 
    context.lineTo(tox-headlen*Math.cos(angle+Math.PI/6),toy-headlen*Math.sin(angle+Math.PI/6)); 
} 

Вот пример: http://stuff.titus-c.ch/arrow.html

+1

Это создает странную форму, вы хотите, чтобы избавиться от этого последнего шага и добавить в конце LineTo (токсикодендрон, игрушка) – owook

+1

функция не работает хорошо, когда lineWidth не == 1 –

+0

отлично работает с 2: P '+ 1' –

2

Учитывая размер и начальную позицию, следующий код будет рисовать стрелка для вас.

<!DOCTYPE HTML> 
<html> 
    <head> 
     <style> 
      body { 
       margin: 0px; 
       padding: 0px; 
      } 

      #myCanvas { 
       border: 1px solid #9C9898; 
      } 
     </style> 
     <script> 
      function draw_arrow(context, startX, startY, size) 
      { 
       var arrowX = startX + 0.75*size; 
       var arrowTopY = startY - 0.707*(0.25*size); 
       var arrowBottomY = startY + 0.707*(0.25*size); 
       context.moveTo(startX, startY); 
       context.lineTo(startX+size, startX); 
       context.lineTo(arrowX, arrowTopY); 
       context.moveTo(startX+size, startX); 
       context.lineTo(arrowX, arrowBottomY); 
       context.stroke(); 
      } 
      window.onload = function(){ 
       var canvas = document.getElementById("myCanvas"); 
       var context = canvas.getContext("2d"); 
       var startX = 50; 
       var startY = 50; 
       var size = 100; 
       context.lineWidth = 2; 
       draw_arrow(context, startX, startY, size); 
      }; 
     </script> 
    </head> 
    <body onmousedown="return false;"> 
     <canvas id="myCanvas" width="578" height="200"> 
     </canvas> 

    </body> 
</html> 
16

Итак, первый ответ на этой странице мне очень помог, когда я пытался понять эту проблему вне себя, хотя, как кто-то уже было сказано, если у вас есть ширина больше, чем 1px вы получите забавные формы линии , Исправление, которое предложил кто-то другой, почти сработало, но у меня все еще были проблемы при попытке использовать более толстую стрелку ширины. После нескольких часов игры с ним я смог объединить вышеупомянутое решение с некоторыми из моих собственных мастерингов, чтобы придумать следующий код, который будет рисовать стрелу любой нужной толщины без искажения формы стрелки.

function drawArrow(fromx, fromy, tox, toy){ 
       //variables to be used when creating the arrow 
       var c = document.getElementById("myCanvas"); 
       var ctx = c.getContext("2d"); 
       var headlen = 10; 

       var angle = Math.atan2(toy-fromy,tox-fromx); 

       //starting path of the arrow from the start square to the end square and drawing the stroke 
       ctx.beginPath(); 
       ctx.moveTo(fromx, fromy); 
       ctx.lineTo(tox, toy); 
       ctx.strokeStyle = "#cc0000"; 
       ctx.lineWidth = 22; 
       ctx.stroke(); 

       //starting a new path from the head of the arrow to one of the sides of the point 
       ctx.beginPath(); 
       ctx.moveTo(tox, toy); 
       ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7)); 

       //path from the side point of the arrow, to the other side point 
       ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7)); 

       //path from the side point back to the tip of the arrow, and then again to the opposite side point 
       ctx.lineTo(tox, toy); 
       ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7)); 

       //draws the paths created above 
       ctx.strokeStyle = "#cc0000"; 
       ctx.lineWidth = 22; 
       ctx.stroke(); 
       ctx.fillStyle = "#cc0000"; 
       ctx.fill(); 
      } 

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

Надеюсь, это поможет!

+0

спасибо, это отлично работает! – satnam

+0

Ты прибил его мужчине! – Exception

1

Вот еще один способ рисования стрелок. Он использует метод треугольника отсюда: https://stackoverflow.com/a/8937325/1828637

Немного вспомогательной функции.

функция canvas_arrow (контекст, fromx, fromy, tox, toy, r) { var x_center = tox; var y_center = игрушка;

var angle; 
var x; 
var y; 

context.beginPath(); 

angle = Math.atan2(toy-fromy,tox-fromx) 
x = r*Math.cos(angle) + x_center; 
y = r*Math.sin(angle) + y_center; 

context.moveTo(x, y); 

angle += (1/3)*(2*Math.PI) 
x = r*Math.cos(angle) + x_center; 
y = r*Math.sin(angle) + y_center; 

context.lineTo(x, y); 

angle += (1/3)*(2*Math.PI) 
x = r*Math.cos(angle) + x_center; 
y = r*Math.sin(angle) + y_center; 

context.lineTo(x, y); 

context.closePath(); 

context.fill(); 

}

А вот демонстрация его рисовать стрелки в начале и в конце строки.

var can = document.getElementById('c'); 
 
var ctx = can.getContext('2d'); 
 

 
ctx.lineWidth = 10; 
 
ctx.strokeStyle = 'steelblue'; 
 
ctx.fillStyle = 'steelbllue'; // for the triangle fill 
 
ctx.lineJoin = 'butt'; 
 

 
ctx.beginPath(); 
 
ctx.moveTo(50, 50); 
 
ctx.lineTo(150, 150); 
 
ctx.stroke(); 
 

 
canvas_arrow(ctx, 50, 50, 150, 150, 10); 
 
canvas_arrow(ctx, 150, 150, 50, 50, 10); 
 

 
function canvas_arrow(context, fromx, fromy, tox, toy, r){ 
 
\t var x_center = tox; 
 
\t var y_center = toy; 
 
\t 
 
\t var angle; 
 
\t var x; 
 
\t var y; 
 
\t 
 
\t context.beginPath(); 
 
\t 
 
\t angle = Math.atan2(toy-fromy,tox-fromx) 
 
\t x = r*Math.cos(angle) + x_center; 
 
\t y = r*Math.sin(angle) + y_center; 
 

 
\t context.moveTo(x, y); 
 
\t 
 
\t angle += (1/3)*(2*Math.PI) 
 
\t x = r*Math.cos(angle) + x_center; 
 
\t y = r*Math.sin(angle) + y_center; 
 
\t 
 
\t context.lineTo(x, y); 
 
\t 
 
\t angle += (1/3)*(2*Math.PI) 
 
\t x = r*Math.cos(angle) + x_center; 
 
\t y = r*Math.sin(angle) + y_center; 
 
\t 
 
\t context.lineTo(x, y); 
 
\t 
 
\t context.closePath(); 
 
\t 
 
\t context.fill(); 
 
}
<canvas id="c" width=300 height=300></canvas>

1

Этот код похож на решение Titus Cieslewski в, может быть, стрелка немного лучше:

function canvasDrawArrow(context, fromx, fromy, tox, toy) { 
    var headlen = 10.0; 
    var back = 4.0; 
    var angle1 = Math.PI/13.0; 
    var angle2 = Math.atan2(toy - fromy, tox - fromx); 
    var diff1 = angle2 - angle1; 
    var diff2 = angle2 + angle1; 
    var xx = getBack(back, fromx, fromy, tox, toy); 
    var yy = getBack(back, fromy, fromx, toy, tox); 

    context.moveTo(fromx, fromy); 
    context.lineTo(tox, toy); 

    context.moveTo(xx, yy); 
    context.lineTo(xx - headlen * Math.cos(diff1), yy - headlen * Math.sin(diff1)); 

    context.moveTo(xx, yy); 
    context.lineTo(xx - headlen * Math.cos(diff2), yy - headlen * Math.sin(diff2)); 
} 

function getBack(len, x1, y1, x2, y2) { 
    return x2 - (len * (x2 - x1)/(Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2)))); 
} 

это хорошо работает с lineWidth > 1. Это может пригодиться при составлении x и y оси

0

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

 
ctx.clearRect(0, 0, canvas.width, canvas.height); \t 
 
arrow({x: 10, y: 10}, {x: 100, y: 170}, 10); 
 
arrow({x: 40, y: 250}, {x: 10, y: 70}, 5); 
 

 

 
function arrow (p1, p2, size) { 
 
    var angle = Math.atan2((p2.y - p1.y) , (p2.x - p1.x)); 
 
    var hyp = Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)); 
 

 
    ctx.save(); 
 
    ctx.translate(p1.x, p1.y); 
 
    ctx.rotate(angle); 
 

 
    // line 
 
    ctx.beginPath(); \t 
 
    ctx.moveTo(0, 0); 
 
    ctx.lineTo(hyp - size, 0); 
 
    ctx.stroke(); 
 

 
    // triangle 
 
    ctx.fillStyle = 'blue'; 
 
    ctx.beginPath(); 
 
    ctx.lineTo(hyp - size, size); 
 
    ctx.lineTo(hyp, 0); 
 
    ctx.lineTo(hyp - size, -size); 
 
    ctx.fill(); 
 

 
    ctx.restore(); 
 
}
<canvas id = "canvas" width = "300" height = "400"></canvas>

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