theme-picker.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <template>
  2. <el-color-picker
  3. class="theme-picker"
  4. popper-class="theme-picker-dropdown"
  5. v-model="theme"></el-color-picker>
  6. </template>
  7. <style>
  8. .theme-picker {
  9. height: 80px;
  10. display: inline-block;
  11. @utils-vertical-center;
  12. }
  13. .theme-picker .el-color-picker__trigger {
  14. vertical-align: middle;
  15. }
  16. .theme-picker-dropdown .el-color-dropdown__link-btn {
  17. display: none;
  18. }
  19. </style>
  20. <script>
  21. import { version } from 'main/index.js';
  22. const ORIGINAL_THEME = '#409EFF';
  23. export default {
  24. data() {
  25. return {
  26. chalk: '', // content of theme-chalk css
  27. docs: '', // content of docs css
  28. theme: ORIGINAL_THEME
  29. };
  30. },
  31. watch: {
  32. theme(val, oldVal) {
  33. if (typeof val !== 'string') return;
  34. const themeCluster = this.getThemeCluster(val.replace('#', ''));
  35. const originalCluster = this.getThemeCluster(oldVal.replace('#', ''));
  36. const getHandler = (text, id) => {
  37. return () => {
  38. const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''));
  39. let newStyle = this.updateStyle(text, originalCluster, themeCluster);
  40. let styleTag = document.getElementById(id);
  41. if (!styleTag) {
  42. styleTag = document.createElement('style');
  43. styleTag.setAttribute('id', id);
  44. document.head.appendChild(styleTag);
  45. }
  46. styleTag.innerText = newStyle;
  47. };
  48. };
  49. const chalkHandler = getHandler(this.chalk, 'chalk-style');
  50. const docsHandler = getHandler(this.docs, 'docs-style');
  51. if (!this.chalk) {
  52. this.getCSSString(`https://unpkg.com/element-ui@${ version }/lib/theme-chalk/index.css`, chalkHandler);
  53. } else {
  54. chalkHandler();
  55. }
  56. if (!this.docs) {
  57. const links = [].filter.call(document.querySelectorAll('link'), link => {
  58. return /docs\..+\.css/.test(link.href || '');
  59. });
  60. links[0] && this.getCSSString(links[0].href, docsHandler);
  61. } else {
  62. docsHandler();
  63. }
  64. const styles = [].slice.call(document.querySelectorAll('style'))
  65. .filter(style => {
  66. const text = style.innerText;
  67. return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text);
  68. });
  69. styles.forEach(style => {
  70. const { innerText } = style;
  71. if (typeof innerText !== 'string') return;
  72. style.innerText = this.updateStyle(innerText, originalCluster, themeCluster);
  73. });
  74. }
  75. },
  76. methods: {
  77. updateStyle(style, oldCluster, newCluster) {
  78. let newStyle = style;
  79. oldCluster.forEach((color, index) => {
  80. newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]);
  81. });
  82. return newStyle;
  83. },
  84. getCSSString(url, callback) {
  85. const xhr = new XMLHttpRequest();
  86. xhr.onreadystatechange = () => {
  87. if (xhr.readyState === 4 && xhr.status === 200) {
  88. this.chalk = xhr.responseText.replace(/@font-face{[^}]+}/, '');
  89. callback();
  90. }
  91. };
  92. xhr.open('GET', url);
  93. xhr.send();
  94. },
  95. getThemeCluster(theme) {
  96. const tintColor = (color, tint) => {
  97. let red = parseInt(color.slice(0, 2), 16);
  98. let green = parseInt(color.slice(2, 4), 16);
  99. let blue = parseInt(color.slice(4, 6), 16);
  100. if (tint === 0) { // when primary color is in its rgb space
  101. return [red, green, blue].join(',');
  102. } else {
  103. red += Math.round(tint * (255 - red));
  104. green += Math.round(tint * (255 - green));
  105. blue += Math.round(tint * (255 - blue));
  106. red = red.toString(16);
  107. green = green.toString(16);
  108. blue = blue.toString(16);
  109. return `#${ red }${ green }${ blue }`;
  110. }
  111. };
  112. const clusters = [theme];
  113. for (let i = 0; i <= 9; i++) {
  114. clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
  115. }
  116. return clusters;
  117. }
  118. }
  119. };
  120. </script>