我在查找允許有this effect on a canvas' stroke的代碼。 我已經有一個動畫圓形筆畫,我只需要得到ANGLE漸變,不是線性的而不是徑向的。我只有3種顏色。 現有一個is available here(審查等級)畫布中的角度漸變
謝謝大家:)
我在查找允許有this effect on a canvas' stroke的代碼。 我已經有一個動畫圓形筆畫,我只需要得到ANGLE漸變,不是線性的而不是徑向的。我只有3種顏色。 現有一個is available here(審查等級)畫布中的角度漸變
謝謝大家:)
上下文的StrokeStyle可以是梯度:
// create a gradient
gradient = ctx.createLinearGradient(xStart, yStart, xEnd, yEnd);
gradient.addColorStop(0.0,"blue");
gradient.addColorStop(1.0,"purple");
// stroke using that gradient
ctx.strokeStyle = gradient;
實施例的代碼和使用梯度的StrokeStyle一個演示:http://jsfiddle.net/m1erickson/w46ps/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
function drawMultiRadiantCircle(xc, yc, r, radientColors) {
var partLength = (2 * Math.PI)/radientColors.length;
var start = 0;
var gradient = null;
var startColor = null,
endColor = null;
for (var i = 0; i < radientColors.length; i++) {
startColor = radientColors[i];
endColor = radientColors[(i + 1) % radientColors.length];
// x start/end of the next arc to draw
var xStart = xc + Math.cos(start) * r;
var xEnd = xc + Math.cos(start + partLength) * r;
// y start/end of the next arc to draw
var yStart = yc + Math.sin(start) * r;
var yEnd = yc + Math.sin(start + partLength) * r;
ctx.beginPath();
gradient = ctx.createLinearGradient(xStart, yStart, xEnd, yEnd);
gradient.addColorStop(0, startColor);
gradient.addColorStop(1.0, endColor);
ctx.strokeStyle = gradient;
ctx.arc(xc, yc, r, start, start + partLength);
ctx.lineWidth = 30;
ctx.stroke();
ctx.closePath();
start += partLength;
}
}
var someColors = [];
someColors.push('#0F0');
someColors.push('#0FF');
someColors.push('#F00');
someColors.push('#FF0');
someColors.push('#F0F');
drawMultiRadiantCircle(150, 150, 120, someColors);
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
幾天前我也需要這種效果,並且我設法創建了一個變通辦法來實現它。
我所做的是一個覆蓋梯度比其他使用是這樣的:
var ic = [
/*0*/{ a:"#FEC331" ,b:"#FB1E24" ,r1:0 ,r2:1 ,x0:0 ,y0:rd*0.5 ,x1:0 ,y1:-rd},
/*1*/{ a:"#FEC331" ,b:"#FB1E24" ,r1:0.5 ,r2:0.5 ,x0:0 ,y0:rd*0.3 ,x1:0 ,y1:-rd},
/*2*/{ a:"#EA6F2B" ,b:"transparent" ,r1:0 ,r2:1 ,x0:-rd ,y0:0 ,x1:rd ,y1:0 }
];
下面是的jsfiddle完整的代碼和演示:
https://jsfiddle.net/flamedenise/n9no9Lgw/33/
希望它能幫助。
在我的情況下,我需要填充整個圓圈而不是圍繞圓周的中風。使用上面的答案並將線寬設置爲半徑的兩倍給出了不希望的結果,所以我寫了自己的。
/**
* @description Options used when calling CanvasRenderingContext2D.strokeArcGradient() and
* CanvasRenderingContext2D.fillArcGradient().
* @property {Boolean} useDegrees Whether the specified angles should be interpreted as degrees rather than radians.
* (default: false)
* @property {Number} resolutionFactor The number of lines to render per pixel along the arc. A higher number produces
* a cleaner gradient, but has worse performance for large radii. Must be greater
* than 0. (default: 8)
*/
class ArcGradientOptions {
constructor(options) {
function validateParam(test, errorMessage, fatal = false) {
if (!test) {
if (fatal) {
throw new Error(errorMessage);
} else {
console.assert(false, errorMessage);
}
}
}
options = Object.assign({
useDegrees: false,
resolutionFactor: 8,
}, options);
validateParam(
(options.resolutionFactor instanceof Number | typeof options.resolutionFactor === 'number') &&
options.resolutionFactor > 0,
`ArcGradientOptions.resolutionFactor must be a Number greater than 0. Given: ${options.resolutionFactor}`,
true);
Object.assign(this, options);
}
};
(function() {
/**
* @description Strokes an arc using a linear gradient.
* @param {number} x The x-component of origin of the arc.
* @param {number} y The y-component of the origin of the arc.
* @param {number} radius The radius of the arc.
* @param {number} startAngle Where in the circle to begin the stroke.
* @param {number} endAngle Where in the circle to end the stroke.
* @param {ArcGradientOptions} options Additional options.
*/
CanvasRenderingContext2D.prototype.strokeArcGradient = function (x, y, radius, startAngle, endAngle, colorStops,
options) {
options = new ArcGradientOptions(options);
let lineWidth = this.lineWidth;
this.fillArcGradient(x, y, startAngle, endAngle, colorStops, radius + lineWidth/2, radius - lineWidth/2,
options);
}
/**
* @description Fills a sector or a portion of a ring with a linear gradient.
* @param {number} x The x-component of origin of the arc
* @param {number} y The y-component of the origin of the arc
* @param {number} startAngle Where in the circle to begin the fill.
* @param {number} endAngle Where in the circle to end the fill.
* @param {number} outerRadius The radius of the arc.
* @param {number} innerRadius The radius of the arc that won't be filled. An innerRadius = 0 will fill the whole
* arc. (default: 0)
* @param {ArcGradientOptions} options Additional options.
*/
CanvasRenderingContext2D.prototype.fillArcGradient = function (x, y, startAngle, endAngle, colorStops, outerRadius,
innerRadius = 0, options) {
options = new ArcGradientOptions(options);
let oldLineWidth = this.lineWidth,
oldStrokeStyle = this.strokeStyle;
if (options.useDegrees) {
startAngle = startAngle * Math.PI/180;
endAngle = endAngle * Math.PI/180;
}
let deltaArcAngle = endAngle - startAngle;
gradientWidth = Math.floor(outerRadius * Math.abs(deltaArcAngle) * options.resolutionFactor),
gData = generateGradientImgData(gradientWidth, colorStops).data;
this.lineWidth = Math.min(4/options.resolutionFactor, 1);
for (let i = 0; i < gradientWidth; i++) {
let gradi = i * 4,
theta = startAngle + deltaArcAngle * i/gradientWidth;
this.strokeStyle = `rgba(${gData[gradi]}, ${gData[gradi + 1]}, ${gData[gradi + 2]}, ${gData[gradi + 3]})`;
this.beginPath();
this.moveTo(x + Math.cos(theta) * innerRadius, y + Math.sin(theta) * innerRadius);
this.lineTo(x + Math.cos(theta) * outerRadius, y + Math.sin(theta) * outerRadius);
this.stroke();
this.closePath();
}
this.lineWidth = oldLineWidth;
this.strokeStyle = oldStrokeStyle;
}
function generateGradientImgData(width, colorStops) {
let canvas = document.createElement('canvas');
canvas.setAttribute('width', width);
canvas.setAttribute('height', 1);
let ctx = canvas.getContext('2d'),
gradient = ctx.createLinearGradient(0, 0, width, 0);
for (let i = 0; i < colorStops.length; i++) {
gradient.addColorStop(colorStops[i].offset, colorStops[i].color);
}
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, 1);
return ctx.getImageData(0, 0, width, 1);
}
})();
此方法從圓的中心繪製線條,沿着它的邊緣繪製每個像素。這樣就可以得到更清晰的漸變效果。
對於大型線的厚度,它仍然是清潔的。
它的一個主要缺點是性能。如果你的半徑非常大,產生一個很好的圓所需的線數約爲半徑的50倍。
這就是所謂的錐形漸變。 – Kroltan
也許你是對的,但在Photoshop中它被稱爲「角度」:) – AndrePliz