Theme skin changing based on element UI

Today we share the theme skin changing function based on element UI

demand

The effect is shown in the moving picture:

Requirement Description: switch themes of different colors and styles according to customers' personal preferences.

Key point 1: configure the theme color in the official element ui and download the corresponding file, which must correspond to the color given by the ui.

Key point 2: realize the switching function, call the interface and save the user's choice. (after optimization, the first thing to do is to save locally, but the product thinks it should be saved so that users can show their previous choices when logging in elsewhere)

Key point 3: all colors related to the theme (background, border, underline, special font, etc.) are controlled by variables. The less syntax used in the project is @ *****.

Step 1: download the configuration file



ps: the red box in the first figure is the color of relevant components in the custom theme. Click download after setting. The downloaded file includes css file and font file. The second picture is the theme static file with corresponding colors configured.

Step 2: realize switching function

1. Skin component code (not including style code, otherwise it is too long)

<template>
  <div class="color" @click.stop>
    <el-scrollbar style="height: 100%;">
      <div class="dropMeau">
        <div class="headerLine">
          Classic skin {{getSkinName}}
        </div>
        <div class="wrapCell">
          <div class="colorSkinWrap" v-for="(item,i,k) in  themeList">
            <span finger @click="changeColor(item.themeName)" :style="{background: computedBgc(item) }" class="colorSkin " :class="{active:getSkinName==item.themeName}" style=" background: #042663;">
              <span class="icon-yiwancheng iconfont"></span>
            </span>
            <p class="name">{{item.themeName}}</p>
          </div>
        </div>
      </div>
    </el-scrollbar>
  </div>
</template>

<script>
import themeList from '@libs/css/style.js'   // Define the color js file, which contains the color and special picture address
import { mixin } from "@libs/mixs.js"; 
import {
  mapActions,
  mapGetters
} from 'vuex'
export default {
  name: "messageQuick",
  mixins: [mixin],
  data() {
    return {
      themeName: '',
      themeList,
    }
  },
  computed: {
    ...mapGetters('info', ['getSkinName']), // Color variable attribute that exists in vux
  },
  created() {
  },
  methods: {
    ...mapActions('info', [
      'actionSkinChange'   
    ]),
    computedBgc(item) {
      if (item.spec) {
        return `${item.style['--primary-color']} url('${item.showBox}')`
      } else {
        return item.style['--primary-color']
      }
    },
    changeColor(name) {   //Theme jump page to judge skin change

      if (name != this.getSkinName) {
        this.axios({
          url: "/service-user-app/app/user/config/skin/peeler",  // Save user's selection interface
          method: "post",
          params: {
            colour: name
          },
          interface: 1
        }).then(res => {
          let data = res.data
          if (data.code == 0) {
              this.actionSkinChange(name)   // Change the default color value in vux
              this.setStyleRoot(name, themeList)  // Change theme color
          }
        })
      }
    }
  },
}

2. themeList color code (there are 11 color configuration attributes in it, and I only take two typical ones)

export default  [
  {
    "themeName": "Cyanosis",
    // gangqing
    "src": "/static/theme/gangqing/index.css",
    "style": {
      "--primary-color": "#245BBF",
      "--table-header-bcolor": "#F7F7F7",
      "--primary-mix05": "#CFD5E0",
      "--primary-mix1": "#CFD5E0",
      "--primary-mix2": "#BDC8DC",
      "--primary-mix3": "#A9BAD9",
      "--primary-mix4": "#97ADD5",
      "--primary-mix5": "#849FD2",
      "--primary-mix6": "#7091CD",
      "--primary-mix7": "#5D83CA",
      "--primary-mix8": "#4A76C6",
      "--primary-mix9": "#3769C3",

      /* navigation bar */
      "--nav-backgroud-color": "#042663",
      "--nav-ul-backgroud-color": "#fff",
      "--nav-ul-font-color": "#333",
      "--nav-ul-active-backgroud-color": "#D8E6FF",
      "--nav-ul-active-font-color": "#333",


      /* Head color*/
      "--header-backgroud-color": "#042663",
    }
  },
// todo plus pictures
  {
    "themeName": "Begonia",
    // zitang
    "spec":true,
    "showBox":'/static/img/zitang.png',
    "src": "/static/theme/zitang/index.css",
    "style": {
      "--primary-color": "#78359A",
      "--table-header-bcolor": "#F7F7F7",
      "--primary-mix05": "#F1EAF5",
      "--primary-mix1": "#F1EAF5",
      "--primary-mix2": "#E4D6EB",
      "--primary-mix3": "#D6C2E0",
      "--primary-mix4": "#C9AED6",
      "--primary-mix5": "#BB99CC",
      "--primary-mix6": "#AE85C2",
      "--primary-mix7": "#A071B8",
      "--primary-mix8": "#935DAE",
      "--primary-mix9": "#8548A3",

      /* navigation bar */
      // "--nav-backgroud-color": "#531659",
      "--nav-backgroud-color": "#531659 url('/static/img/zitang1.jpg')",
      "--nav-ul-backgroud-color": "#fff",
      "--nav-ul-font-color": "#333",
      "--nav-ul-active-backgroud-color": "#F6EAFC",
      "--nav-ul-active-font-color": "#333",


      /* Head color*/
      // "--header-backgroud-color": "#531659",
      "--header-backgroud-color": "#531659 url('/static/img/zitang2.jpg')",
    }
  },
]

ps: because there are too many codes, it is drawn into a js file. I only take two code segments with different colors (11 complete ones, the same as those on the page). There is "spec": true. The color of the attribute is the theme with patterns, not the ordinary plain color theme.

3. vux code (save the acquired color after the user logs in)

import Vue from "vue"
import {isHiddenPhone} from '@libs/http/vuex_http'

export let info = {
  namespaced:true,
  state:{
    skinName:'',
    _radio:null,  // '0':'1'
    timestamp:new Date().getTime() -0 + 1800000
  },
  getters: {
    radio: state => state.radio,
    getSkinName:state => state.skinName||'Cyanosis',//Default skin
  },
  mutations: {
    changeSkin(state, data) {
      state.skinName = data
    },
    changeHiddenStatus(state, data) {
      state._radio = data
    },
  },
  actions: {
    actionSkinChange({ commit,getters},res){ // Modify the skinName value in state
      commit('changeSkin',res)
    },
    httpForIsHiddenPhone ({ commit,getters}) {
      isHiddenPhone(Vue).then(res=>{
        if (res.data.code == '0') {
          //  Whether to hide true needs to hide the middle four digits of the phone number. false does not need to be hidden
          commit('changeHiddenStatus',res.data.data?'0':'1')
        }
      })
    }
  }
}

4. Key code for switching theme color

/**
		 * @description: Set skin
		 * @param {themeName} Custom style name
		 * @return {*}
		 */
		setStyleRoot(themeName, themeList = []) {
			let arr = themeList.filter(q => q.themeName == themeName)
			if (arr.length == 0) return console.error('Unstyled skin')
			let item = arr[0]
			let root = []
			for (let i in item.style) {
				root.push(i + `:` + item.style[i])  
			}
			let test = `:root{${root.join(';')}}` // Splice to style code, 
			// Root: This CSS pseudo class matches the root element of the document tree. For HTML,: root represents the < HTML > element, which is the same as the HTML selector except for higher priority.
			this.addNode(test, item.src)
		},

		/**
		 * @description: Add skin node
		 * @param {test} Setting: root style
		 * @param {url} Inserted outer chain
		 * @return {*}
		 */
		addNode(test, url) {
			let styleNode = document.getElementById('theme')
			let linkNode = document.getElementById('linkTheme')
			if (styleNode) {     // If there is a node, it will be changed, and if there is no node, it will be created
				styleNode.innerHTML = test
				document.getElementsByTagName('body')[0].appendChild(styleNode)
				if(linkNode.getAttribute('href') != url) {
					linkNode.setAttribute('href', url)
				}
			} else {
				styleNode = document.createElement('style')
				linkNode = document.createElement('link')
				styleNode.setAttribute('id', 'theme')
				linkNode.setAttribute('href', url)
				linkNode.setAttribute('id', "linkTheme")
				linkNode.setAttribute('rel', "stylesheet")
				linkNode.setAttribute('type', "text/css")
				styleNode.innerHTML = test
				document.getElementsByTagName('body')[0].appendChild(styleNode)
				document.getElementsByTagName('head')[0].appendChild(linkNode)
			}
		},

5. less color variable code

@primaryColor: var(--primary-color,#245BBF);  //If the theme color var global variable, - primary color has no value, it is the default color #245BBF

//Color value percentage of mixed white to be replaced
@primaryColorMix05:var(--primary-mix05,#F3F6FC);
@primaryColorMix1:var(--primary-mix1,#E8EEF9);
@primaryColorMix2:var(--primary-mix2,#D3DEF2);
@primaryColorMix3:var(--primary-mix3,#BCCDEC);
@primaryColorMix4:var(--primary-mix4,#A7BDE5);
@primaryColorMix5:var(--primary-mix5,#91ACDF);
@primaryColorMix6:var(--primary-mix6,#7B9CDF);
@primaryColorMix7:var(--primary-mix7,#658BD2);
@primaryColorMix8:var(--primary-mix8,#4f7BCB);
@primaryColorMix9:var(--primary-mix9,#396BC5);


@borderColor_base: #e5e5e5;  // General border color value
@tableBColor_base:var(--table-header-bcolor,#F7F7F7);  // Table header color

/* Navigation bar color value */
@navBackgroudColor: var(--nav-backgroud-color, #ffffff);
//@navBackgroudImg: var(--nav-backgroud-img);
@navUlBackgroudColor: var(--nav-ul-backgroud-color, #ffffff);
@navUlFontColor: var(--nav-ul-font-color, #ffffff);
@navUlActiveBackgroudColor: var(--nav-ul-active-backgroud-color, #ffffff);
@navUlActiveFontColor: var(--nav-ul-active-font-color, #ffffff);
@headerBackgroudColor: var(--header-backgroud-color, #ffffff);
//@headerBackgroudImg: var(--header-backgroud-img);

ps: all color codes related to theme colors should use @ ******, such as a css Style:

.active {
   font-size: 14px;
   font-weight: 700;
   color: @primaryColor;
   border-bottom: 1px solid @primaryColor;
}
Step 3: restore the previously saved theme color after login
	  getSkin(){
        this.axios({
          url: "/service-user-app/app/user/config/select-by-userId",
          method: "get",
          interface:1
        }).then(res => {
          let data = res.data
          if (data.code == 0) {
            if(!data.data)return
            let obj = JSON.parse(data.data.val)
            this.actionSkinChange(obj.colour)//Save it
            this.setStyleRoot(obj.colour, themeList) //change one's skin
          }
        })
      },

ps: the interface returns: val: "{" platformSource ": 22," colour ":" cyan "}", so it needs to be deserialized.

I shared a wave years ago. There are places that can be optimized. I also hope you can give me some advice.

Keywords: Javascript Vue.js css

Added by gizmola on Fri, 28 Jan 2022 02:41:44 +0200