[英]How can I generate a rainbow circle using HTML5 canvas?
I would like to generate a canvas image using gradients in some clever way. 我想以一些聪明的方式使用渐变生成画布图像。 I would like the image to looks something like this: 我希望图像看起来像这样:
I just can't get my head around it. 我只是无法理解它。 I need to generate lines in the form and arc - or use gradients with color stops in some clever way. 我需要在窗体和圆弧中生成线条 - 或者以一些聪明的方式使用带有颜色停止的渐变。 Maybe it would be a lot easier if I converted to HSL and just go through the HUE values? 如果我转换为HSL并且只是通过HUE值,那可能会容易得多吗?
For example in a rectangle format I could 例如,我可以使用矩形格式
for (var i = 0; i < h; ++i) {
var ratio = i/h;
var hue = Math.floor(360*ratio);
var sat = 100;
var lum = 50;
line(dc, hslColor(hue,sat,lum), left_margin, top_margin+i, left_margin+w, top_margin+i);
}
Does anybody have any clever tips on how to produce this image using canvas? 有没有人有关于如何使用画布生成此图像的聪明提示?
This is not perfect (due to drawing steps ...), but it can help you : 这不完美(由于绘图步骤......),但它可以帮助您:
http://jsfiddle.net/afkLY/2/ http://jsfiddle.net/afkLY/2/
HTML: HTML:
<canvas id="colors" width="200" height="200"></canvas>
Javascript: 使用Javascript:
var canvas = document.getElementById("colors");
var graphics = canvas.getContext("2d");
var CX = canvas.width / 2,
CY = canvas.height/ 2,
sx = CX,
sy = CY;
for(var i = 0; i < 360; i+=0.1){
var rad = i * (2*Math.PI) / 360;
graphics.strokeStyle = "hsla("+i+", 100%, 50%, 1.0)";
graphics.beginPath();
graphics.moveTo(CX, CY);
graphics.lineTo(CX + sx * Math.cos(rad), CY + sy * Math.sin(rad));
graphics.stroke();
}
The idea is to draw the disc line by line with a hue value corresponding to the line direction. 该想法是逐行绘制具有对应于线方向的色调值的盘。
You can change the color base rotation by adding a radius angle to rad variable (adding -pi/2 to rad would make the gradient look like your figure). 您可以通过向rad变量添加半径角来更改颜色基础旋转(将-pi / 2添加到rad会使渐变看起来像您的图形)。
Here is an alternate approach that takes a slightly more functional approach: 这是一种采用稍微更具功能性的方法的替代方法:
var canvas = document.getElementById("radial"),
ctx = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height,
center = { x: width/2, y: height/2 },
diameter = Math.min(width, height);
var distanceBetween = function(x1,y1,x2,y2) {
// Get deltas
var deltaX = x2 - x1,
deltaY = y2 - y1;
// Calculate distance from center
return Math.sqrt(deltaX*deltaX+deltaY*deltaY);
}
var angleBetween = function(x1,y1,x2,y2) {
// Get deltas
var deltaX = x2 - x1,
deltaY = y2 - y1;
// Calculate angle
return Math.atan2(deltaY, deltaX);
}
var radiansToDegrees = _.memoize(function(radians) {
// Put in range of [0,2PI)
if (radians < 0) radians += Math.PI * 2;
// convert to degrees
return radians * 180 / Math.PI;
})
// Partial application of center (x,y)
var distanceFromCenter = _.bind(distanceBetween, undefined, center.x, center.y)
var angleFromCenter = _.bind(angleBetween, undefined, center.x, center.y)
// Color formatters
var hslFormatter = function(h,s,l) { return "hsl("+h+","+s+"%,"+l+"%)"; },
fromHue = function(h) { return hslFormatter(h,100,50); };
// (x,y) => color
var getColor = function(x,y) {
// If distance is greater than radius, return black
return (distanceFromCenter(x,y) > diameter/2)
// Return black
? "#000"
// Determine color
: fromHue(radiansToDegrees(angleFromCenter(x,y)));
};
for(var y=0;y<height;y++) {
for(var x=0;x<width;x++) {
ctx.fillStyle = getColor(x,y);
ctx.fillRect( x, y, 1, 1 );
}
}
It uses a function to calculate the color at each pixel – not the most efficient implementation, but perhaps you'll glean something useful from it. 它使用一个函数来计算每个像素的颜色 - 不是最有效的实现,但也许你会收集一些有用的东西。
Note it uses underscore for some helper functions like bind()
– for partial applications – and memoize
. 注意它对一些辅助函数使用下划线 ,比如bind()
- 对于部分应用程序 - 和memoize
。
Small adjustment to make it have a white center 小调整使其具有白色中心
var canvas = document.getElementById('colorPicker'); var canvas = document.getElementById('colorPicker'); var graphics = canvas.getContext("2d"); var graphics = canvas.getContext(“2d”);
var CX = canvas.width / 2,
CY = canvas.height / 2,
sx = CX,
sy = CY;
for (var i = 0; i < 360; i += 0.1) {
var rad = i * (2 * Math.PI) / 360;
var grad = graphics.createLinearGradient(CX, CY, CX + sx * Math.cos(rad), CY + sy * Math.sin(rad));
grad.addColorStop(0, "white");
grad.addColorStop(0.01, "white");
grad.addColorStop(0.99, "hsla(" + i + ", 100%, 50%, 1.0)");
grad.addColorStop(1, "hsla(" + i + ", 100%, 50%, 1.0)");
graphics.strokeStyle = grad;
graphics.beginPath();
graphics.moveTo(CX, CY);
graphics.lineTo(CX + sx * Math.cos(rad), CY + sy * Math.sin(rad));
graphics.stroke();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.