1.public/css/variable.scss
// 颜色定义规范
$color-background: #F2F3F4;
$color-background-d: rgba(0, 0, 0, 0.3);
$color-highlight-background: rgb(253, 108, 98);
$color-dialog-background: rgb(204, 204, 204);
$color-theme: rgb(212, 68, 57);
$color-theme-l: rgba(185, 9, 1, 0.2);
$color-theme-g: rgb(219, 219, 219);
$color-theme-d: rgba(19, 19, 19, 0.6);
$color-sub-theme: rgb(240, 116, 107);
$color-text: #2E3030;
$color-text-g: #757575;
$color-text-ggg: #c7c7c7;
$color-text-gg: rgb(219, 219, 219);
$color-text-l: rgb(241, 241, 241);
$color-text-lm: rgb(228, 228, 228);
$color-text-ll: rgba(255, 255, 255, 0.8);
//字体定义规范
$font-size-small-ss: 9px;
$font-size-small-s: 10px;
$font-size-small: 11px;
$font-size-small-x: 12px;
$font-size-medium: 14px;
$font-size-medium-x: 16px;
$font-size-large-s: 17px;
$font-size-large: 18px;
$font-size-large-x: 22px;
2.src/commonJS/dom.js
export function addClass (el, className) {
if (hasClass(el, className)) {
return
}
let newClass = el.className.split(' ')
newClass.push(className)
el.className = newClass.join(' ')
}
export function hasClass (el, className) {
let reg = new RegExp('(^|\\s)' + className + '(\\s|$)')
return reg.test(el.className)
}
export function getData (el, name, val) {
const prefix = 'data-'
name = prefix + name
if (val) {
// 如果有 val 就添加这个 val 到 dom 中
// name="val"
return el.setAttribute(name, val)
} else {
// 没有 val ,就获取 dom 中的 name
return el.getAttribute(name)
}
}
// 能力检测
let elementStyle = document.createElement('div').style
let vendor = (() => {
// 定义游览器前缀
let transformNames = {
webkit: 'webkitTransform',
Moz: 'MozTransform',
O: 'OTransform',
ms: 'msTransform',
standard: 'transform'
}
// 遍历前缀,如果游览器支持的话,就返回对应 key
for (let key in transformNames) {
if (elementStyle[transformNames[key]] !== undefined) {
return key
}
}
// 如果都不支持,那肯定是有问题的,返回 false
return false
})()
export function prefixStyle (style) {
if (vendor === false) {
return false
}
// 如果 vendor 为标准,就不改变 style
if (vendor === 'standard') {
return style
}
// 否则返回 vender(也就是 webkit Moz O ms 中的一个) + 样式首字母大写
// 例如:webkit + transform ---> webkitTransform
return vendor + style.charAt(0).toUpperCase() + style.substr(1)
}
3.components/common/progress-bar.vue
<template>
<div class="progress-bar" ref="progressBar" @click="progressClick">
<div class="bar-inner">
<div class="progress" ref="progress"></div>
<div class="progress-btn-wrapper" ref="progressBtn"
@touchstart.prevent="progressTouchStart"
@touchmove.prevent="progressTouchMove"
@touchend.prevent="progressTouchEnd">
<div class="progress-btn">
<div class="inner-play-btn"></div>
</div>
</div>
</div>
</div>
</template>
<script>
import {prefixStyle} from '../../commonJS/dom'
const progressBtnWidth = 16
const transform = prefixStyle('transform')
export default {
data () {
return {
newPercent: 0
}
},
props: {
percent: {
type: Number,
default: 0
}
},
created () {
this.touch = {}
},
methods: {
progressClick (e) {
// this._offset(e.offsetX)
const rect = this.$refs.progressBar.getBoundingClientRect()
// rect.left 元素距离左边的距离
// e.pageX 点击距离左边的距离
const offsetWidth = e.pageX - rect.left
// console.log(rect, e.pageX)
this._offset(offsetWidth)
const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
const percent = this.$refs.progress.clientWidth / barWidth
this.$emit('percentChangeEnd', percent)
},
progressTouchStart (e) {
this.touch.initiated = true
this.touch.startX = e.touches[0].pageX
this.touch.left = this.$refs.progress.clientWidth
},
progressTouchMove (e) {
if (!this.touch.initiated) {
return
}
this._triggerPercent()
const deltaX = e.touches[0].pageX - this.touch.startX
const offsetWidth = Math.min(Math.min(this.$refs.progressBar.clientWidth - progressBtnWidth, Math.max(0, this.touch.left + deltaX)))
this._offset(offsetWidth)
},
progressTouchEnd (e) {
this.touch.initiated = false
const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
const percent = this.$refs.progress.clientWidth / barWidth
this.$emit('percentChangeEnd', percent)
},
_triggerPercent () {
const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
const percent = this.$refs.progress.clientWidth / barWidth
this.$emit('percentChange', percent)
},
_offset (offsetWidth) {
this.$refs.progress.style.width = `${offsetWidth}px`
this.$refs.progressBtn.style[transform] = `translate3d(${offsetWidth}px, 0, 0)`
}
},
watch: {
percent (newPercent) {
if (newPercent >= 0 && !this.touch.initiated) {
const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
const offsetWidth = newPercent * barWidth
this._offset(offsetWidth)
}
}
}
}
</script>
<style scoped lang="scss">
@import "../../../public/css/variable";
.progress-bar {
height: 20px;
.bar-inner {
position: relative;
top: 10px;
height: 4px;
background: rgba(0, 0, 0, 0.3);
.progress {
position: absolute;
height: 100%;
background: $color-theme;
}
.progress-btn-wrapper {
position: absolute;
left: -8px;
top: -13px;
width: 30px;
height: 30px;
.progress-btn {
position: relative;
top: 7px;
left: 7px;
box-sizing: border-box;
width: 15px;
height: 15px;
border: 4px solid $color-theme-l;
border-radius: 50%;
.inner-play-btn{
position: absolute;
top: -1px;
left: -1px;
height: 9px;
width: 9px;
border-radius: 50%;
background: $color-theme;
}
}
}
}
}
</style>
4.use.vue
<style lang="scss" scoped>
.evening-broadcasting{
background: #f7f7f7;
padding: 10px 14px;
.broadcasting{
background: #fff;
padding: 11px 14px 18px 15.5px;
.play-box{
border-radius: 50%;
width: 42px;
height: 42px;
margin-top: 15px;
.play-button{
width: 42px;
height: 42px;
}
}
.play-content{
box-sizing: border-box;
padding-left: 19px;
width: 270px;
overflow: hidden;
.play-date{
font-size: 16px;
}
.play-title{
font-size: 12px;
color: #999999;
padding-top: 2px;
}
.play-control{
width: 270px;
#play-audio{
width: 250px;
}
.timingLength{
width: 250px;
.time-l{
font-size: 11px;
color:#666;
}
.time-r{
font-size: 11px;
color:#999;
}
}
}
}
}
}
</style>
<template>
<div class="evening-broadcasting">
<div class="broadcasting clearfix">
<div class="play-box left" @click="transPlayStatus">
<img src="../../components/common/image/播放.png" class="play-button" @touchstart="play" v-if="!isPlay">
<img src="../../components/common/image/暂停.png" class="play-button" @touchstart="pause" v-else>
</div>
<div class="play-content left">
<div class="play-date">
{{nowDate|fomatTime2}}
</div>
<div class="play-title ">
晚间播报
</div>
<div class="play-control">
<audio id="audio" :src="audioUrl" ref="audio" @timeupdate="updateTime">该浏览器不支持audio属性</audio>
<progress-bar id="play-audio" :percent="percent" @percentChangeEnd="percentChangeEnd" @percentChange="percentChange"></progress-bar>
<div class="clearfix timingLength">
<span class="time time-l left" v-if="timeLoading">{{format(currentTime)}}</span>
<span class="time time-l left" v-else>-:--</span>
<span class="time time-r right" v-if="timeLoading">{{format(duration)}}</span>
<span class="time time-r right" v-else>-:--</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import ProgressBar from '../../components/common/progress-bar'
export default {
data() {
return {
nowDate:this.$route.params.nowDate,
userid:this.$route.params.userid,
playStatus:true,
audioUrl:'test.mp3',
isPlay: false, // 是否播放
width: 0, // 视频音频的总时间的长度条
percent: 0,
currentTime: 0,// 播放时间
duration: 0,// 视频音频的总时长
playing: false,
timeLoading:true
};
},
components: {
ProgressBar,
},
watch: {
currentTime () {
this.percent = this.currentTime / this.duration
}
},
methods: {
format (interval) {
interval = interval | 0
let minute = interval / 60 | 0
let second = interval % 60
if (second < 10) {
second = '0' + second
}
return minute + ':' + second
},
percentChange (percent) {
this.move = true
const currentTime = this.duration * percent
this.currentTime = currentTime
},
percentChangeEnd (percent) {
this.move = false
const currentTime = this.duration * percent
this.$refs.audio.currentTime = currentTime
if (!this.playing) {
this.$refs.audio.play()
this.playing=true;
}
},
updateTime (e) {
if (this.move) {
return
}
this.currentTime = e.target.currentTime;
if (this.audio.ended) {
this.isPlay = false
}
},
transPlayStatus(){
this.playStatus=!this.playStatus;
},
// 播放
play () {
if(this.currentTime==0){
var u = navigator.userAgent;
if (!!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) {
this.audio.load()
this.timeLoading=false;
setTimeout(() => {
this.timeLoading=true;
}, 2000);
this.audio.play()
this.isPlay = true
}
if (u.indexOf("Android") > -1 || u.indexOf("Adr") > -1) {
this.audio.load()
this.timeLoading=false;
this.isPlay = true
setTimeout(() => {
this.timeLoading=true;
this.audio.play()
}, 2000);
}
}else{
this.isPlay = true;
this.audio.currentTime = this.currentTime;//重新播放
this.audio.play();
}
},
// 暂停
pause () {
this.audio.pause()
this.isPlay = false
},
},
created(){
this.move = false;
//加载屏关闭
setTimeout(() => {
document.getElementById('login').style.display = 'none';
}, 250);
},
mounted(){
this.audio = this.$refs.audio
this.duration = 95 //后台给时长
},
}
</script>