gradient.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /**
  2. * Module dependencies.
  3. */
  4. var stylus = require('stylus'),
  5. Canvas = require('canvas'),
  6. nodes = stylus.nodes,
  7. utils = stylus.utils;
  8. /**
  9. * Expose `Gradient`.
  10. */
  11. exports = module.exports = Gradient;
  12. /**
  13. * Create a new `Gradient` node with the given `size`
  14. * and `start` position.
  15. *
  16. * @param {Number} size
  17. * @param {String|Ident|Literal} start
  18. * @return {Gradient}
  19. * @api public
  20. */
  21. exports.create = function(size, start){
  22. utils.assertType(size, 'unit', 'size');
  23. utils.assertString(start, 'start');
  24. return new Gradient(size.val, start.string);
  25. };
  26. /**
  27. * Add color stop to `grad`.
  28. *
  29. * @param {Gradient} grad
  30. * @param {Unit} pos
  31. * @param {HSLA|RGBA} color
  32. * @return {Null}
  33. * @api public
  34. */
  35. exports.addColorStop = function(grad, pos, color){
  36. utils.assertType(grad, 'gradient', 'grad');
  37. utils.assertType(pos, 'unit', 'pos');
  38. utils.assertColor(color, 'color');
  39. grad.addColorStop(pos.val / 100, color.rgba.toString());
  40. return nodes.null;
  41. };
  42. /**
  43. * Return the data URI for `grad`.
  44. *
  45. * @param {Gradient} grad
  46. * @return {String}
  47. * @api public
  48. */
  49. exports.dataURL = function(grad){
  50. utils.assertType(grad, 'gradient');
  51. return new nodes.String(grad.toDataURL());
  52. };
  53. /**
  54. * Initialize a new `Gradient` node with the given `size`
  55. * and `start` position.
  56. *
  57. * @param {Number} size
  58. * @param {String} start
  59. * @api private
  60. */
  61. function Gradient(size, start) {
  62. this.size = size;
  63. this.canvas = new Canvas(1, 1);
  64. this.setStartPosition(start);
  65. this.ctx = this.canvas.getContext('2d');
  66. this.grad = this.ctx.createLinearGradient(
  67. this.from[0], this.from[1],
  68. this.to[0], this.to[1]);
  69. }
  70. /**
  71. * Inspect the gradient.
  72. *
  73. * @return {String}
  74. * @api private
  75. */
  76. Gradient.prototype.toString = function(){
  77. return 'Gradient(' + this.size + 'px ' + this.stops.map(function(stop){
  78. return stop[0] + ' ' + stop[1];
  79. }).join(', ') + ')';
  80. };
  81. /**
  82. * Set `start` position.
  83. *
  84. * @param {String} start
  85. * @api private
  86. */
  87. Gradient.prototype.setStartPosition = function(start){
  88. var size = this.size,
  89. canvas = this.canvas;
  90. switch (start) {
  91. case 'top':
  92. canvas.height = size;
  93. this.from = [canvas.width / 2, 0];
  94. this.to = [canvas.width / 2, canvas.height];
  95. break;
  96. case 'bottom':
  97. canvas.height = size;
  98. this.from = [canvas.width / 2, canvas.height];
  99. this.to = [canvas.width / 2, 0];
  100. break;
  101. case 'left':
  102. canvas.width = size;
  103. this.from = [0, 0];
  104. this.to = [canvas.width, canvas.height];
  105. break;
  106. case 'right':
  107. canvas.width = size;
  108. this.from = [canvas.width, canvas.height];
  109. this.to = [0, 0];
  110. break;
  111. default:
  112. throw new Error('invalid start position "' + start + '"');
  113. }
  114. };
  115. /**
  116. * Add color stop `pos` / `color`.
  117. *
  118. * @param {Number} pos
  119. * @param {String} color
  120. * @api private
  121. */
  122. Gradient.prototype.addColorStop = function(pos, color){
  123. this.grad.addColorStop(pos, color);
  124. };
  125. /**
  126. * Return data URI string.
  127. *
  128. * @return {String}
  129. * @api private
  130. */
  131. Gradient.prototype.toDataURL = function(){
  132. var canvas = this.canvas,
  133. ctx = this.ctx;
  134. ctx.fillStyle = this.grad;
  135. ctx.fillRect(0, 0, canvas.width, canvas.height);
  136. return canvas.toDataURL();
  137. };
  138. /**
  139. * Inherit from `nodes.Node.prototype`.
  140. */
  141. Gradient.prototype.__proto__ = nodes.Node.prototype;