Skip to content

Commit 55cb450

Browse files
committed
feat: 播放器音量功能
1 parent 9d45886 commit 55cb450

File tree

16 files changed

+490
-147
lines changed

16 files changed

+490
-147
lines changed

public/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<meta http-equiv="X-UA-Compatible" content="IE=edge">
77
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
88
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
9-
<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_777085_hhq2p3r7g3u.css">
9+
<link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/font_777085_lg5nuqbwl.css">
1010
<title>vue-netease-muisc</title>
1111
</head>
1212

src/App.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
<div id="app">
33
<Layout />
44
<MiniPlayer />
5+
<Playlist />
56
</div>
67
</template>
78

89
<script>
910
import Layout from "@/layout"
1011
import MiniPlayer from "@/components/mini-player"
12+
import Playlist from "@/components/playlist"
1113
export default {
12-
components: { Layout, MiniPlayer }
14+
components: { Layout, MiniPlayer, Playlist }
1315
}
1416
</script>
1517

src/base/icon.vue

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
11
<template>
22
<i
3-
class="iconfont"
4-
:class="`icon-${type}`"
3+
class="iconfont icon-component"
4+
:class="getIconCls()"
55
:style="{fontSize: `${size}px`}"
66
/>
77
</template>
88

99
<script type="text/ecmascript-6">
1010
export default {
11-
props: ["size", "type"]
11+
props: ["size", "type", "color"],
12+
methods: {
13+
getIconCls() {
14+
let cls = `icon-${this.type}`
15+
if (this.color) {
16+
cls += ` icon-color-${this.color}`
17+
}
18+
return cls
19+
}
20+
}
1221
}
1322
</script>
1423

15-
<style lang="scss" scoped>
16-
.iconfont {
24+
<style lang="scss">
25+
.icon-component {
1726
color: #fff;
1827
}
28+
29+
.icon-color-theme {
30+
color: $theme-color;
31+
}
1932
</style>

src/base/progress-bar.vue

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
<div
1313
class="progress-btn-wrapper"
1414
ref="progressBtn"
15-
@touchstart.prevent="progressTouchStart"
16-
@touchmove.prevent="progressTouchMove"
17-
@touchend="progressTouchEnd"
1815
>
19-
<div class="progress-btn"></div>
16+
<div
17+
class="progress-btn"
18+
:class="{show: alwaysShowBtn}"
19+
></div>
2020
</div>
2121
</div>
2222
</div>
@@ -25,52 +25,39 @@
2525
<script type="text/ecmascript-6">
2626
import { prefixStyle } from "@/utils/dom"
2727
28-
const progressBtnWidth = 16
2928
const transform = prefixStyle("transform")
3029
3130
export default {
3231
props: {
3332
percent: {
3433
type: Number,
3534
default: 0
35+
},
36+
alwaysShowBtn: {
37+
type: Boolean,
38+
default: false
3639
}
3740
},
3841
created() {
3942
this.touch = {}
4043
},
44+
mounted() {
45+
if (this.percent > 0) {
46+
this.setProgressOffset(this.percent)
47+
}
48+
},
4149
methods: {
42-
progressTouchStart(e) {
43-
this.touch.initiated = true
44-
this.touch.startX = e.touches[0].pageX
45-
this.touch.left = this.$refs.progress.clientWidth
46-
},
47-
progressTouchMove(e) {
48-
if (!this.touch.initiated) {
49-
return
50-
}
51-
const deltaX = e.touches[0].pageX - this.touch.startX
52-
const offsetWidth = Math.min(
53-
this.$refs.progressBar.clientWidth - progressBtnWidth,
54-
Math.max(0, this.touch.left + deltaX)
55-
)
56-
this._offset(offsetWidth)
57-
this.$emit("percentChanging", this._getPercent())
58-
},
59-
progressTouchEnd() {
60-
this.touch.initiated = false
61-
this._triggerPercent()
62-
},
6350
progressClick(e) {
6451
const rect = this.$refs.progressBar.getBoundingClientRect()
65-
const offsetWidth = e.pageX - rect.left
52+
const offsetWidth = Math.max(0, Math.min(e.pageX - rect.left, this.$refs.progressBar.clientWidth))
6653
this._offset(offsetWidth)
6754
// 这里当我们点击 progressBtn 的时候,e.offsetX 获取不对
6855
// this._offset(e.offsetX)
6956
this._triggerPercent()
7057
},
7158
setProgressOffset(percent) {
7259
if (percent >= 0 && !this.touch.initiated) {
73-
const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
60+
const barWidth = this.$refs.progressBar.clientWidth
7461
const offsetWidth = percent * barWidth
7562
this._offset(offsetWidth)
7663
}
@@ -85,7 +72,7 @@ export default {
8572
] = `translate3d(${offsetWidth}px,0,0)`
8673
},
8774
_getPercent() {
88-
const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
75+
const barWidth = this.$refs.progressBar.clientWidth
8976
return this.$refs.progress.clientWidth / barWidth
9077
}
9178
},
@@ -104,7 +91,7 @@ export default {
10491
10592
.bar-inner {
10693
position: relative;
107-
top: 13px;
94+
top: 14px;
10895
height: 2px;
10996
background: rgba(0, 0, 0, 0.3);
11097
@@ -116,7 +103,7 @@ export default {
116103
117104
.progress-btn-wrapper {
118105
position: absolute;
119-
left: -8px;
106+
left: -15px;
120107
top: -13px;
121108
width: 30px;
122109
height: 30px;
@@ -125,12 +112,16 @@ export default {
125112
display: none;
126113
position: relative;
127114
top: 8px;
128-
left: 7px;
115+
left: 9px;
129116
box-sizing: border-box;
130117
width: 12px;
131118
height: 12px;
132119
border-radius: 50%;
133120
background: $theme-color;
121+
122+
&.show {
123+
display: block;
124+
}
134125
}
135126
}
136127
}

src/base/volume.vue

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<template>
2+
<div class="volume">
3+
<Icon
4+
:size="20"
5+
class="icon"
6+
:type="getIconType()"
7+
@click.native="toggleSilence"
8+
/>
9+
<div class="progress-wrap">
10+
<ProgressBar
11+
alwaysShowBtn
12+
:percent="volumePercent"
13+
@percentChange="onProgressChange"
14+
/>
15+
</div>
16+
</div>
17+
</template>
18+
19+
<script type="text/ecmascript-6">
20+
import ProgressBar from '@/base/progress-bar'
21+
export default {
22+
data() {
23+
return {
24+
volumePercent: 1
25+
}
26+
},
27+
methods: {
28+
onProgressChange(percent) {
29+
if (percent < 0.05) {
30+
percent = 0
31+
}
32+
this.volumePercent = percent
33+
this.$emit('volumeChange', percent)
34+
},
35+
getIconType() {
36+
return this.isSilence ? 'silence' : 'horn'
37+
},
38+
toggleSilence() {
39+
this.isSilence = !this.isSilence
40+
}
41+
},
42+
computed: {
43+
isSilence: {
44+
get() {
45+
return this.volumePercent === 0
46+
},
47+
set(newSilence) {
48+
const target = newSilence ? 0 : this.lastVolume
49+
if (newSilence) {
50+
this.lastVolume = this.volumePercent
51+
}
52+
this.volumePercent = target
53+
this.onProgressChange(target)
54+
}
55+
}
56+
},
57+
components: {
58+
ProgressBar
59+
}
60+
}
61+
</script>
62+
63+
<style lang="scss" scoped>
64+
.volume {
65+
display: flex;
66+
align-items: center;
67+
width: 150px;
68+
padding: 0 16px;
69+
70+
.icon {
71+
color: $font-color;
72+
cursor: pointer;
73+
margin-right: 8px;
74+
}
75+
.progress-wrap {
76+
flex: 1;
77+
}
78+
}
79+
</style>

0 commit comments

Comments
 (0)