2015-03-31 3 views
1

Как я могу иметь линию двух размеров с холстом?Нарисуйте линию с двумя концами разного размера

У меня есть строка Я рисую с canvas, что я хотел бы начать с шириной 30 и постепенно (пропорционально) уменьшить до размера 15, так что он достигает 15 в самом конце строки ,

Возможно, если я установил context.lineWidth в двух местах (начало и конец), это сработает.

<!DOCTYPE HTML> 
 
<html> 
 
    <head> 
 
    <style> 
 
     body { 
 
     margin: 0px; 
 
     padding: 0px; 
 
     } 
 
    </style> 
 
    </head> 
 
    <body> 
 
    <canvas id="myCanvas" width="578" height="200"></canvas> 
 
    <script> 
 
     var canvas = document.getElementById('myCanvas'); 
 
     var context = canvas.getContext('2d'); 
 

 
     context.beginPath(); 
 
     context.moveTo(100, 150); 
 
     context.lineWidth = 30; 
 
     context.lineTo(450, 50); 
 
     context.lineWidth = 15; 
 
     context.stroke(); 
 
    </script> 
 
    </body> 
 
</html>

+2

Нарисуйте очень узкий четырехугольник. – Pointy

+1

Что @Pointy сказал или программно сломал вашу линию вверх в вычисленный набор фрагментов линии, которые становятся более узкими по ширине. –

+2

В случае, если это может помочь, вот как вы можете нарисовать линию с переменной шириной: https://gamealchemist.wordpress.com/2013/08/28/variable-width-lines-in-html5-canvas/ – GameAlchemist

ответ

3

я когда-то задавался вопросом о создании такой переменной ширины линии, и я закончил строить свое собственное решение, и написал сообщение в блоге из него.
я скопирую первую часть этого здесь, закругленная версия также можно найти здесь: https://gamealchemist.wordpress.com/2013/08/28/variable-width-lines-in-html5-canvas/


Variable линии шириной в html5

рисования такой [переменной ширины] линии довольно легко, когда мы понимаем, что нам нужно рисовать не линию: на самом деле это многоугольник.

Если отрезок мы хотим сделать это (A, B), ситуация выглядит следующим образом:

enter image description here

Что мы хотим сделать на самом деле является A1, A2, B2, B1 многоугольник.

Если мы называем N вектор нормали (нарисованы на схеме), а w1 и w2 ширину в А и В, соответственно, мы имеем:
A1 = A + N * w1/2
A2 = A - N * w1/2
B1 = B + N * w2/2
B2 = B - N * w2/2

Так как же мы находим это нормальный вектор N?
Maths утверждает, что если (x, y) определяет вектор V, то его нормальные векторные координаты (-y, x).
N, вектор нормали к АВ будет, следовательно, иметь (- (yB - yA), (xB - xA)) как координаты.
Но в этом векторе есть раздражающая вещь: она зависит от длины AB, которая не является , что мы хотим: нам нужно нормализовать этот вектор, то есть иметь стандартную длину 1, поэтому, когда мы позже умножим этот вектор по w1/2, мы получим добавленный вектор длины.

Векторная нормализация осуществляется путем деления x и y вектора на длину вектора. Поскольку длина найдена с помощью теоремы phytagore в, что делает 2 квадрата, один квадратный корень, и, наконец, 2 водоразделов найти нормированный вектор N:

// computing the normalized vector normal to AB 
length = Math.sqrt(sq (xB-xA) + sq (yB - yA)) ; 
Nx  = - (yB - yA)/length ; 
Ny  =  (xB - xA)/length ; 

Так что теперь мы можем вычислить четыре точки, давайте ссылку их полилинией и заполнить полученную форму: здесь идет наш сегмент переменной ширины!

Вот Javascript код:

// varLine : draws a line from A(x1,y1) to B(x2,y2) 
// that starts with a w1 width and ends with a w2 width. 
// relies on fillStyle for its color. 
// ctx is a valid canvas's context2d. 
function varLine(ctx, x1, y1, x2, y2, w1, w2) { 
    var dx = (x2 - x1); 
    var dy = (y2 - y1); 
    w1 /= 2; w2 /= 2; // we only use w1/2 and w2/2 for computations. 
    // length of the AB vector 
    var length = Math.sqrt(sq(dx) + sq(dy)); 
    if (!length) return; // exit if zero length 
    dx /= length ; dy /= length ; 
    var shiftx = - dy * w1 // compute AA1 vector's x 
    var shifty = dx * w1 // compute AA1 vector's y 
    ctx.beginPath(); 
    ctx.moveTo(x1 + shiftx, y1 + shifty); 
    ctx.lineTo(x1 - shiftx, y1 - shifty); // draw A1A2 
    shiftx = - dy * w2 ; // compute BB1 vector's x 
    shifty = dx * w2 ; // compute BB1 vector's y 
    ctx.lineTo(x2 - shiftx, y2 - shifty); // draw A2B1 
    ctx.lineTo(x2 + shiftx, y2 + shifty); // draw B1B2 
    ctx.closePath(); // draw B2A1 
    ctx.fill();  
} 

Так давайте посмотрим результат на небольшой пример: рисование переменных сегментов по ширине в пределах круга с хорошими цветами HSL:

enter image description here

(О замечании @ MarkE (интересного) о цепных сегментах линии, я боюсь, что это довольно сложная задача, так как в зависимости от длины линии/w1/w2/angle между сегментами существует множество конкретных случаев. Я вполне решил это, используя силовые поля a nd маршевые кубы, но я боюсь, что это совершенно не по теме! :-))

+0

NICE! Я использовал его для создания кривой безье с разным размером: http://codepen.io/maudulus/pen/yyrXZy – maudulus

+0

Я думаю, что результат, который вы ищете, больше http://codepen.io/anon/pen/xberNd. В любом случае, я рад, что могу помочь, и поразил, что ваши кривые Безье выглядят еще лучше, чем мои линии! :-) – GameAlchemist

+0

ха-ха-ха-ха, да, вы правы, моя была слегка отключена. Я просто переназначил d3 sankey.js по мере необходимости ... не стесняйтесь брать взаймы. – maudulus

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