gradient.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /* eslint-disable */
  2. export const GD = {
  3. isGradient(bg) {
  4. if (bg && (bg.startsWith('linear') || bg.startsWith('radial'))) {
  5. return true;
  6. }
  7. return false;
  8. },
  9. doGradient(bg, width, height, ctx) {
  10. if (bg.startsWith('linear')) {
  11. linearEffect(width, height, bg, ctx);
  12. } else if (bg.startsWith('radial')) {
  13. radialEffect(width, height, bg, ctx);
  14. }
  15. },
  16. }
  17. function analizeGrad(string) {
  18. const colorPercents = string.substring(0, string.length - 1).split("%,");
  19. const colors = [];
  20. const percents = [];
  21. for (let colorPercent of colorPercents) {
  22. colors.push(colorPercent.substring(0, colorPercent.lastIndexOf(" ")).trim());
  23. percents.push(colorPercent.substring(colorPercent.lastIndexOf(" "), colorPercent.length) / 100);
  24. }
  25. return {
  26. colors: colors,
  27. percents: percents
  28. };
  29. }
  30. function radialEffect(width, height, bg, ctx) {
  31. const colorPer = analizeGrad(bg.match(/radial-gradient\((.+)\)/)[1]);
  32. const grd = ctx.createCircularGradient(0, 0, width < height ? height / 2 : width / 2);
  33. for (let i = 0; i < colorPer.colors.length; i++) {
  34. grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
  35. }
  36. ctx.setFillStyle(grd);
  37. }
  38. function analizeLinear(bg, width, height) {
  39. const direction = bg.match(/([-]?\d{1,3})deg/);
  40. const dir = direction && direction[1] ? parseFloat(direction[1]) : 0;
  41. let coordinate;
  42. switch (dir) {
  43. case 0:
  44. coordinate = [0, -height / 2, 0, height / 2];
  45. break;
  46. case 90:
  47. coordinate = [width / 2, 0, -width / 2, 0];
  48. break;
  49. case -90:
  50. coordinate = [-width / 2, 0, width / 2, 0];
  51. break;
  52. case 180:
  53. coordinate = [0, height / 2, 0, -height / 2];
  54. break;
  55. case -180:
  56. coordinate = [0, -height / 2, 0, height / 2];
  57. break;
  58. default:
  59. let x1 = 0;
  60. let y1 = 0;
  61. let x2 = 0;
  62. let y2 = 0;
  63. if (direction[1] > 0 && direction[1] < 90) {
  64. x1 = (width / 2) - ((width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
  65. 90 - direction[1]) * Math.PI * 2 / 360) / 2;
  66. y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
  67. x2 = -x1;
  68. y1 = -y2;
  69. } else if (direction[1] > -180 && direction[1] < -90) {
  70. x1 = -(width / 2) + ((width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
  71. 90 - direction[1]) * Math.PI * 2 / 360) / 2;
  72. y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
  73. x2 = -x1;
  74. y1 = -y2;
  75. } else if (direction[1] > 90 && direction[1] < 180) {
  76. x1 = (width / 2) + (-(width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 * (
  77. 90 - direction[1]) * Math.PI * 2 / 360) / 2;
  78. y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
  79. x2 = -x1;
  80. y1 = -y2;
  81. } else {
  82. x1 = -(width / 2) - (-(width / 2) * Math.tan((90 - direction[1]) * Math.PI * 2 / 360) - height / 2) * Math.sin(2 *
  83. (90 - direction[1]) * Math.PI * 2 / 360) / 2;
  84. y2 = Math.tan((90 - direction[1]) * Math.PI * 2 / 360) * x1;
  85. x2 = -x1;
  86. y1 = -y2;
  87. }
  88. coordinate = [x1, y1, x2, y2];
  89. break;
  90. }
  91. return coordinate;
  92. }
  93. function linearEffect(width, height, bg, ctx) {
  94. const param = analizeLinear(bg, width, height);
  95. const grd = ctx.createLinearGradient(param[0], param[1], param[2], param[3]);
  96. const content = bg.match(/linear-gradient\((.+)\)/)[1];
  97. const colorPer = analizeGrad(content.substring(content.indexOf(',') + 1));
  98. for (let i = 0; i < colorPer.colors.length; i++) {
  99. grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
  100. }
  101. ctx.setFillStyle(grd);
  102. }