手撸手完成网抑云音乐2 换肤之旅

346 阅读4分钟
1. 换肤 首先要先将颜色变量提取出来
##### base.scss
```css
@import "./reset.scss";
@import "./variable.scss";
@import "./mixin.scss";

html, body{
  width: 100%;
  height: 100%;
  overflow: hidden;
  // 解决IScroll拖拽卡顿问题
  touch-action: none;
}
body{
  @include font_size($font_medium);
  //@include font_size(50px);
  //font-size: 50px;
  font-family: Helvetica,sans-serif,STHeiTi;
}
img{
  vertical-align: bottom;
}
mixin.scss
@import "./variable.scss";

/*根据dpr计算font-size*/
@mixin font_dpr($font-size) {
  font-size: $font-size;

  [data-dpr="2"] & {
    font-size: $font-size * 2;
  }

  [data-dpr="3"] & {
    font-size: $font-size * 3;
  }
}

/*通过该函数设置字体大小,后期方便统一管理;*/
@mixin font_size($size) {
  @include font_dpr($size);
}

// 不换行
@mixin no-wrap() {
  text-overflow: ellipsis;
  overflow     : hidden;
  white-space  : nowrap;
}

// 限制行数
@mixin clamp($row) {
  overflow          : hidden;
  text-overflow     : ellipsis;
  display           : -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: $row;
}

// 根据属性选择器来设置背景颜色
@mixin bg_color() {
  background: $background-color-theme;

  // 判断data的自定义属性
  [data-theme=theme1] & {
    background: $background-color-theme1;
  }

  [data-theme=theme2] & {
    background: $background-color-theme2;
  }
}

reset.scss

html{color:#000;background:#FFF}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0}
table{border-collapse:collapse;border-spacing:0}
fieldset,img{border:0}
address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal}
ol,ul{list-style:none}
caption,th{text-align:left}
h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}
q:before,q:after{content:''}
abbr,acronym{border:0;font-variant:normal}
sup{vertical-align:text-top}
sub{vertical-align:text-bottom}
input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;*font-size:100%}
legend{color:#000}
a{text-decoration: none}
#yui3-css-stamp.cssreset{display:none}
variable.scss
//字体定义规范
$font_samll:12Px;
$font_medium_s:13Px;
$font_medium:15Px;
$font_large:17Px;

// 背景颜色规范(主要)
$background-color-theme: #d43c33;//背景主题颜色默认(网易红)
$background-color-theme1: rgba(34,213,156,1);//背景主题颜色1(QQ绿)
$background-color-theme2: #333;//背景主题颜色2(夜间模式)

// 背景颜色规范(次要)
$background-color-sub-theme: #f5f5f5;//背景主题颜色默认(网易红)
$background-color-sub-theme1: #f5f5f5;//背景主题颜色1(QQ绿)
$background-color-sub-theme2: #444;//背景主题颜色2(夜间模式)

// 字体颜色规范(默认)
$font-color-theme : #666;//字体主题颜色默认(网易)
$font-color-theme1 : #666;//字体主题颜色1(QQ)
$font-color-theme2 : #ddd;//字体主题颜色2(夜间模式)

// 字体颜色规范(激活)
$font-active-color-theme : #d43c33;//字体主题颜色默认(网易红)
$font-active-color-theme1 : rgba(34,213,156,1);//字体主题颜色1(QQ绿)
$font-active-color-theme2 : #ffcc33;//字体主题颜色2(夜间模式)

// 边框颜色
$border-color-theme : #d43c33;//边框主题颜色默认(网易)
$border-color-theme1 : rgba(34,213,156,1);//边框主题颜色1(QQ)
$border-color-theme2 : #ffcc33;//边框主题颜色2(夜间模式)

换肤之旅开始

在components新建一个header.vue文件 基础版
  • 导入准备好的scss

  • @import "@/assets/css/variable.scss"; @import "@/assets/css/mixin.scss";

  • 头部的背景颜色采用颜色变量

  • 默认就是红色 所以直接使用这个bg_color函数即可

  • @include bg_color();

<template>
  <div class="header">
    <div class="header-left"></div>
    <p class="title">网抑云音乐</p>
    <div class="header-right"></div>
  </div>
</template>

<script>
export default {}
</script>

<style lang="scss" scoped>
@import "@/assets/css/variable.scss";
@import "@/assets/css/mixin.scss";
.header {
  width: 100%;
  height: 100px;
  // 默认颜色 网易红
  @include bg_color();
  display: flex;
  justify-content: space-between;
  .header-left,
  .header-right {
    width: 84px;
    height: 84px;
    margin-top: 8px;
    background-color: #000;
  }
  .title {
    line-height: 100px;
    text-align: center;
  }
}
</style>

2 在app.vue 注册头部组件 以及使用颜色变量
<template>
  <div id="app">
    <Header></Header>
    <div class="theme">
      <button @click="fn('theme')"></button>
      <button @click="fn('theme1')"></button>
      <button @click="fn('theme2')"></button>
    </div>
  </div>
</template>
<script>
import Header from './components/Header'
export default {
  components: {
    Header
  },
  methods: {
  	// 换肤函数 点击不同按钮切换
    fn (data) {
      console.log(data)
      // 添加自定义属性
      document.documentElement.setAttribute('data-theme', data)
    }
  }
}
</script>
<style lang="scss" scoped>
@import "./assets/css/variable.scss";
.theme {
  position: absolute;
  bottom: 0;
  left: 0;
  button {
    width: 100px;
    height: 100px;
    &:nth-of-type(1) {
      background-color: $background-color-theme;
    }
    &:nth-of-type(2) {
      background-color: $background-color-theme1;
    }
    &:nth-of-type(3) {
      background-color: $background-color-theme2;
    }
  }
}
</style>
2.1 配合scss来理解
  • 我们在fn函数 document.documentElement.setAttribute('data-theme', data) 添加了这个自定义属性名叫data-theme 并且传了值
  • 所以在bg_color这个函数判断 这个属性是否等于传入的值 根据传入的值给不同的颜色变量 默认就给网易红 所以默认我们直接调用这个函数
  • 在Header组件中我们头部的背景颜色就是使用bg_color控制 所以只要我们点击不同的按钮就会传不同的值 颜色也就随着改变
// 根据属性选择器来设置背景颜色
@mixin bg_color() {
  background: $background-color-theme;

  // 判断data的自定义属性
  [data-theme=theme1] & {
    background: $background-color-theme1;
  }

  [data-theme=theme2] & {
    background: $background-color-theme2;
  }
}
  • 颜色变量scss
// 背景颜色规范(主要)
$background-color-theme: #d43c33;//背景主题颜色默认(网易红)
$background-color-theme1: rgba(34,213,156,1);//背景主题颜色1(QQ绿)
$background-color-theme2: #333;//背景主题颜色2(夜间模式)
3 点击头部直接换肤以及图片 其原理其实和基础一致
  • 在组件Header.vue中 直接使用两个变量 颜色数组数组 和 下标 以此来换肤 当下标大于等于颜色数据数组 要重置下标为0
  • 核心其实是让颜色数据数组的变量与下标保持一致 每次点击下标++ 而基础版我们使用三个按钮 传入对应的颜色变量形参
  • mixin.scss文件中 要去配置对应的数据
  • 图片换肤 还是跟颜色一样 都是拿我们自定义的属性判断 添加不同的后缀
  • 去掉app.vue中按钮的事件
<template>
  <div class="header" @click="changeTheme">
    <div class="header-left"></div>
    <p class="title">网抑云音乐</p>
    <div class="header-right"></div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      // 换肤颜色数组
      themeArr: ['theme', 'theme1', 'theme2'],
      // 换肤默认下标
      corlorIndex: 0
    }
  },
  methods: {
    // 换肤操作
    changeTheme () {
      this.corlorIndex++
      // 判断是否超出配置的颜色数据
      if (this.corlorIndex >= this.themeArr.length) {
        // 重置index
        this.corlorIndex = 0
      }
      // 添加换肤
      document.documentElement.setAttribute('data-theme', this.themeArr[this.corlorIndex])
    }
  }
}
</script>

<style lang="scss" scoped>
@import "@/assets/css/variable.scss";
@import "@/assets/css/mixin.scss";
.header {
  width: 100%;
  height: 100px;
  // 默认颜色 网易红
  @include bg_color();
  display: flex;
  justify-content: space-between;
  .header-left,
  .header-right {
    width: 84px;
    height: 84px;
    margin-top: 8px;
  }
  .header-left {
    // 图片换肤
    @include bg_img("../assets/images/logo");
  }
  .header-right {
    // 图片换肤
    @include bg_img("../assets/images/account");
  }
  .title {
    line-height: 100px;
    text-align: center;
    color: #fff;
    font-weight: bold;
    @include font_size($font_medium_s);
  }
}
</style>

mixin.scss
// 图片换肤
@mixin bg_img($url) {
  [data-theme=theme] & {
    background-image: url($url + '_163.png');
  }

  [data-theme=theme1] & {
    background-image: url($url + '_qq.png');
  }

  [data-theme=theme2] & {
    background-image: url($url + '_it666.png');
  }

  background-size  : cover;
  background-repeat: no-repeat;

  [data-theme=theme][data-dpr='2'] & {
    background-image: url($url + '_163@2x.png');
  }

  [data-theme=theme][data-dpr='3'] & {
    background-image: url($url + '_163@3x.png');
  }

  [data-theme=theme1][data-dpr='2'] & {
    background-image: url($url + '_qq@2x.png');
  }

  [data-theme=theme1][data-dpr='3'] & {
    background-image: url($url + '_qq@3x.png');
  }

  [data-theme=theme2][data-dpr='2'] & {
    background-image: url($url + '_it666@2x.png');
  }

  [data-theme=theme2][data-dpr='3'] & {
    background-image: url($url + '_it666@3x.png');
  }
}

tabbar换肤

结构代码
<template>
  <div class="Tabbar">
    <router-link tag="div" class="item" to="/recommend">
      <span>推荐</span></router-link
    >
    <router-link tag="div" class="item" to="/singer">
      <span>歌手</span></router-link
    >
    <router-link tag="div" class="item" to="/rank">
      <span>排行</span></router-link
    >
    <router-link tag="div" class="item" to="/search">
      <span>搜索</span></router-link
    >
  </div>
</template>

<script>
export default {}
</script>

<style lang="scss">
@import "@/assets/css/mixin.scss";
@import "@/assets/css/variable.scss";
.Tabbar {
  width: 100%;
  height: 84px;
  display: flex;
  @include bg_sub_color();
  justify-content: space-around;
  .item {
    span {
      line-height: 84px;
      @include font_size($font_medium);
      @include font_color();
    }
    &.router-link-active {
      span {
        @include font_active_color();
      }
      border-bottom: 5px solid #000;
      @include border_color();
    }
  }
}
</style>

2 只要使用router-link 选中就会有router-link-active
  • 根据这个特性添加 选中的颜色变量 以及边框
&.router-link-active {
      span {
        @include font_active_color();
      }
      border-bottom: 5px solid #000;
      @include border_color();
    }
3 tabbar的背景颜色也要跟随变化
.Tabbar {
  width: 100%;
  height: 84px;
  display: flex;
  // 添加背景颜色 能直接使用函数 因为这个函数默认就是网易红 之后根据对应的自定义data-theme属性 来判断 1 为绿色 2为黑色 默认红色
  @include bg_sub_color();
  justify-content: space-around;
}
4.图片换肤
  • 根据每个颜色不同我们换上不同的图片 常见的场景就是在白天和黑夜模式
  • 在此之上还改进了 根据不同的屏幕下 图片的倍图也会改变
  • scss
// 图片换肤
@mixin bg_img($url) {
  [data-theme=theme] & {
    background-image: url($url + '_163.png');
  }

  [data-theme=theme1] & {
    background-image: url($url + '_qq.png');
  }

  [data-theme=theme2] & {
    background-image: url($url + '_it666.png');
  }

  background-size  : cover;
  background-repeat: no-repeat;

  [data-theme=theme][data-dpr='2'] & {
    background-image: url($url + '_163@2x.png');
  }

  [data-theme=theme][data-dpr='3'] & {
    background-image: url($url + '_163@3x.png');
  }

  [data-theme=theme1][data-dpr='2'] & {
    background-image: url($url + '_qq@2x.png');
  }

  [data-theme=theme1][data-dpr='3'] & {
    background-image: url($url + '_qq@3x.png');
  }

  [data-theme=theme2][data-dpr='2'] & {
    background-image: url($url + '_it666@2x.png');
  }

  [data-theme=theme2][data-dpr='3'] & {
    background-image: url($url + '_it666@3x.png');
  }
}
  • 使用 bg_img 就直接点出图片 不带后缀即可
  • ../assets/images/logo.163.png原本路径 因为我们配置了路径函数 所以去掉.163.png即可
@include bg_img("../assets/images/account");
@include bg_img("../assets/images/logo");