CreateJS径向渐变与矩阵
Posted
技术标签:
【中文标题】CreateJS径向渐变与矩阵【英文标题】:CreateJS Radial gradient with matrix 【发布时间】:2016-06-03 05:46:55 【问题描述】:我正在将 Flash 应用程序转换为 html5 Canvas。大部分开发已经完成,但是为了处理颜色,在 flash 应用程序中有这样的代码:
matrix = new Matrix ();
matrix.createGradientBox (600, ColorHeight * 1200, 0, 80, ColorHeight * -600);
Animation_gradient_mc.clear ();
Animation_gradient_mc.beginGradientFill (fillType, colors, alphas, ratios, matrix, spreadMethod, interpolationMethod, focalPointRatio);
CreateJS 中径向渐变的声明如下:
beginRadialGradientFill(colors, ratios, x0, y0, r0, x1, y1, r1 )
有人知道将矩阵应用于渐变填充的方法吗?
任何帮助将不胜感激。
提前致谢
编辑
以下是我尝试重现的渐变的一些示例:
如您所见,它以标准径向渐变开始。
但是,它也可能显得拉伸,我认为这是矩阵的帮助。
我试图通过创建一个带有矩阵的 createjs.Graphics.Fill 来创建相同的效果,但它似乎没有做任何事情:
var matrix = new VacpMatrix();
matrix.createGradientBox(
600,
discharge_gradient.color_height * 1200,
0,
80,
discharge_gradient.color_height * -600
);
// test_graphics.append(new createjs.Graphics.Fill('#0000ff', matrix));
console.log('matrix', matrix);
test_graphics.append(new createjs.Graphics.Fill('#ff0000', matrix).radialGradient(
discharge_gradient.colors,
discharge_gradient.ratios,
discharge_gradient.x0,
discharge_gradient.y0,
discharge_gradient.r0,
discharge_gradient.x1,
discharge_gradient.y1,
discharge_gradient.r1
));
var discharge_shape = new createjs.Shape(test_graphics);
我扩展了 Matrix2d 类以使用来自 openfl 项目的代码添加一个 createGradientBox 方法:
p.createGradientBox = function (width, height, rotation, tx, ty)
if (_.isUndefined(rotation) || _.isNull(rotation))
rotation = 0;
if (_.isUndefined(tx) || _.isNull(tx))
tx = 0;
if (_.isUndefined(ty) || _.isNull(ty))
ty = 0;
var a = width / 1638.4,
d = height / 1638.4;
// Rotation is clockwise
if (rotation != 0)
var cos = math.cos(rotation),
sin = math.sin(rotation);
this.b = sin * d;
this.c = -sin * a;
this.a = a * cos;
this.d = d * cos;
else
this.b = 0;
this.c = 0;
this.tx = tx + width / 2;
this.ty = ty + height / 2;
我希望额外的信息有用。
【问题讨论】:
您是否有一个使用 CreateJS 无法重现的矩阵制作的 AS3 渐变的视觉示例?显示您尝试过的代码,以便其他人可以看到您要去哪里... 【参考方案1】:标准矩阵会按以下顺序调整输入:Width, angle Horizontal, angle Vertical, Height, pos X, pos Y
,
您在这里使用的是 gradientBox,这不是通常的 AS3 矩阵类型。预期输入:Width, Height, Rotation, pos X, pos Y
我不使用 createJS,所以我猜这个(你建立在它之上)...
你平时的beginRadialGradientFill(colors, ratios, x0, y0, r0, x1, y1, r1 )
变成如下(好像涉及到梯度框矩阵):beginRadialGradientFill(colors, ratios, posX, posY, Rotation, Width, Height, Rotation )
【讨论】:
我已尝试按照您的建议插入参数,但似乎无法正常工作。 html5/canvas 渐变是使用 2 个圆圈制作的,因此更改参数只会移动第二个圆圈的坐标 我现在从更新中看到,您还需要拉伸/挤压。你能不只是缩放画布绘制的渐变,然后将它叠加在另一个画布背景上作为最终输出吗?【参考方案2】:我不太了解createJS,也不了解Flash Matrix
对象,但是要使用原生Canvas2d API 制作这种ovalGradient,您需要转换上下文的矩阵。
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var horizontalScale = .3;
var verticalScale = 1;
var gradient = ctx.createRadialGradient(100/horizontalScale, 100/verticalScale, 100, 100/horizontalScale,100/verticalScale,0);
gradient.addColorStop(0,"green");
gradient.addColorStop(1,"red");
// shrink the context's matrix
ctx.scale(horizontalScale, verticalScale)
// draw your gradient
ctx.fillStyle = gradient;
// stretch the rectangle which contains the gradient accordingly
ctx.fillRect(0,0, 200/horizontalScale, 200/verticalScale);
// reset the context's matrix
ctx.setTransform(1,0,0,1,0,0);
canvas background-color: ivory;
<canvas id="canvas" width="200" height="200"></canvas>
因此,如果您打算编写某种函数来重现它,请查看 ctx.scale()
、ctx.transform()
和 ctx.setTransform()
。
编辑
正如您所注意到的,这也会缩小您绘制的形状,此外,您必须计算应该在绘图中“取消缩小”多少,就像我对 fillRect
所做的那样。 (同意,这个很简单)
这是一个可以帮助您处理更复杂形状的函数。我并没有真正测试它(仅使用给定的示例),所以它可能会以某种方式失败,但它也可以让您了解如何处理它:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
function shrinkedRadial(ctx, shapeArray, xScale, yScale, gradientOpts)
// scaling by 0 is like not drawing
if (!xScale || !yScale) return;
var gO = gradientOpts;
// apply our scale on the gradient options we passed
var gradient = ctx.createRadialGradient(gO.x0 / xScale, gO.y0 / yScale, gO.r0, gO.x1 / xScale, gO.y1 / yScale, gO.r1);
gradient.addColorStop(gO.c1_pos, gO.c1_fill);
gradient.addColorStop(gO.c2_pos, gO.c2_fill);
// shrink the context's matrix
ctx.scale(xScale, yScale);
ctx.fillStyle = gradient;
// execute the drawing operations' string
shapeArray.forEach(function(str)
var val = str.split(' ');
var op = shapesRef[val[0]];
if (val[1])
var pos = val[1].split(',').map(function(v, i)
// if even, it should be an y axis, otherwise an x one
return i % 2 ? v / yScale : v / xScale;
);
ctx[op].apply(ctx, pos);
else
// no parameters
ctx[op]();
);
// apply our gradient
ctx.fill();
// reset the transform matrix
ctx.setTransform(1, 0, 0, 1, 0, 0);
// just for shortening our shape drawing operations
// notice how arc operations are omitted, it could be implemented but...
var shapesRef =
b: 'beginPath',
fR: 'fillRect',
m: 'moveTo',
l: 'lineTo',
bC: 'bezierCurveTo',
qC: 'quadraticCurveTo',
r: 'rect',
c: 'closePath'
;
var gradientOpts =
x0: 232,
y0: 55,
r0: 70,
x1: 232,
y1: 55,
r1: 0,
c1_fill: 'red',
c1_pos: 0,
c2_fill: 'green',
c2_pos: 1
var shapes = ['b', 'm 228,133', 'bC 209,121,154,76,183,43', 'bC 199,28,225,34,233,59', 'bC 239,34,270,29,280,39', 'bC 317,76,248,124,230,133']
// our shape is drawn at 150px from the right so we do move the context accordingly, but you won't have to.
ctx.translate(-150, 0);
shrinkedRadial(ctx, shapes, .3, 1, gradientOpts);
ctx.font = '15px sans-serif';
ctx.fillStyle = 'black';
ctx.fillText('shrinked radialGradient', 3, 20);
// how it looks like without scaling :
ctx.translate(50, 0)
var gO = gradientOpts;
var gradient = ctx.createRadialGradient(gO.x0, gO.y0, gO.r0, gO.x1, gO.y1, gO.r1);
gradient.addColorStop(gO.c1_pos, gO.c1_fill);
gradient.addColorStop(gO.c2_pos, gO.c2_fill);
ctx.fillStyle = gradient;
shapes.forEach(function(str)
var val = str.split(' ');
var op = shapesRef[val[0]];
if (val[1])
var pos = val[1].split(',');
ctx[op].apply(ctx, pos);
else
ctx[op]();
);
ctx.fill();
ctx.font = '15px sans-serif';
ctx.fillStyle = 'black';
ctx.fillText('normal radialGradient', 160, 20);
<canvas id="canvas" width="400" height="150"></canvas>
【讨论】:
抱歉格式化,我在用手机。这就是我目前正在研究的解决方案。然而,我在渐变中使用的形状非常复杂(想象一条线向下然后被向左或向右拖动,它代表气流条件)。如果我转换上下文,形状也会被转换,不是吗? 是的,你的形状也会被拉伸/收缩,所以你必须通过反转比例来绘制它,就像我对矩形所做的那样。显然,对于更复杂的形状,这将变得更加困难。 感谢您的出色回答,这对您有很大帮助。以上是关于CreateJS径向渐变与矩阵的主要内容,如果未能解决你的问题,请参考以下文章