я когда-то задавался вопросом о создании такой переменной ширины линии, и я закончил строить свое собственное решение, и написал сообщение в блоге из него.
я скопирую первую часть этого здесь, закругленная версия также можно найти здесь: https://gamealchemist.wordpress.com/2013/08/28/variable-width-lines-in-html5-canvas/
Variable линии шириной в html5
рисования такой [переменной ширины] линии довольно легко, когда мы понимаем, что нам нужно рисовать не линию: на самом деле это многоугольник.
Если отрезок мы хотим сделать это (A, B), ситуация выглядит следующим образом:
Что мы хотим сделать на самом деле является 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:
(О замечании @ MarkE (интересного) о цепных сегментах линии, я боюсь, что это довольно сложная задача, так как в зависимости от длины линии/w1/w2/angle между сегментами существует множество конкретных случаев. Я вполне решил это, используя силовые поля a nd маршевые кубы, но я боюсь, что это совершенно не по теме! :-))
Нарисуйте очень узкий четырехугольник. – Pointy
Что @Pointy сказал или программно сломал вашу линию вверх в вычисленный набор фрагментов линии, которые становятся более узкими по ширине. –
В случае, если это может помочь, вот как вы можете нарисовать линию с переменной шириной: https://gamealchemist.wordpress.com/2013/08/28/variable-width-lines-in-html5-canvas/ – GameAlchemist