theme-picker.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. const url = `https://unpkg.com/element-ui@${ version }/lib/theme-chalk/index.css`;
  53. this.getCSSString(url, chalkHandler, 'chalk');
  54. } else {
  55. chalkHandler();
  56. }
  57. if (!this.docs) {
  58. const links = [].filter.call(document.querySelectorAll('link'), link => {
  59. return /docs\..+\.css/.test(link.href || '');
  60. });
  61. links[0] && this.getCSSString(links[0].href, docsHandler, 'docs');
  62. } else {
  63. docsHandler();
  64. }
  65. const styles = [].slice.call(document.querySelectorAll('style'))
  66. .filter(style => {
  67. const text = style.innerText;
  68. return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text);
  69. });
  70. styles.forEach(style => {
  71. const { innerText } = style;
  72. if (typeof innerText !== 'string') return;
  73. style.innerText = this.updateStyle(innerText, originalCluster, themeCluster);
  74. });
  75. }
  76. },
  77. methods: {
  78. updateStyle(style, oldCluster, newCluster) {
  79. let newStyle = style;
  80. oldCluster.forEach((color, index) => {
  81. newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]);
  82. });
  83. return newStyle;
  84. },
  85. getCSSString(url, callback, variable) {
  86. const xhr = new XMLHttpRequest();
  87. xhr.onreadystatechange = () => {
  88. if (xhr.readyState === 4 && xhr.status === 200) {
  89. this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '');
  90. callback();
  91. }
  92. };
  93. xhr.open('GET', url);
  94. xhr.send();
  95. },
  96. getThemeCluster(theme) {
  97. const tintColor = (color, tint) => {
  98. let red = parseInt(color.slice(0, 2), 16);
  99. let green = parseInt(color.slice(2, 4), 16);
  100. let blue = parseInt(color.slice(4, 6), 16);
  101. if (tint === 0) { // when primary color is in its rgb space
  102. return [red, green, blue].join(',');
  103. } else {
  104. red += Math.round(tint * (255 - red));
  105. green += Math.round(tint * (255 - green));
  106. blue += Math.round(tint * (255 - blue));
  107. red = red.toString(16);
  108. green = green.toString(16);
  109. blue = blue.toString(16);
  110. return `#${ red }${ green }${ blue }`;
  111. }
  112. };
  113. const clusters = [theme];
  114. for (let i = 0; i <= 9; i++) {
  115. clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
  116. }
  117. return clusters;
  118. }
  119. }
  120. };
  121. </script>