index.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <template>
  2. <el-color-picker
  3. v-model="theme"
  4. :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
  5. class="theme-picker"
  6. popper-class="theme-picker-dropdown"
  7. />
  8. </template>
  9. <script>
  10. const ORIGINAL_THEME = '#409EFF' // default color
  11. export default {
  12. data() {
  13. return {
  14. chalk: '', // content of theme-chalk css
  15. theme: ''
  16. }
  17. },
  18. computed: {
  19. defaultTheme() {
  20. return this.$store.state.settings.theme
  21. }
  22. },
  23. watch: {
  24. defaultTheme: {
  25. handler: function(val, oldVal) {
  26. this.theme = val
  27. },
  28. immediate: true
  29. },
  30. async theme(val) {
  31. await this.setTheme(val)
  32. }
  33. },
  34. created() {
  35. if(this.defaultTheme !== ORIGINAL_THEME) {
  36. this.setTheme(this.defaultTheme)
  37. }
  38. },
  39. methods: {
  40. async setTheme(val) {
  41. const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
  42. if (typeof val !== 'string') return
  43. const themeCluster = this.getThemeCluster(val.replace('#', ''))
  44. const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
  45. const getHandler = (variable, id) => {
  46. return () => {
  47. const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
  48. const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
  49. let styleTag = document.getElementById(id)
  50. if (!styleTag) {
  51. styleTag = document.createElement('style')
  52. styleTag.setAttribute('id', id)
  53. document.head.appendChild(styleTag)
  54. }
  55. styleTag.innerText = newStyle
  56. }
  57. }
  58. if (!this.chalk) {
  59. const url = `/styles/theme-chalk/index.css`
  60. await this.getCSSString(url, 'chalk')
  61. }
  62. const chalkHandler = getHandler('chalk', 'chalk-style')
  63. chalkHandler()
  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. this.$emit('change', val)
  75. },
  76. updateStyle(style, oldCluster, newCluster) {
  77. let newStyle = style
  78. oldCluster.forEach((color, index) => {
  79. newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
  80. })
  81. return newStyle
  82. },
  83. getCSSString(url, variable) {
  84. return new Promise(resolve => {
  85. const xhr = new XMLHttpRequest()
  86. xhr.onreadystatechange = () => {
  87. if (xhr.readyState === 4 && xhr.status === 200) {
  88. this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
  89. resolve()
  90. }
  91. }
  92. xhr.open('GET', url)
  93. xhr.send()
  94. })
  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 shadeColor = (color, shade) => {
  114. let red = parseInt(color.slice(0, 2), 16)
  115. let green = parseInt(color.slice(2, 4), 16)
  116. let blue = parseInt(color.slice(4, 6), 16)
  117. red = Math.round((1 - shade) * red)
  118. green = Math.round((1 - shade) * green)
  119. blue = Math.round((1 - shade) * blue)
  120. red = red.toString(16)
  121. green = green.toString(16)
  122. blue = blue.toString(16)
  123. return `#${red}${green}${blue}`
  124. }
  125. const clusters = [theme]
  126. for (let i = 0; i <= 9; i++) {
  127. clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
  128. }
  129. clusters.push(shadeColor(theme, 0.1))
  130. return clusters
  131. }
  132. }
  133. }
  134. </script>
  135. <style>
  136. .theme-message,
  137. .theme-picker-dropdown {
  138. z-index: 99999 !important;
  139. }
  140. .theme-picker .el-color-picker__trigger {
  141. height: 26px !important;
  142. width: 26px !important;
  143. padding: 2px;
  144. }
  145. .theme-picker-dropdown .el-color-dropdown__link-btn {
  146. display: none;
  147. }
  148. </style>