Skip to content

Instantly share code, notes, and snippets.

@cajus
Created July 28, 2017 07:10
Show Gist options
  • Save cajus/9e99c497a0717afe5231a25091c4a857 to your computer and use it in GitHub Desktop.
Save cajus/9e99c497a0717afe5231a25091c4a857 to your computer and use it in GitHub Desktop.
Playground snippet for making radial gradient decorators
qx.Mixin.define("foo.MRadialBackgroundGradient",
{
/*
*****************************************************************************
PROPERTIES
*****************************************************************************
*/
properties :
{
/**
* Start color of the background gradient.
* Note that alpha transparency (rgba) is not supported in IE 8.
*/
radialStartColor :
{
check : "Color",
nullable : true,
apply : "_applyRadialBackgroundGradient"
},
/**
* End color of the background gradient.
* Note that alpha transparency (rgba) is not supported in IE 8.
*/
radialEndColor :
{
check : "Color",
nullable : true,
apply : "_applyRadialBackgroundGradient"
},
/** The orientation of the gradient. */
shape :
{
check : ["circle", "ellipse"],
init : "ellipse",
apply : "_applyRadialBackgroundGradient"
},
/** The orientation of the gradient. */
radialMode :
{
check : ["cover", "farthest-corner", "farthest-side", "closest-corner", "closest-side"],
init : "cover",
apply : "_applyRadialBackgroundGradient"
},
/** The orientation of the gradient. */
positionX :
{
check : "Integer",
init : null,
nullable : true,
apply : "_applyRadialBackgroundGradient"
},
/** The orientation of the gradient. */
positionY :
{
check : "Integer",
init : null,
nullable : true,
apply : "_applyRadialBackgroundGradient"
},
/** Property group to set the start color including its start position. */
position :
{
group : ["positionX", "positionY"],
mode : "shorthand"
},
/** Position in percent where to start the color. */
radialStartColorPosition :
{
check : "Number",
init : 0,
apply : "_applyRadialBackgroundGradient"
},
/** Position in percent where to start the color. */
radialEndColorPosition :
{
check : "Number",
init : 100,
apply : "_applyRadialBackgroundGradient"
},
/** Defines if the given positions are in % or px.*/
radialColorPositionUnit :
{
check : ["px", "%"],
init : "%",
apply : "_applyRadialBackgroundGradient"
}
},
/*
*****************************************************************************
MEMBERS
*****************************************************************************
*/
members :
{
__rcanvas : null,
/**
* Takes a styles map and adds the radial background styles in place to the
* given map. This is the needed behavior for
* {@link qx.ui.decoration.Decorator}.
*
* @param styles {Map} A map to add the styles.
*/
_styleRadialBackgroundGradient : function(styles)
{
var colors = this.__getRadialColors();
var radialStartColor = colors.start;
var radialEndColor = colors.end;
var value;
if (!radialStartColor || !radialEndColor) {
return;
}
var unit = this.getRadialColorPositionUnit();
var where = "";
// new implementation for webkit is available since chrome 10 --> version
if (qx.core.Environment.get("css.gradient.legacywebkit"))
{
// webkit uses px values if non are given
unit = unit === "px" ? "" : unit;
if (this.getPositionY()) {
where += this.getPositionY();
}
if (this.getPositionX()) {
where += where === "" ? this.getPositionX() : " " + this.getPositionX();
}
if (where === "") {
where = "center";
}
value = "-webkit-gradient(" + where + "," + this.getShape() + " " + this.getRadialMode() + "," + radialStartColor + " " + this.getRadialStartColorPosition() + unit + "," + radialEndColor + " " + this.getRadialEndColorPosition() + unit + ")";
styles.background = value;
// IE9 canvas solution
} else if (qx.core.Environment.get("css.gradient.filter") && !qx.core.Environment.get("css.gradient.radial") && qx.core.Environment.get("css.borderradius"))
{
if (!this.__rcanvas) {
this.__rcanvas = document.createElement("canvas");
}
var radius = 200;
var range = Math.max(100, this.getRadialEndColorPosition() - this.getRadialStartColorPosition());
//// use the px difference as dimension
if (unit === "px") {
radius = Math.max(radius, this.getRadialEndColorPosition() - this.getRadialStartColorPosition());
} else {
radius = Math.max(radius, (this.getRadialEndColorPosition() - this.getRadialStartColorPosition()) * 2);
}
this.__rcanvas.width = radius * 2;
this.__rcanvas.height = radius * 2;
var ctx = this.__rcanvas.getContext('2d');
var radgrad = ctx.createRadialGradient(radius, radius, 0, radius, radius, radius);
// don't allow negative start values
if (unit === "%")
{
radgrad.addColorStop(Math.max(0, this.getRadialStartColorPosition()) / range, colors.start);
radgrad.addColorStop(this.getRadialEndColorPosition() / range, colors.end);
} else
{
radgrad.addColorStop(Math.max(0, this.getRadialStartColorPosition()) / radius, colors.start);
radgrad.addColorStop(this.getRadialEndColorPosition() / radius, colors.end);
}
ctx.fillStyle = radgrad;
ctx.fillRect(0, 0, radius * 2, radius * 2);
styles["background-image"] = "url(" + this.__rcanvas.toDataURL() + ")";
if (unit === "%") {
styles["background-size"] = range + "% " + range + "%";
} else {
styles["background-size"] = radius + "px " + radius + "px";
}
} else if (!(qx.core.Environment.get("css.gradient.filter") && !qx.core.Environment.get("css.gradient.radial")))
{
// WebKit, Opera and Gecko interpret 0deg as "to right"
var prefixedName = qx.core.Environment.get("css.gradient.radial");
where = "";
if (this.getPositionY()) {
where += "at " + this.getPositionY();
}
if (this.getPositionX()) {
where += where === "" ? "at " + this.getPositionX() : " " + this.getPositionX();
}
value = prefixedName + "(" + this.getShape() + " " + this.getRadialMode() + where + "," + radialStartColor + " " + this.getRadialStartColorPosition() + unit + "," + radialEndColor + " " + this.getRadialEndColorPosition() + unit + ")";
if (styles["background-image"]) {
styles["background-image"] += ", " + value;
} else {
styles["background-image"] = value;
}
}
},
/**
* Helper to get start and end color.
* @return {Map} A map containing start and end color.
*/
__getRadialColors : function()
{
var radialStartColor, radialEndColor;
if (qx.core.Environment.get("qx.theme"))
{
var color = qx.theme.manager.Color.getInstance();
radialStartColor = color.resolve(this.getRadialStartColor());
radialEndColor = color.resolve(this.getRadialEndColor());
} else
{
radialStartColor = this.getRadialStartColor();
radialEndColor = this.getRadialEndColor();
}
return {
start : radialStartColor,
end : radialEndColor
};
},
// property apply
_applyRadialBackgroundGradient : function() {
if (qx.core.Environment.get("qx.debug")) {
if (this._isInitialized()) {
throw new Error("This decorator is already in-use. Modification is not possible anymore!");
}
}
}
}
});
// Needed to make it run multiple times in the playground
try {
qx.Class.patch(qx.ui.decoration.Decorator, foo.MRadialBackgroundGradient);
}catch(e){};
var radial = new qx.ui.decoration.Decorator().set({
width: 0,
shadowLength: [0, 2],
shadowBlurRadius: 4,
shadowSpreadRadius: 2,
shadowColor: "rgba(0,0,0,0.5)",
radialStartColor: "#FFFF00",
radialEndColor: "#00FF00",
shape: "ellipse",
radius: 6
}
);
// Create a button
var button1 = new qx.ui.form.Button("First Button", "icon/22/apps/internet-web-browser.png");
button1.setDecorator(radial);
button1.setPadding(18);
// Document is the application root
var doc = this.getRoot();
// Add button to document at fixed coordinates
doc.add(button1,
{
left : 100,
top : 50
});
// Add an event listener
button1.addListener("execute", function(e) {
alert("Hello World!");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment