我正在使用Pixi.js v4 graphics library与JavaScript制作游戏。我知道我可以像这样绘制一个黑色+圆角矩形:
const rectangle = new pixi.Graphics();
rectangle.beginFill(0); // Color it black
rectangle.drawRoundedRect(
0,
0,
100, // Make it 100x100
100,
5, // Make the rounded corners have a radius of 5
);
rectangle.endFill();
stage.addChild(rectangle);
1)如何绘制一个带有从白色到黑色渐变的圆角矩形?
2)如何绘制渐变不透明的圆角矩形,使其从左向右淡入?
答案 0 :(得分:4)
不是完整答案,而是一些额外信息
1)据我所知,你不能为PIXI.Graphics使用渐变,即使对于你需要额外画布的精灵也是如此
只需将您想要的渐变绘制到画布上: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createLinearGradient
然后将该画布用作纹理:Texture.fromCanvas(canvas);
看:http://www.html5gamedevs.com/topic/25691-gradients-in-pixi4/
2)对于渐进的不透明度 Alpha Mask 可以提供帮助
http://pixijs.io/examples/#/demos/alpha-mask.js
P.S也许phaser.js可以做得更多
答案 1 :(得分:3)
看起来似乎不可能在没有附加代码的情况下用pixi.js实现你需要的东西,但我们可以做一些魔术来实现它。这是我得到的结果:https://jsfiddle.net/exkf3zfo/21/
底色为纯红色,0.2 alpha。
我会将整个过程分成以下几个步骤:
以下是代码本身:
var app = new PIXI.Application(800, 600, {
antialias: true
});
document.body.appendChild(app.view);
// Functions
// param color is a number (e.g. 255)
// return value is a string (e.g. ff)
var prepareRGBChannelColor = function(channelColor) {
var colorText = channelColor.toString(16);
if (colorText.length < 2) {
while (colorText.length < 2) {
colorText = "0" + colorText;
}
}
return colorText;
}
// Getting RGB channels from a number color
// param color is a number
// return an RGB channels object {red: number, green: number, blue: number}
var getRGBChannels = function(color) {
var colorText = color.toString(16);
if (colorText.length < 6) {
while (colorText.length < 6) {
colorText = "0" + colorText;
}
}
var result = {
red: parseInt(colorText.slice(0, 2), 16),
green: parseInt(colorText.slice(2, 4), 16),
blue: parseInt(colorText.slice(4, 6), 16)
};
return result;
}
// Preparaiton of a color data object
// param color is a number [0-255]
// param alpha is a number [0-1]
// return the color data object {color: number, alpha: number, channels: {red: number, green: number, blue: number}}
var prepareColorData = function(color, alpha) {
return {
color: color,
alpha: alpha,
channels: getRGBChannels(color)
}
}
// Getting the color of a gradient for a very specific gradient coef
// param from is a color data object
// param to is a color data object
// return value is of the same type
var getColorOfGradient = function(from, to, coef) {
if (!from.alpha && from.alpha !== 0) {
from.alpha = 1;
}
if (!from.alpha && from.alpha !== 0) {
to.alpha = 1;
}
var colorRed = Math.floor(from.channels.red + coef * (to.channels.red - from.channels.red));
colorRed = Math.min(colorRed, 255);
var colorGreen = Math.floor(from.channels.green + coef * (to.channels.green - from.channels.green));
colorGreen = Math.min(colorGreen, 255);
var colorBlue = Math.floor(from.channels.blue + coef * (to.channels.blue - from.channels.blue));
colorBlue = Math.min(colorBlue, 255);
var rgb = prepareRGBChannelColor(colorRed) + prepareRGBChannelColor(colorGreen) + prepareRGBChannelColor(colorBlue);
return {
color: parseInt(rgb, 16),
alpha: from.alpha + coef * (to.alpha - from.alpha)
};
}
var startTime = Date.now();
console.log("start: " + startTime);
// Drawing the gradient
//
var gradient = new PIXI.Graphics();
app.stage.addChild(gradient);
//
var rect = {
width: 200,
height: 200
};
var round = 20;
//
var colorFromData = prepareColorData(0xFF00FF, 1);
var colorToData = prepareColorData(0xFF0000, 0.2);
//
var stepCoef;
var stepColor;
var stepAlpha;
var stepsCount = 100;
var stepHeight = rect.height / stepsCount;
for (var stepIndex = 0; stepIndex < stepsCount; stepIndex++) {
stepCoef = stepIndex / stepsCount;
stepColor = getColorOfGradient(colorFromData, colorToData, stepCoef);
gradient.beginFill(stepColor.color, stepColor.alpha);
gradient.drawRect(
0,
rect.height * stepCoef,
rect.width,
stepHeight
);
}
// Applying a mask with round corners to the gradient
var roundMask = new PIXI.Graphics();
roundMask.beginFill(0x000000);
roundMask.drawRoundedRect(0, 0, rect.width, rect.height, round);
app.stage.addChild(roundMask);
gradient.mask = roundMask;
var endTime = Date.now();
console.log("end: " + endTime);
console.log("total: " + (endTime - startTime));
有趣的是整个过程只需要2-5毫秒!
如果您不想将渐变的颜色更改为白色&gt;黑色(如问题中所述),只需更改下一个参数:
var colorFromData = prepareColorData(0xFF00FF, 1);
var colorToData = prepareColorData(0xFF0000, 0.2);
要:
var colorFromData = prepareColorData(0xFFFFFF, 1);
var colorToData = prepareColorData(0x000000, 0.2);
答案 2 :(得分:2)
你有没有想过这个?我也无法在线找到解决方案,所以我自己使用过滤器实现了它。看看:https://codepen.io/Lancer611/pen/KodabK。
一些pixi代码:
function newGradientPoly(poly, fill, fillSize){
var container = new PIXI.Sprite();
app.stage.addChild(container);
var shape = new PIXI.Graphics();
shape.beginFill(0xffffff)
.lineStyle(1, 0x333333)
.drawPolygon(poly);
var mask = new PIXI.Graphics();
mask.beginFill(0xffffff, 1)
.drawPolygon(poly);
container.mask = mask;
container.addChild(shape);
var fshaderCode = document.getElementById("fragShader").innerHTML;
fogShader = new PIXI.Filter(null, fshaderCode);
fogShader.uniforms.resolution = [width, height];
fogShader.uniforms.segments = poly.slice();
fogShader.uniforms.count = poly.length/2;
fogShader.uniforms.gSize = fillSize;
fogShader.uniforms.fill = fill;
shape.filters=[fogShader];
}
答案 3 :(得分:0)
我创建了一个pixi plugin用于在Pixi中显示矢量绘图。主要的限制是你需要首先在矢量艺术程序Omber中绘制矩形,所以你需要事先知道矩形的大小(因为一切都是基于矢量的,理论上你可以稍后缩放,但是然后圆角会变得有点不均匀)。工作流程类似于使用精灵:1。在Omber中绘制矩形2.将它们导出到gltf 3.在你的Pixi程序中加载gltf文件4.将矩形放在你想要的位置。
另一种可能性是您可以将渐变创建为单独的对象,然后可以使用多边形将其遮罩。这是一个example。在这个例子中,我使用了渐变的矢量绘图,但由于渐变时渐变不会变得模糊,所以你也可以使用精灵。我不确定面具是否具有良好的性能,但如果你只是需要它们中的一些,那么它可能很好。