PDA

Просмотр полной версии : Градиентная заливка треугольника


Волгоградец
21.02.2011, 12:51
Привет. Мне нужно получить такой треугольник:

26052

Вот его координаты:
g.lineStyle(1);
g.moveTo(200, 100);
g.lineTo(250, 150) g.lineTo(50, 250);
g.lineTo(200, 100);
Как мне его залить градиентом так, чтобы получилось как на картинке? Т.е. начинается от катета P1P3 и идет параллельно катету P1P2. Ширина градиентной заливки получается равна длине P1P2 и наклон в данном примере 45 градусов.
Я знаю что нужную матрицу надо получить из matrix.createGradientBox(), но что передавать туда? Вообще этот метод ведет себя странно очень - по идее наклон градиента должен быть таким, каким я его задаю третьим параметром в этом методе, но, чёрт побери, он меняется в зависимости от ширины и высоты что я передаю в метод!!!

in4core
21.02.2011, 13:43
Вы вкурсе что наклон задается Math.PI ? Если да, то проблем не должно быть поидее

cleptoman
21.02.2011, 13:46
точно, константой )

shootkin
21.02.2011, 14:30
Как-то так:
var p1 : Point = new Point( 200, 100 );
var p2 : Point = new Point( 250, 150 );
var p3 : Point = new Point( 50, 250 );
var triangle : Shape = new Shape();
var g : Graphics = triangle.graphics;
var gradient_colors : Array = new Array( 0x000000, 0xFFFFFF );
var gradient_alphas : Array = new Array( 1.0, 1.0 );
var gradient_ratios : Array = new Array( 0, 255 );
var gradient_matrix : Matrix = new Matrix();
var angle : Number = Math.atan2( p2.y - p1.y, p2.x - p1.x );
gradient_matrix.createGradientBox( p2.x - p1.x, p2.y - p1.y, angle, p1.x, p1.y );
g.beginGradientFill( GradientType.LINEAR, gradient_colors, gradient_alphas, gradient_ratios, gradient_matrix );
g.lineStyle( 1 );
g.moveTo( 200, 100 );
g.lineTo( 250, 150 ); triangle.graphics.lineTo( 50, 250 );
g.lineTo( 200, 100 );
g.endFill();
addChild( triangle );

Объяснять лень.
Ах да, раз уж есть p1, p2 и p3, то в moveTo() и lineTo() лучше, конечно, их использовать.

Волгоградец
21.02.2011, 17:38
Нет, такой вариант не прокатывает - если менять точки p1, p2, p3 - то все ломается. Нужен универсальный способ.

samana
21.02.2011, 17:57
Я не уверен, но кажется с помощью drawTriangles можно положить текстуру задав нужные UV.

Волгоградец
21.02.2011, 18:21
Да, но текстура нужна в виде Bitmap. А мне нужна векторная заливка.
Еще интересный момент с createGradientBox:
m.createGradientBox(w, h, r, x, y);
не то же самое, что
m.createGradientBox(w, h);
m.rotate(r);
m.tx = x;
m.ty = y;
Что там творится внутри этого метода?

samana
21.02.2011, 18:44
Просто мысль. А если делать градиентный прямоугольник и ограничивать его треугольной маской?

Волгоградец
21.02.2011, 18:56
Не хотелось бы многоходовки применять...
Вобщем удалось мне сделать то что хотел - главное не передавать аргументы в метод, а потом дергать методы матрицы (см. пост 7).
Всем спасибо.

shootkin
21.02.2011, 19:12
Хоть я и понимаю, что опоздал, но свои ошибки надо исправлять.
Да, ротацию и перемещение лучше не доверять методу createGradientBox.
gradient_matrix.createGradientBox( Point.distance( p1, p2 ), 16, 0, 0, 0 );
gradient_matrix.rotate( Math.atan2( p2.y - p1.y, p2.x - p1.x ) );
gradient_matrix.translate( p1.x, p1.y );

То есть в createGradientBox осталась только ширина градиента.

Волгоградец
21.02.2011, 19:17
Не - там translate надо делать не в p1, а в центр треугольника (если точнее - то в центр OOBB). А почему высота 16 ))) (я знаю что там можно все что угодно кроме 0, но почему именно 16).

shootkin
21.02.2011, 19:27
16 - 2 в четвертой степени. Просто первое число, которое пришло в голову.
Насчет транслирования в центр треугольника - не понимаю зачем. У меня работает как надо с трансляцией в первую точку, что вполне логично. Градиент получается полный от первой вершины до второй. Попробовал транслировать в центр, градиент получился половинчатым.

i.o.
21.02.2011, 19:50
Что там творится внутри этого метода?
отвечаю на ваш вопрос:

playerglobal_10.1.swc -> flash.geom.Matrix:

public function createBox(scaleX:Number, scaleY:Number, rotation:Number = 0, tx:Number = 0, ty:Number = 0) : void
{
this.identity();
this.rotate(rotation);
this.scale(scaleX, scaleY);
this.tx = tx;
this.ty = ty;
return;
}

public function createGradientBox(width:Number, height:Number, rotation:Number = 0, tx:Number = 0, ty:Number = 0) : void
{
this.createBox(width / 1638.4, height / 1638.4, rotation, tx + width / 2, ty + height / 2);
return;
}

Волгоградец
21.02.2011, 19:57
Градиент вращается вокруг центра (центр здесь - это центр прямоугольника, заданного в виде width, height), и 'точка регистрации' находится в центре. Когда делаешь translate - ты прибавляешь к уже существующим tx и ty некоторое значение, т.е. неочевидно совершенно какие параметры стали у матрицы. Правильнее жестко задать эти tx и ty.

@i.o.: снова эти магические цифры... Лично мне совсем не понятно что они означают. Особенно эти 1638.4. Зачем это?

i.o.
21.02.2011, 20:08
@i.o.: снова эти магические цифры... Лично мне совсем не понятно что они означают. Особенно эти 1638.4. Зачем это?
Мне то откуда знать? :)

Добавлено через 2 минуты
Волгоградец, зная как работает createGradientBox и как вы не хотели бы чтобы он работал, то можете написать свой вариант. Т.к. все равно используется Matrix.

Волгоградец
21.02.2011, 20:16
Мне то откуда знать?
Это был риторический вопрос :)

createGradientBox оказался простым - вся магия вероятно происходит в beginGradientFill.

Zebestov
21.02.2011, 20:17
Работает для любого прямоугольного треугольника вроде.


var p1:Point = new Point(50, 250);
var p2:Point = new Point(200, 100); // corner point
var p3:Point = new Point(250, 150);
var d23:Number = Point.distance(p2, p3);

var angle:Number = Math.atan2(p3.y - p2.y, p3.x - p2.x);

var matrix:Matrix = new Matrix();
matrix.createGradientBox(d23, d23, angle, (p3.x + p2.x) / 2 - d23 / 2, (p3.y + p2.y) / 2 - d23 / 2);

graphics.lineStyle(0, 0);
graphics.beginGradientFill(GradientType.LINEAR, [0x000000, 0xffffff], [1, 1], [0, 255], matrix);
graphics.moveTo(p1.x, p1.y);
graphics.lineTo(p2.x, p2.y);
graphics.lineTo(p3.x, p3.y);
graphics.lineTo(p1.x, p1.y);
graphics.endFill();

Волгоградец
21.02.2011, 20:36
Да, тоже вариант. Спасибо.