style-parse.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import { each } from '../../util/common';
  2. function _mod(n, m) {
  3. return (n % m + m) % m;
  4. }
  5. function _addStop(steps, gradient) {
  6. each(steps, function (item) {
  7. item = item.split(':');
  8. gradient.addColorStop(Number(item[0]), item[1]);
  9. });
  10. } // the string format: 'l(0) 0:#ffffff 0.5:#7ec2f3 1:#1890ff'
  11. function _parseLineGradient(color, shape, context) {
  12. var arr = color.split(' ');
  13. var angle = arr[0].slice(2, arr[0].length - 1);
  14. angle = _mod(parseFloat(angle) * Math.PI / 180, Math.PI * 2);
  15. var steps = arr.slice(1);
  16. var {
  17. minX,
  18. minY,
  19. maxX,
  20. maxY
  21. } = shape.getBBox();
  22. var start;
  23. var end;
  24. if (angle >= 0 && angle < 0.5 * Math.PI) {
  25. start = {
  26. x: minX,
  27. y: minY
  28. };
  29. end = {
  30. x: maxX,
  31. y: maxY
  32. };
  33. } else if (0.5 * Math.PI <= angle && angle < Math.PI) {
  34. start = {
  35. x: maxX,
  36. y: minY
  37. };
  38. end = {
  39. x: minX,
  40. y: maxY
  41. };
  42. } else if (Math.PI <= angle && angle < 1.5 * Math.PI) {
  43. start = {
  44. x: maxX,
  45. y: maxY
  46. };
  47. end = {
  48. x: minX,
  49. y: minY
  50. };
  51. } else {
  52. start = {
  53. x: minX,
  54. y: maxY
  55. };
  56. end = {
  57. x: maxX,
  58. y: minY
  59. };
  60. }
  61. var tanTheta = Math.tan(angle);
  62. var tanTheta2 = tanTheta * tanTheta;
  63. var x = (end.x - start.x + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.x;
  64. var y = tanTheta * (end.x - start.x + tanTheta * (end.y - start.y)) / (tanTheta2 + 1) + start.y;
  65. var gradient = context.createLinearGradient(start.x, start.y, x, y);
  66. _addStop(steps, gradient);
  67. return gradient;
  68. } // the string format: 'r(0.5, 0.5, 0.1) 0:#ffffff 1:#1890ff'
  69. function _parseRadialGradient(color, shape, context) {
  70. var arr = color.split(' ');
  71. var circleCfg = arr[0].slice(2, arr[0].length - 1);
  72. circleCfg = circleCfg.split(',');
  73. var fx = parseFloat(circleCfg[0]);
  74. var fy = parseFloat(circleCfg[1]);
  75. var fr = parseFloat(circleCfg[2]);
  76. var steps = arr.slice(1); // if radius is 0, no gradient, stroke with the last color
  77. if (fr === 0) {
  78. var _color = steps[steps.length - 1];
  79. return _color.split(':')[1];
  80. }
  81. var {
  82. width,
  83. height,
  84. minX,
  85. minY
  86. } = shape.getBBox();
  87. var r = Math.sqrt(width * width + height * height) / 2;
  88. var gradient = context.createRadialGradient(minX + width * fx, minY + height * fy, fr * r, minX + width / 2, minY + height / 2, r);
  89. _addStop(steps, gradient);
  90. return gradient;
  91. }
  92. function parseStyle(color, shape, context) {
  93. if (color[1] === '(') {
  94. try {
  95. var firstCode = color[0];
  96. if (firstCode === 'l') {
  97. return _parseLineGradient(color, shape, context);
  98. } else if (firstCode === 'r') {
  99. return _parseRadialGradient(color, shape, context);
  100. }
  101. } catch (ev) {
  102. console.error('error in parsing gradient string, please check if there are any extra whitespaces.');
  103. console.error(ev);
  104. }
  105. }
  106. return color;
  107. }
  108. export { parseStyle };
  109. export default {
  110. parseStyle
  111. };