gradient.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /* eslint-disable */
  2. // 当ctx传入当前文件,const grd = ctx.createCircularGradient() 和
  3. // const grd = this.ctx.createLinearGradient() 无效,因此只能分开处理
  4. // 先分析,在外部创建grd,再传入使用就可以
  5. !(function () {
  6. var api = {
  7. isGradient: function (bg) {
  8. if (bg && (bg.startsWith('linear') || bg.startsWith('radial'))) {
  9. return true;
  10. }
  11. return false;
  12. },
  13. doGradient: function (bg, width, height, ctx) {
  14. if (bg.startsWith('linear')) {
  15. linearEffect(width, height, bg, ctx);
  16. } else if (bg.startsWith('radial')) {
  17. radialEffect(width, height, bg, ctx);
  18. }
  19. }
  20. };
  21. function analizeGrad(string) {
  22. const colorPercents = string.substring(0, string.length - 1).split('%,');
  23. const colors = [];
  24. const percents = [];
  25. for (let colorPercent of colorPercents) {
  26. colors.push(colorPercent.substring(0, colorPercent.lastIndexOf(' ')).trim());
  27. percents.push(colorPercent.substring(colorPercent.lastIndexOf(' '), colorPercent.length) / 100);
  28. }
  29. return {
  30. colors: colors,
  31. percents: percents
  32. };
  33. }
  34. function radialEffect(width, height, bg, ctx) {
  35. const colorPer = analizeGrad(bg.match(/radial-gradient\((.+)\)/)[1]);
  36. const grd = ctx.createCircularGradient(0, 0, width < height ? height / 2 : width / 2);
  37. for (let i = 0; i < colorPer.colors.length; i++) {
  38. grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
  39. }
  40. ctx.fillStyle = grd; //ctx.fillRect(-(width / 2), -(height / 2), width, height);
  41. }
  42. function analizeLinear(bg, width, height) {
  43. const direction = bg.match(/([-]?\d{1,3})deg/);
  44. const dir = direction && direction[1] ? parseFloat(direction[1]) : 0;
  45. let coordinate;
  46. switch (dir) {
  47. case 0:
  48. coordinate = [0, -height / 2, 0, height / 2];
  49. break;
  50. case 90:
  51. coordinate = [width / 2, 0, -width / 2, 0];
  52. break;
  53. case -90:
  54. coordinate = [-width / 2, 0, width / 2, 0];
  55. break;
  56. case 180:
  57. coordinate = [0, height / 2, 0, -height / 2];
  58. break;
  59. case -180:
  60. coordinate = [0, -height / 2, 0, height / 2];
  61. break;
  62. default:
  63. let x1 = 0;
  64. let y1 = 0;
  65. let x2 = 0;
  66. let y2 = 0;
  67. if (direction[1] > 0 && direction[1] < 90) {
  68. x1 =
  69. width / 2 -
  70. (((width / 2) * Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) - height / 2) * Math.sin((2 * (90 - direction[1]) * Math.PI * 2) / 360)) / 2;
  71. y2 = Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) * x1;
  72. x2 = -x1;
  73. y1 = -y2;
  74. } else if (direction[1] > -180 && direction[1] < -90) {
  75. x1 =
  76. -(width / 2) +
  77. (((width / 2) * Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) - height / 2) * Math.sin((2 * (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 if (direction[1] > 90 && direction[1] < 180) {
  82. x1 =
  83. width / 2 +
  84. ((-(width / 2) * Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) - height / 2) * Math.sin((2 * (90 - direction[1]) * Math.PI * 2) / 360)) / 2;
  85. y2 = Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) * x1;
  86. x2 = -x1;
  87. y1 = -y2;
  88. } else {
  89. x1 =
  90. -(width / 2) -
  91. ((-(width / 2) * Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) - height / 2) * Math.sin((2 * (90 - direction[1]) * Math.PI * 2) / 360)) / 2;
  92. y2 = Math.tan(((90 - direction[1]) * Math.PI * 2) / 360) * x1;
  93. x2 = -x1;
  94. y1 = -y2;
  95. }
  96. coordinate = [x1, y1, x2, y2];
  97. break;
  98. }
  99. return coordinate;
  100. }
  101. function linearEffect(width, height, bg, ctx) {
  102. const param = analizeLinear(bg, width, height);
  103. const grd = ctx.createLinearGradient(param[0], param[1], param[2], param[3]);
  104. const content = bg.match(/linear-gradient\((.+)\)/)[1];
  105. const colorPer = analizeGrad(content.substring(content.indexOf(',') + 1));
  106. for (let i = 0; i < colorPer.colors.length; i++) {
  107. grd.addColorStop(colorPer.percents[i], colorPer.colors[i]);
  108. }
  109. ctx.fillStyle = grd; //ctx.fillRect(-(width / 2), -(height / 2), width, height);
  110. }
  111. module.exports = {
  112. api
  113. };
  114. })();