2013-11-15 90 views
3

我想用一些聪明的方式使用渐变生成画布图像。我想图像看起来是这样的:如何使用HTML5画布生成彩虹圈?

rainbow circle

我不能让我的头周围。我需要在窗体和弧中生成线条 - 或者以一些聪明的方式使用带有色彩渐变的渐变。如果我转换成HSL并且通过HUE值,可能会容易得多?

例如,在一个长方形格式我可以

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); 
} 

是否有人对如何使用生产帆布这个图像的任何巧妙的技巧?

回答

11

这是不完美的(由于绘图步骤...),但它可以帮助你:

http://jsfiddle.net/afkLY/2/

HTML:

<canvas id="colors" width="200" height="200"></canvas> 

的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(); 
} 

这个想法是用对应于line direc的色调值逐行绘制圆盘灰。

可以通过添加一个半径角度拉德变量(添加-pi/2到拉德会使梯度看起来像您的图)改变颜色基座转动。

+1

这是完美的... – MarsOne

+0

那么,在这种情况下呢。但该步骤必须是光盘尺寸的功能,否则绘图不完整。让我们尝试2000x2000的画布大小而不更改代码:http://jsfiddle.net/afkLY/4/ 这是一个极端的例子,但无论如何都是一个例子。 – dooxe

+0

这看起来非常棒!谢谢,你能详细阐述你对绘图步骤的含义吗?你是什​​么意思,这一步必须是光盘大小的函数? – Yonder

0

这里是另一种方法是采用一种略微更注重功能的做法:

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); 
    } 
} 

它采用了功能在每个像素–不是最有效的实现来计算颜色,但也许你会搜集一些有用的东西从中。

注意它使用underscorebind() –一些辅助功能部分应用–和memoize

Codepen进行实验。

0

小调整,使之有一个白色的中心

变种画布=的document.getElementById( '颜色拾取'); 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(); 
     }