4.qq音乐练习3 进度条

"Hello World, Hello Blog"

Posted by wudimingwo on December 15, 2018

step1 更新alltime功能 pro.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 进度条模块

(function ($,root) {
	// 渲染总时间 根据 duration
	
	function renderalltime (time) {
		$body = $(document.body);
		time = format(time);
		$body.find('.all-time').html(time);
		
	}
	// 转换时间格式
	function format (time) {
		var m = parseInt(time/60);
		var s = time%60;
		m = ('0' + m).slice(-2); 
		s = ('0' + s).slice(-2); 
		return (m + ':' + s);
		
	}
	
	root.pro = {
	  renderalltime,
	}
	
})(window.Zepto ,window.player || (window.player = {}));

step2 渲染 播放计时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 进度条模块

(function ($,root) {
	// 渲染总时间 根据 duration
	var duration;
	var $body = $(document.body);
	var frameId;
	var lastper = 0;
	var starttime;
	function renderalltime (time) {
	  duration = time;
		time = format(time);
		$body.find('.all-time').html(time);
	}
	// 转换时间格式
	function format (time) {
	  time = Math.round(time);
		var m = Math.round(time/60);
		var s = time%60;
		m = ('0' + m).slice(-2); 
		s = ('0' + s).slice(-2); 
		return (m + ':' + s);
		
	}
	
	function start () {
		starttime = new Date().getTime();
		function frame () {
			var currentTime = new Date().getTime();
			var percent = lastper + (currentTime - starttime) / (duration * 1000);
//			console.log(lastper);
			update(percent);
			frameId = requestAnimationFrame(frame);
		}
		frame();
		
	}
	
	function stop () {
	  cancelAnimationFrame(frameId);
	  var stoptime = new Date().getTime();
	  console.log(stoptime - starttime);
	  lastper += (stoptime - starttime) / (duration * 1000);
	}
	
	function update (p) {
		var time = p * duration;
		time = format(time);
		$body.find('.current-time').html(time);
	}
	
	
	
	root.pro = {
	  renderalltime,
	  start,
	  update,
	  stop,
	}
	
})(window.Zepto ,window.player || (window.player = {}));

step3 控制条 样式部分 index.less

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.pro-wrap{
                    flex: 1;
                    position: relative;
                    overflow: hidden;
                    >div{// 这是坑, 如果不加这个默认后代都会被设上.以前没注意.
                        position: absolute;
                        width: 100%;
                        height: 2px;
                        left: 0;
                        right: 0;
                        top: 0;
                        bottom: 0;
                        margin: auto;
                    }
                    .pro-bottom{
                        background-color: rgba(200,200,200,0.8);
                    }
                    .pro-top{
                        background-color: rgba(240,240,240,1);
                        height: 3px;
                        transform: translateX(-100%);
                        .slider{
                            position: absolute;
                            width: 15px;
                            height: 15px;
                            border-radius: 50%;
                            right: -15px;
                            top: 0;
                            bottom: 0;
                            margin: auto;
                            background-color: #fff;
                        }
                    }
                }

pro.js

1
2
3
4
5
6
7
8
9
	function update (p) {
		var time = p * duration;
		time = format(time);
		$body.find('.current-time').html(time);
		var pX = (p - 1) * 100 + "%";
		$body.find(".pro-top").css({
		  'transform' : 'translateX(' + pX +')'
		})
	}

step4 pro.js 实现拖拽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 进度条模块

(function ($,root) {
	// 渲染总时间 根据 duration
	var duration;
	var $body = $(document.body);
	var frameId;
	var lastper = 0;
	var starttime;
	function renderalltime (time) {
	  duration = time;
		time = format(time);
		lastper = 0;
		starttime = 0;
		$body.find('.all-time').html(time);
	}
	// 转换时间格式
	function format (time) {
	  time = Math.round(time);
		var m = Math.round(time/60);
		var s = time%60;
		m = ('0' + m).slice(-2); 
		s = ('0' + s).slice(-2); 
		return (m + ':' + s);
		
	}
	
	function start (per) {
		lastper = per == undefined ? lastper : per;
	  cancelAnimationFrame(frameId);
	  starttime = new Date().getTime();
		function frame () {
			var currentTime = new Date().getTime();
			var percent = lastper + (currentTime - starttime) / (duration * 1000);
//			console.log(lastper);
			update(percent);
			frameId = requestAnimationFrame(frame);
		}
		frame();
		
	}
	
	function stop () {
	  cancelAnimationFrame(frameId);
	  var stoptime = new Date().getTime();
	  console.log(stoptime - starttime);
	  lastper += (stoptime - starttime) / (duration * 1000);
	}
	
	function update (p) {
		var time = p * duration;
		time = format(time);
		$body.find('.current-time').html(time);
		var pX = (p - 1) * 100 + "%";
		$body.find(".pro-top").css({
		  'transform' : 'translateX(' + pX +')'
		})
	}
	
	
	
	root.pro = {
	  renderalltime,
	  start,
	  update,
	  stop,
	}
	
})(window.Zepto ,window.player || (window.player = {}));

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
var root = window.player;
//var nowIndex = 0;
var dataLength = null;
var dataclone;
var url = '../mock/data.json';

var audio = root.audioManager;

var control;

var timer;
var duration = 0;

root.gaussBlur = gaussBlur;

function getData(url) {
  $.ajax({
    type: "GET",
    url: url,
    async: true,
    success: function(data) {
      console.log(data[2]);
      dataLength = data.length;
      dataclone = data;
      control = new root.controlIndex(dataLength);
      var i = control.index;
      root.render(data[i]);
      audio.getAudio(data[i].audio);
      duration = dataclone[i].duration;
      root.pro.renderalltime(duration);
      audio.audio.onloadedmetadata = function () {
        console.log(audio.audio.duration);
      }
      bindEvent();
    },
    error: function() {
      console.log("error");
    }
  });
}

function bindEvent() {

  $("body").on("play:change", function(e, index) {

    audio.getAudio(dataclone[index].audio);
    audio.play();
    $(".icon-PLAY").removeClass('icon-PLAY').addClass('icon-stop');
    root.render(dataclone[index]);
    rotate();
    root.pro.renderalltime(dataclone[index].duration);
    $(".img-box").css({
      'transform': 'rotateZ(0deg)',
      'transition': 'none'
    });
  })

  $(".pre").on('click', function() {
    var i = control.pre();
    $("body").trigger("play:change", i);
    root.pro.start();
  });
  $(".next").on('click', function() {
    var i = control.next();
    $("body").trigger("play:change", i);
    root.pro.start();
  });

  $(".play").on('click', function() {
    // 图案变成 暂停
    // 音乐停止播放
    // 图片停止旋转.

    if(audio.state == 'play') {
      $(".icon-stop").removeClass('icon-stop').addClass('icon-PLAY');
      audio.pause();
      //    var reg = /\d+/g;
      //    var deg = $(".img-box").css('transform').match(reg)[0];
      //    $(".img-box").attr('data-deg',deg);
      root.pro.stop();
      clearInterval(timer);
    } else if(audio.state == 'pause') {
      $(".icon-PLAY").removeClass('icon-PLAY').addClass('icon-stop');
      audio.play();
      root.pro.start();
      rotate();
    }

  })
}

function bindTouch() {
    var $body = $(document.body);
    var $slider = $body.find('.slider');
    var offset = $slider.offset();
    var left = offset.left;
    var width = $slider.parent().offset().width;
	$slider.on("touchstart",function (e) {
		root.pro.stop();
	}).on("touchmove",function (e) {
		var x = e.changedTouches[0].clientX;
		var per = (x - left) / width;
		// 需要存进去.
		console.log(per,duration,per*duration);
		if (per < 1 && per > 0) {
		  root.pro.update(per);
		}
		
	}).on("touchend",function (e) {
		var x = e.changedTouches[0].clientX;
    var per = (x - left) / width;
    if (per < 1 && per > 0) {
      audio.playTo(duration * per);
      root.pro.start(per);
    }
	})
}

bindTouch();

function rotate() {
  clearInterval(timer);
  //  var deg = Number($(".img-box").attr('data-deg')) || 0;
  var deg = 0;
  timer = setInterval(function() {
    deg += 2;
    $(".img-box").css({
      'transform': 'rotateZ(' + deg + 'deg)',
      'transition': 'transform .2s ease-in-out'
    });
  }, 200);
}

getData("../mock/data.json");

拖拽 到达临界点的时候有问题. 而且会出现数值超过all-time的情况 image.png 这个问题出在 format 时间转换中

1
2
3
不能是    
var m = Math.round(time / 60);
    var m = Math.floor(time / 60);

还有一个问题是, 这个计算不准的原因,可能是我拖动所求的百分比有问题. 因为样式部分的设置,视频里没有交代, 所以这部分可能有所出入, 可以稍微改一下求百分比的方式.

pro.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 进度条模块

(function($, root) {
  // 渲染总时间 根据 duration
  var duration;
  var $body = $(document.body);
  var frameId;
  var lastper = 0;
  var starttime;

  function renderalltime(time) {
    duration = time;
    time = format(time);
    lastper = 0;
    starttime = 0;
    $body.find('.all-time').html(time);
  }
  // 转换时间格式
  function format(time) {
    time = Math.round(time);
    var m = Math.floor(time / 60);
    var s = time % 60;
    m = ('0' + m).slice(-2);
    s = ('0' + s).slice(-2);
    return(m + ':' + s);

  }

  function start(per) {
    lastper = per == undefined ? lastper : per;
    cancelAnimationFrame(frameId);
    starttime = new Date().getTime();

    function frame() {
      var currentTime = new Date().getTime();
      var percent = lastper + (currentTime - starttime) / (duration * 1000);
      update(percent);
      frameId = requestAnimationFrame(frame);
      if(percent >= 1) {
        percent = 0;
        lastper = 0;
        update(0);
      }
    }
    frame();

  }

  function stop() {
    cancelAnimationFrame(frameId);
    var stoptime = new Date().getTime();
    console.log(stoptime - starttime);
    lastper += (stoptime - starttime) / (duration * 1000);
  }

  function update(p) {
    var time = p * duration;
    time = format(time);
    $body.find('.current-time').html(time);
    var pX = (p - 1) * 100 + "%";
    $body.find(".pro-top").css({
      'transform': 'translateX(' + pX + ')'
    })
  }

  root.pro = {
    renderalltime,
    start,
    update,
    stop,
  }

})(window.Zepto, window.player || (window.player = {}));

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
var root = window.player;
//var nowIndex = 0;
var dataLength = null;
var dataclone;
var url = '../mock/data.json';

var audio = root.audioManager;

var control;

var timer;
var duration = 0;

root.gaussBlur = gaussBlur;

function getData(url) {
  $.ajax({
    type: "GET",
    url: url,
    async: true,
    success: function(data) {
      console.log(data[2]);
      dataLength = data.length;
      dataclone = data;
      control = new root.controlIndex(dataLength);
      var i = control.index;
      root.render(data[i]);
      audio.getAudio(data[i].audio);
      duration = dataclone[i].duration;
      root.pro.renderalltime(duration);
      audio.audio.onloadedmetadata = function() {
        console.log(audio.audio.duration);
      }
      bindEvent();
    },
    error: function() {
      console.log("error");
    }
  });
}

function bindEvent() {

  $("body").on("play:change", function(e, index) {

    audio.getAudio(dataclone[index].audio);
    audio.play();
    $(".icon-PLAY").removeClass('icon-PLAY').addClass('icon-stop');
    root.render(dataclone[index]);
    rotate();
    root.pro.renderalltime(dataclone[index].duration);
    $(".img-box").css({
      'transform': 'rotateZ(0deg)',
      'transition': 'none'
    });
  })

  $(".pre").on('click', function() {
    var i = control.pre();
    $("body").trigger("play:change", i);
    root.pro.start();
  });
  $(".next").on('click', function() {
    var i = control.next();
    $("body").trigger("play:change", i);
    root.pro.start();
  });

  $(".play").on('click', function() {
    // 图案变成 暂停
    // 音乐停止播放
    // 图片停止旋转.

    if(audio.state == 'play') {
      $(".icon-stop").removeClass('icon-stop').addClass('icon-PLAY');
      audio.pause();
      //    var reg = /\d+/g;
      //    var deg = $(".img-box").css('transform').match(reg)[0];
      //    $(".img-box").attr('data-deg',deg);
      root.pro.stop();
      clearInterval(timer);
    } else if(audio.state == 'pause') {
      $(".icon-PLAY").removeClass('icon-PLAY').addClass('icon-stop');
      audio.play();
      root.pro.start();
      rotate();
    }

  })
}

function bindTouch() {
  var $body = $(document.body);
  var $slider = $body.find('.slider');
  var offset = $slider.parent().offset();
  var left = $slider.offset().left;
  var width = offset.width;
  var length;
  $slider.on("touchstart", function(e) {
    root.pro.stop();
  }).on("touchmove", function(e) {
    length = e.changedTouches[0].clientX - left;
    var per = length / width;
    // 需要存进去.
    if(per < 1 && per > 0) {
      root.pro.update(per);
    }

  }).on("touchend", function(e) {
    length = e.changedTouches[0].clientX - left;
    var per = length / width;
    if(per < 1 && per > 0) {
      audio.playTo(duration * per);
      root.pro.start(per);
    }else if (per >= 1) {
    	audio.playTo(duration);
      root.pro.start(per);
    }else if (per <= 0){
      audio.playTo(0);
      root.pro.start(0);
    }
  })
}

bindTouch();

function rotate() {
  clearInterval(timer);
  //  var deg = Number($(".img-box").attr('data-deg')) || 0;
  var deg = 0;
  timer = setInterval(function() {
    deg += 2;
    $(".img-box").css({
      'transform': 'rotateZ(' + deg + 'deg)',
      'transition': 'transform .2s ease-in-out'
    });
  }, 200);
}

getData("../mock/data.json");

开始跟着写这个之前,感觉会非常的简单. 可是写到越往后的时候,就觉得越复杂. 比如知道 写这个control之前都很简单, 单写这一个control也很简单, 但在之前的基础之上, 再写这个control的时候, 就感觉有点复杂. 为什么会复杂呢?