懒羊羊
2024-01-31 e57a8990ae56f657a59c435a0613c5f7a8728003
提交 | 用户 | 时间
e57a89 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
10 <script>
11 const version = require('element-ui/package.json').version // element-ui version from node_modules
12 const ORIGINAL_THEME = '#409EFF' // default color
13
14 export default {
15   data() {
16     return {
17       chalk: '', // content of theme-chalk css
18       theme: ''
19     }
20   },
21   computed: {
22     defaultTheme() {
23       return this.$store.state.settings.theme
24     }
25   },
26   watch: {
27     defaultTheme: {
28       handler: function(val, oldVal) {
29         this.theme = val
30       },
31       immediate: true
32     },
33     async theme(val) {
34       await this.setTheme(val)
35     }
36   },
37   created() {
38     if(this.defaultTheme !== ORIGINAL_THEME) {
39       this.setTheme(this.defaultTheme)
40     }
41   },
42
43   methods: {
44     async setTheme(val) {
45       const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
46       if (typeof val !== 'string') return
47       const themeCluster = this.getThemeCluster(val.replace('#', ''))
48       const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
49
50       const getHandler = (variable, id) => {
51         return () => {
52           const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
53           const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
54
55           let styleTag = document.getElementById(id)
56           if (!styleTag) {
57             styleTag = document.createElement('style')
58             styleTag.setAttribute('id', id)
59             document.head.appendChild(styleTag)
60           }
61           styleTag.innerText = newStyle
62         }
63       }
64
65       if (!this.chalk) {
66         const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
67         await this.getCSSString(url, 'chalk')
68       }
69
70       const chalkHandler = getHandler('chalk', 'chalk-style')
71
72       chalkHandler()
73
74       const styles = [].slice.call(document.querySelectorAll('style'))
75         .filter(style => {
76           const text = style.innerText
77           return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
78         })
79       styles.forEach(style => {
80         const { innerText } = style
81         if (typeof innerText !== 'string') return
82         style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
83       })
84
85       this.$emit('change', val)
86     },
87
88     updateStyle(style, oldCluster, newCluster) {
89       let newStyle = style
90       oldCluster.forEach((color, index) => {
91         newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
92       })
93       return newStyle
94     },
95
96     getCSSString(url, variable) {
97       return new Promise(resolve => {
98         const xhr = new XMLHttpRequest()
99         xhr.onreadystatechange = () => {
100           if (xhr.readyState === 4 && xhr.status === 200) {
101             this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
102             resolve()
103           }
104         }
105         xhr.open('GET', url)
106         xhr.send()
107       })
108     },
109
110     getThemeCluster(theme) {
111       const tintColor = (color, tint) => {
112         let red = parseInt(color.slice(0, 2), 16)
113         let green = parseInt(color.slice(2, 4), 16)
114         let blue = parseInt(color.slice(4, 6), 16)
115
116         if (tint === 0) { // when primary color is in its rgb space
117           return [red, green, blue].join(',')
118         } else {
119           red += Math.round(tint * (255 - red))
120           green += Math.round(tint * (255 - green))
121           blue += Math.round(tint * (255 - blue))
122
123           red = red.toString(16)
124           green = green.toString(16)
125           blue = blue.toString(16)
126
127           return `#${red}${green}${blue}`
128         }
129       }
130
131       const shadeColor = (color, shade) => {
132         let red = parseInt(color.slice(0, 2), 16)
133         let green = parseInt(color.slice(2, 4), 16)
134         let blue = parseInt(color.slice(4, 6), 16)
135
136         red = Math.round((1 - shade) * red)
137         green = Math.round((1 - shade) * green)
138         blue = Math.round((1 - shade) * blue)
139
140         red = red.toString(16)
141         green = green.toString(16)
142         blue = blue.toString(16)
143
144         return `#${red}${green}${blue}`
145       }
146
147       const clusters = [theme]
148       for (let i = 0; i <= 9; i++) {
149         clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
150       }
151       clusters.push(shadeColor(theme, 0.1))
152       return clusters
153     }
154   }
155 }
156 </script>
157
158 <style>
159 .theme-message,
160 .theme-picker-dropdown {
161   z-index: 99999 !important;
162 }
163
164 .theme-picker .el-color-picker__trigger {
165   height: 26px !important;
166   width: 26px !important;
167   padding: 2px;
168 }
169
170 .theme-picker-dropdown .el-color-dropdown__link-btn {
171   display: none;
172 }
173 </style>