├── .gitattributes ├── .gitignore ├── README.md ├── config.rb ├── index.html ├── lib ├── wx-audio.css └── wx-audio.js ├── package-lock.json ├── package.json ├── src ├── assets │ ├── pause.png │ └── playing.gif ├── index.js ├── lib │ ├── wx-audio.js │ └── wx-audio.less └── style.less ├── tea.yaml ├── webpack.config.js └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=javascript 2 | *.css linguist-language=javascript 3 | *.html linguist-language=javascript 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wx-audio 2 | 微信公众号音乐播放器 3 | 4 | #### 基于原生js写的一款仿微信公众号的音乐组件 5 | 6 | ## 演示地址 7 | http://www.daiwei.org/components/wx-audio/ 8 | 9 | ## 手机预览 10 | 11 | ### 安装 12 | npm 安装 13 | ```js 14 | npm install @dw/wx-audio 15 | ``` 16 | 17 | ### 引入 18 | ```js 19 | import WxAudio from '@dw/wx-audio/lib/wx-audio.css' 20 | import WxAudio from '@dw/wx-audio' 21 | ``` 22 | 23 | 普通资源引入,先将lib文件下的目录放到自己的项目中,然后根据路径引入 24 | ```html 25 | 26 | 27 | ``` 28 | 29 | ### 实例化 音乐组件 30 | ```js 31 | var wxAudio = new WxAudio({ 32 | ele: '#textaudio1', 33 | title: '河山大好', 34 | disc: '许嵩', 35 | src: 'http://oiq8j9er1.bkt.clouddn.com/%E8%AE%B8%E5%B5%A9%20-%20%E6%B2%B3%E5%B1%B1%E5%A4%A7%E5%A5%BD1.mp3', 36 | width: '320px', 37 | autoplay: true, 38 | loop: true, 39 | ended: function () { 40 | alert('播放结束') 41 | } 42 | }); 43 | ``` 44 | 45 | ### 属性 46 | - ele dom对象 47 | - title 音乐标题 48 | - disc 描述,可以当做显示歌手名称 49 | - src 地址 50 | - width 显示的宽度 51 | - loop 是否循环(当循环状态下时候,ended事件不会执行) 52 | - ended 方法,是一个回调,可在音乐播放结束之后执行其他的代码 53 | - autoplay 属性, 是否自动播放,这个只能在微信浏览器以及只设置静态src才能自动播放 54 | ### 方法 55 | ```js 56 |  // 实例化的wxAudio可以这样操作 57 | wxAudio.audioPlay()   // 播放 58 | 59 | wxAudio.audioPause()   // 暂停 60 | 61 | wxAudio.audioPlayPause() // 播放暂停 62 | 63 | wxAudio.showLoading(bool) //显示加载状态  参数bool 64 |   65 | wxAudio.audioCut(src,title,disc) 实现音频切换的效果 66 | ``` 67 | 68 | ### 新增 音乐组件切歌方法 69 | 通过实例化的wxAudio的audioCut(src,title,disc) 实现音频切换的效果  示例代码如下 70 | ```js 71 | var src = 'http://oiq8j9er1.bkt.clouddn.com/%E6%9E%97%E4%BF%8A%E6%9D%B0%20-%20%E5%A5%B9%E8%AF%B41.mp3' 72 | var title = '她说' 73 | var disc = '林俊杰' 74 | wxAudio.audioCut(src, title, disc) 75 | ``` 76 | -------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | require 'compass/import-once/activate' 2 | # Require any additional compass plugins here. 3 | 4 | # Set this to the root of your project when deployed: 5 | http_path = "/" 6 | css_dir = "css" 7 | sass_dir = "sass" 8 | images_dir = "images" 9 | javascripts_dir = "js" 10 | 11 | # You can select your preferred output style here (can be overridden via the command line): 12 | # output_style = :expanded or :nested or :compact or :compressed 13 | 14 | # To enable relative paths to assets via compass helper functions. Uncomment: 15 | # relative_assets = true 16 | 17 | # To disable debugging comments that display the original location of your selectors. Uncomment: 18 | # line_comments = false 19 | 20 | 21 | # If you prefer the indented syntax, you might want to regenerate this 22 | # project again passing --syntax sass, or you can uncomment this: 23 | # preferred_syntax = :sass 24 | # and then run: 25 | # sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass 26 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Wx-audio 6 | 8 | 9 | 10 |

es6 wx-audio

11 |
12 |
播放
13 |
暂停
14 |
切歌
15 | 16 | -------------------------------------------------------------------------------- /lib/wx-audio.css: -------------------------------------------------------------------------------- 1 | @keyframes slidein { 2 | 0% { 3 | -webkit-transform: translateX(-50%); 4 | -moz-transform: translateX(-50%); 5 | -ms-transform: translateX(-50%); 6 | -o-transform: translateX(-50%); 7 | transform: translateX(-50%); 8 | } 9 | 100% { 10 | -webkit-transform: translateX(0); 11 | -moz-transform: translateX(0); 12 | -ms-transform: translateX(0); 13 | -o-transform: translateX(0); 14 | transform: translateX(0); 15 | } 16 | } 17 | .wx-audio-content { 18 | user-select: none; 19 | width: 100%; 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | min-height: auto; 24 | padding: 8px 12px; 25 | border: 1px solid #efefef; 26 | margin: 0 auto; 27 | font-size: 0; 28 | box-sizing: border-box; 29 | font-family: 'PingFangSC-Regular'; 30 | -webkit-tap-highlight-color: transparent; 31 | background: #fdfdfd; 32 | } 33 | .wx-audio-content p { 34 | margin: 0; 35 | } 36 | .wx-audio-content .wx-audio-info { 37 | display: none; 38 | } 39 | .wx-audio-content .wx-audio-left { 40 | display: inline-block; 41 | width: 42px; 42 | height: 100%; 43 | } 44 | .wx-audio-content .wx-audio-left .wx-audio-state { 45 | width: 100%; 46 | height: 100%; 47 | } 48 | .wx-audio-content .wx-audio-right { 49 | display: inline-block; 50 | width: calc(100% - 42px); 51 | font-size: 16px; 52 | box-sizing: border-box; 53 | padding-left: 10px; 54 | } 55 | .wx-audio-content .wx-audio-right .wx-audio-title { 56 | padding-bottom: 6px; 57 | width: 100%; 58 | font-size: 16px; 59 | font-weight: 400; 60 | text-overflow: ellipsis; 61 | overflow: hidden; 62 | white-space: nowrap; 63 | } 64 | .wx-audio-content .wx-audio-right .wx-audio-disc { 65 | width: 100%; 66 | text-overflow: ellipsis; 67 | overflow: hidden; 68 | white-space: nowrap; 69 | padding-bottom: 10px; 70 | font-size: 12px; 71 | color: #8c8c8c; 72 | } 73 | .wx-audio-content .wx-audio-right .wx-audio-progrees { 74 | height: 2px; 75 | width: calc(100% - 4px); 76 | position: relative; 77 | } 78 | .wx-audio-content .wx-audio-right .wx-audio-progrees .wx-progrees-detail { 79 | height: 100%; 80 | width: 100%; 81 | background: #ebebeb; 82 | position: relative; 83 | cursor: pointer; 84 | } 85 | .wx-audio-content .wx-audio-right .wx-audio-progrees .wx-progrees-detail .wx-voice-p { 86 | width: 0%; 87 | position: absolute; 88 | top: 0; 89 | bottom: 0; 90 | left: 0; 91 | right: 0; 92 | overflow: hidden; 93 | background: #09bb07; 94 | z-index: 2; 95 | } 96 | .wx-audio-content .wx-audio-right .wx-audio-progrees .wx-progrees-detail .wx-buffer-p { 97 | width: 0%; 98 | position: absolute; 99 | top: 0; 100 | bottom: 0; 101 | left: 0; 102 | right: 0; 103 | overflow: hidden; 104 | background: #d9d9d9; 105 | z-index: 1; 106 | } 107 | .wx-audio-content .wx-audio-right .wx-audio-progrees .wx-progrees-detail .wx-loading { 108 | display: none; 109 | position: absolute; 110 | top: 0; 111 | bottom: 0; 112 | left: 0; 113 | right: 0; 114 | overflow: hidden; 115 | } 116 | .wx-audio-content .wx-audio-right .wx-audio-progrees .wx-progrees-detail .wx-loading .wx-loading-wrapper { 117 | position: absolute; 118 | top: 0; 119 | bottom: 0; 120 | left: 0; 121 | animation: slidein 6s linear infinite normal; 122 | -webkit-animation: slidein 6s linear infinite normal; 123 | -moz-animation: slidein 6s linear infinite normal; 124 | width: 200%; 125 | max-width: none!important; 126 | background-image: -owg-repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 127 | background-image: -webkit-repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 128 | background-image: -moz-repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 129 | background-image: -o-repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 130 | background-image: repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 131 | } 132 | .wx-audio-content .wx-audio-right .wx-audio-progrees .wx-audio-origin { 133 | width: 6px; 134 | height: 6px; 135 | margin-top: -3px; 136 | margin-left: 0; 137 | border-radius: 50%; 138 | -moz-border-radius: 50%; 139 | -webkit-border-radius: 50%; 140 | background-color: #09bb07; 141 | position: absolute; 142 | left: 0; 143 | top: 50%; 144 | z-index: 2; 145 | } 146 | .wx-audio-content .wx-audio-right .wx-audio-progrees .wx-audio-origin:before { 147 | content: " "; 148 | display: block; 149 | position: absolute; 150 | width: 24px; 151 | height: 24px; 152 | border-radius: 50%; 153 | -moz-border-radius: 50%; 154 | -webkit-border-radius: 50%; 155 | background-image: radial-gradient(rgba(9, 187, 7, 0.3) 20%, transparent 40%); 156 | top: 50%; 157 | margin-top: -12px; 158 | margin-left: -9px; 159 | cursor: pointer; 160 | outline: 0; 161 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 162 | } 163 | .wx-audio-content .wx-audio-right .wx-audio-time { 164 | width: 100%; 165 | padding-top: 6px; 166 | height: auto; 167 | display: flex; 168 | align-items: center; 169 | justify-content: space-between; 170 | overflow: hidden; 171 | } 172 | .wx-audio-content .wx-audio-right .wx-audio-time span { 173 | font-size: 12px; 174 | color: #8c8c8c; 175 | } 176 | -------------------------------------------------------------------------------- /lib/wx-audio.js: -------------------------------------------------------------------------------- 1 | var WxAudio=function(i){var t={};function e(A){if(t[A])return t[A].exports;var o=t[A]={i:A,l:!1,exports:{}};return i[A].call(o.exports,o,o.exports,e),o.l=!0,o.exports}return e.m=i,e.c=t,e.d=function(i,t,A){e.o(i,t)||Object.defineProperty(i,t,{enumerable:!0,get:A})},e.r=function(i){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(i,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(i,"__esModule",{value:!0})},e.t=function(i,t){if(1&t&&(i=e(i)),8&t)return i;if(4&t&&"object"==typeof i&&i&&i.__esModule)return i;var A=Object.create(null);if(e.r(A),Object.defineProperty(A,"default",{enumerable:!0,value:i}),2&t&&"string"!=typeof i)for(var o in i)e.d(A,o,function(t){return i[t]}.bind(null,o));return A},e.n=function(i){var t=i&&i.__esModule?function(){return i.default}:function(){return i};return e.d(t,"a",t),t},e.o=function(i,t){return Object.prototype.hasOwnProperty.call(i,t)},e.p="",e(e.s=0)}([function(i,t,e){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var A=function(){function i(i,t){for(var e=0;e0){for(var t=0,e=0;ei.durationT&&(t=i.durationT,i.showLoading(!1),console.log("缓冲完成"));var A=Math.floor(t/i.durationT*100);i.wxBufferP.style.width=A+"%"}var o=new Date;i.wxAudio.paused||(i.reduceTAfter=Date.parse(o)-Math.floor(1e3*i.currentT),i.reduceTAfter-i.reduceTBefore>1e3?i.showLoading(!0):i.showLoading(!1))},i.wxAudio.onended=function(){i.opt.ended()},i.wxAudio.ontimeupdate=function(){var t=new Date;i.isDrag||(i.currentT=i.wxAudio.currentTime,i.currentP=Number(i.wxAudio.currentTime/i.durationT*100),i.reduceTBefore=Date.parse(t)-Math.floor(1e3*i.currentT),i.currentP=i.currentP>100?100:i.currentP,i.wxVoiceP.style.width=i.currentP+"%",i.wxAudioOrigin.style.left=i.currentP+"%",i.wxAudioCurrent.innerText=i.formartTime(i.wxAudio.currentTime),i.showLoading(!1))},i.wxAudioStateImg.onclick=function(){i.audioPlayPause()},i.wxAudioOrigin.onmousedown=function(t){i.isDrag=!0;var e=(t||window.event).clientX,A=t.target.offsetLeft;i.maxProgressWidth=i.wxAudioDetail.offsetWidth,i.wxAudioC.onmousemove=function(t){if(i.isDrag){var o=(t||window.event).clientX;i.dragProgressTo=Math.min(i.maxProgressWidth,Math.max(0,A+(o-e))),i.updatePorgress()}},i.wxAudioC.onmouseup=function(){i.isDrag&&(i.isDrag=!1,i.wxAudio.currentTime=Math.floor(i.dragProgressTo/i.maxProgressWidth*i.durationT))},i.wxAudioC.onmouseleave=function(){i.isDrag&&(i.isDrag=!1,i.wxAudio.currentTime=Math.floor(i.dragProgressTo/i.maxProgressWidth*i.durationT))}},i.wxAudioOrigin.ontouchstart=function(t){i.isDrag=!0;var e=t||window.event,A=e.touches[0].clientX,o=e.target.offsetLeft;i.maxProgressWidth=i.wxAudioDetail.offsetWidth,i.wxAudioC.ontouchmove=function(t){if(i.isDrag){var e=(t||window.event).touches[0].clientX;i.dragProgressTo=Math.min(i.maxProgressWidth,Math.max(0,o+(e-A))),i.updatePorgress()}},i.wxAudioC.ontouchend=function(){i.isDrag&&(i.isDrag=!1,i.wxAudio.currentTime=Math.floor(i.dragProgressTo/i.maxProgressWidth*i.durationT))}},i.wxAudioDetail.onclick=function(t){var e=(t||window.event).layerX,A=i.wxAudioDetail.offsetWidth;i.wxAudio.currentTime=Math.floor(e/A*i.durationT)}}},{key:"isWeiXin",value:function(){var i=window.navigator.userAgent.toLowerCase();return"micromessenger"===String(i.match(/MicroMessenger/i))}},{key:"updatePorgress",value:function(){this.wxAudioOrigin.style.left=this.dragProgressTo+"px",this.wxVoiceP.style.width=this.dragProgressTo+"px";var i=Math.floor(this.dragProgressTo/this.maxProgressWidth*this.durationT);this.wxAudioCurrent.innerText=this.formartTime(i)}},{key:"formartTime",value:function(i){var t=function(i){return(i=i.toString())[1]?i:"0"+i},e=Math.floor(i/60),A=Math.floor(i%60);return t(e)+":"+t(A)}}]),i}();t.default=r},function(i,t){i.exports="data:image/gif;base64,R0lGODlhVABUAPfJAButGiKwIe747m7Kbe/47/r8+vj7+J3bnB+vHqDcny20LByuG+j16Pz9/HvPeiOwIk/ATuT05FLBUTa3Np7bnTm4OCqzKdXv1ff79ySwI8Lowi+1Lj66Pb3mvdvx23nPeaTepMjqyLXktVzEW63hrTW2NEu+So7WjdLu0j66PrzmvKrgqn7QfeL04p/cnkm+SCiyJ7/nvmTHYyGwIPn8+fX69d7y3vb69iWxJE2/TPL58iuzKqzgrHjOeEW8RPT69PH58ZXYlNDtz4bThSyzK+337eb15mLGYdbv1mnJaW/Lb8bqxja3NeX15V3FXPD48GHGYfP689fw11HAUHzQe3fOd0q+STi4N8rrytPu01/FXz25PGzKa17FXez37CCvH6ngqaDcoOn26ODz3x6vHZLXkiaxJef150y/S+Hz4NDt0E/AT77nvrTjtJfZlnrPeje3N0K7QWvKaoXThLvmu8fqxmXHZIPSg5bZlavgq8/tz9zx3JzbnI/WjtHu0Ue9RkS8Q93y3ZTYk6LdovH58FfDV2DGYInUiX3QfIfThmfIZtnw2Dq4OZDXkLrlulDAUIzVi43VjG/LbsPpw/n7+XTNc1TBUx6uHcDnv3DLcDG1MN/y31/FXsjqx2jJaFPBUi60LS60LljDWHXNdGbIZTS2M6/hrnfOdke9R9Tv1FbCVWPHYkC6P1rEWbDir0a8RVXCVMnryYvVi4jUiMHowVnDWMvry+v36zO2Mqjfpx2uHGfIZyeyJsDowLHisZHXkZPYk7nluXbNddnw2fv8+4fUhzC1LxqtGf39/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo4NzEyYzBkMi03NGJlLTQ5MTEtYmQyMi1lNmI4ZTlhZmQ5ZGIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QkUzMTAyRkEyMjg0MTFFN0JDNzBCMEY5NjNCMDhDQjQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QkUzMTAyRjkyMjg0MTFFN0JDNzBCMEY5NjNCMDhDQjQiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4NzEyYzBkMi03NGJlLTQ5MTEtYmQyMi1lNmI4ZTlhZmQ5ZGIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODcxMmMwZDItNzRiZS00OTExLWJkMjItZTZiOGU5YWZkOWRiIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJ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"},function(i,t){i.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFQAAABUCAMAAAArteDzAAAAaVBMVEUAAAAarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRkarRlIa6J1AAAAInRSTlMA9wYa38QR7ZJnMK1IIqBsO3fXDbSGQudZz5fKpV0rfbpRlHIjYQAAA35JREFUWMPFWduyqjAMDS0tgtwEFBGv/P9Hntmh3cWDTYsMs/Oio3SRy0qapuCU7PXIRdUGQxCFncgfrwzWCb/l4TCTML/xbxFlIQariEJ+AZnkwUBKkCdLIZvBQ5olsPw61Uhc4vTOa4Ca39P4IqYWXH2dyw5mWXUs2ez/8liZVx6YD2bW6wXRzmpesov0U70HxW5azTBmpD1xqJW9uUzfaS0Lp1ms0Nru6Nfv9WPSi8lahT2BKoWyvARPKZUPhLRiduq9ckHaKds6y5pa6XmARXJQutaEP4MzLJTzyJfmk193I2YKiyUdUXcf+OnCdKPO+JqNvxO2kx4YNcr+c2jvjpE7Wv27W4uRS/C1jFEu3mpdhJyX34PWISY3ByNj/SxhhZRjfZ0UMkUJt3Bxx08rJU2xbFB16YEZDiG3JSy6sHlXNPbCHIbOVpHiN1VzjBLzKOCkmxjGKld6B4oNbjkiqi3rkJeBNN8jBj7SUEaxyGgnjE1OkS0mHkUAgd5X/qWF80mWR7PaOY0410GrnHHXVHpSqlZII521RzeXqtpkTkgEEitIiwF1YeLDJgQnIldbgAx5wMBj5z4br+aWB5GdGbxUxGjUp6ESLmxhJsaMFzx+Pi5+VIpN6bTUlcvPfw/InXlvjO5MjsdE/ucg6DjxRlEJY4Wb0J1IlnR0ZoXGEHF/6l1I68d+vj3ho9xH0mO+cjumNiMxvg/tTOWYcIAkqCl+XjRbtH7CHv4aCQrIQIui3TCxNPyN1BMXfhQFFxCgJ/yzmYAaTpGgEZpPoOq60GJctfkRaX5IBApRVTNTm/TvnYHqCEoh6kMzUCuNxnUUpVzkB/2+/Pc5iTpT5PdNUx78FrMT6kymqbugmEpxNZU4JXaph7v0GbOGxJQ3SZU+ryINSWT8iAt6skg7txPD1wCJN/rrQG0nZuNzo54nHQOnNj6zRTtRj5Pe5klu0d7NBGTThvFENhNE20NQS5BtD9GgUdQqyQZtaSuZ4bIr1fUGcmHTCz1SRpJNL9GeE3xNHe35/CDhRj04DhLzI48b9eI48mxxONvyGLn+wGtsLTY5mm87RFg/7jhNxh3bD2aANWtHSFsOu7Yfy60fIG4/6lw/lN14fOwedJdWXxKD7m1H8u7LAwZMZsn88mCDa46/v5DZ6OoIhcf7dg7Y7mPalb7XcVEwDEFU+V3H/QOplcP+ctPpgwAAAABJRU5ErkJggg=="},function(i,t){}]).default; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dw/wx-audio", 3 | "version": "1.0.7", 4 | "description": "wx-audio", 5 | "main": "src/lib/wx-audio.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "webpack --mode production", 9 | "build:publish": "webpack --mode production && npm version patch && npm publish", 10 | "dev": "webpack-dev-server --mode development --progress --colors", 11 | "watch": "webpack --progress --colors --watch", 12 | "publish": "npm publish --access=public" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://www.github.com/ifmiss/wx-audio.js" 17 | }, 18 | "files": [ 19 | "lib/", 20 | "src/lib", 21 | "src/assets", 22 | "README.md" 23 | ], 24 | "keywords": [ 25 | "audio", 26 | "wx", 27 | "we-audio", 28 | "wx-audio", 29 | "music" 30 | ], 31 | "author": "daiwei", 32 | "license": "ISC", 33 | "devDependencies": { 34 | "@dw/webpack-prompt-plugin": "^1.0.7", 35 | "axios": "^0.18.0", 36 | "babel-core": "^6.26.0", 37 | "babel-loader": "^7.1.4", 38 | "babel-polyfill": "^6.26.0", 39 | "babel-preset-env": "^1.6.1", 40 | "babel-preset-latest": "^6.24.1", 41 | "css-loader": "^0.28.10", 42 | "extract-text-webpack-plugin": "^4.0.0-beta.0", 43 | "html-webpack-plugin": "^3.0.6", 44 | "less": "^3.9.0", 45 | "less-loader": "^4.1.0", 46 | "style-loader": "^0.20.3", 47 | "url-loader": "^1.0.1", 48 | "url-parse": "^1.4.3", 49 | "webpack": "^4.1.1", 50 | "webpack-cli": "^3.3.1", 51 | "webpack-dev-server": "^3.1.1" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/assets/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IFmiss/wx-audio/8d99e43cbd2ab039983564045b0e3542518fac1d/src/assets/pause.png -------------------------------------------------------------------------------- /src/assets/playing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IFmiss/wx-audio/8d99e43cbd2ab039983564045b0e3542518fac1d/src/assets/playing.gif -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './style.less' 2 | import WxAudio from './lib/wx-audio.js'; 3 | 4 | import axios from 'axios' 5 | let index = 0 6 | let wx, music 7 | 8 | // axios.get('http://www.daiwei.org/vue/server/music.php?inAjax=1&do=playlist&id=2179377798').then((res) => { 9 | // music = res.data.playlist.tracks 10 | // index = Math.floor(Math.random() * music.length) 11 | // axios.get('http://www.daiwei.org/vue/server/music.php?inAjax=1&do=musicInfo&id=' + music[index].id).then((res) => { 12 | // wx = new WxAudio ({ 13 | // ele: '.wx-audio', 14 | // title: music[index].name, 15 | // disc: music[index].ar[0].name, 16 | // src: res.data.data[0].url, 17 | // width: '320px', 18 | // ended: function () { 19 | // index = Math.floor(Math.random() * music.length) 20 | // axios.get('http://www.daiwei.org/vue/server/music.php?inAjax=1&do=musicInfo&id=' + music[index].id).then((res) => { 21 | // console.log(music[index].ar[0].name) 22 | // var src = res.data.data[0].url 23 | // var title = music[index].name 24 | // var disc = music[index].ar[0].name 25 | // wx.audioCut(src, title, disc) 26 | // }, (err) => { 27 | // console.log(err) 28 | // }) 29 | // } 30 | // }) 31 | // }) 32 | // }, (err) => { 33 | // console.log(err) 34 | // }) 35 | wx = new WxAudio ({ 36 | ele: '.wx-audio', 37 | title: '111111', 38 | disc: '2222', 39 | src: 'http://m10.music.126.net/20190426110819/bdb6a025449d78de141a2c31a2330484/ymusic/cd1c/7825/d746/0dc64d2be36bfe20f55a401318b6080a.mp3', 40 | width: '320px', 41 | autoplay: true 42 | }) 43 | 44 | document.getElementById('play').onclick = function () { 45 | wx.audioPlay() 46 | } 47 | 48 | document.getElementById('pause').onclick = function () { 49 | wx.audioPause() 50 | } 51 | 52 | document.getElementById('cut').onclick = function () { 53 | index = Math.floor(Math.random() * music.length) 54 | axios.get('http://www.daiwei.org/vue/server/music.php?inAjax=1&do=musicInfo&id=' + music[index].id).then((res) => { 55 | console.log(music[index].ar[0].name) 56 | var src = res.data.data[0].url 57 | var title = music[index].name 58 | var disc = music[index].ar[0].name 59 | wx.audioCut(src, title, disc) 60 | }, (err) => { 61 | console.log(err) 62 | }) 63 | } 64 | -------------------------------------------------------------------------------- /src/lib/wx-audio.js: -------------------------------------------------------------------------------- 1 | import './wx-audio.less' 2 | const playImg = require('./../assets/playing.gif') 3 | const pauseImg = require('./../assets/pause.png') 4 | export default class WxAudio { 5 | constructor (tpl) { 6 | let defaultOptions = { 7 | ele: null, 8 | width: '320px', 9 | title: '这是一个测试title', 10 | src: '', 11 | disc: '这是一个测试disc', 12 | autoplay: false, 13 | // loop为true的时候不执行ended事件 14 | loop: true, 15 | ended: function () {} 16 | } 17 | this.opt = Object.assign({}, defaultOptions, tpl) 18 | // 判断传进来的是DOM还是字符串 19 | if (typeof this.opt.ele === 'string') { 20 | this.opt.ele = document.querySelector(this.opt.ele) 21 | } 22 | if (!this.opt.ele) return 23 | 24 | this.loading = false 25 | this.isDrag = false 26 | this.isplaying = false 27 | this.durationT = 0 28 | this.currentT = 0 29 | this.currentP = 0 30 | this.maxProgressWidth = 0 31 | this.dragProgressTo = 0 32 | 33 | // 通过时间戳与当前时间的差值来判断是否需要加载 34 | this.reduceTBefore = 0 // 时间戳与当前时间的差值 (初始化) 35 | this.reduceTAfter = 0 // 时间戳与当前时间的差值 (执行中) 36 | 37 | this.initDom(); 38 | } 39 | 40 | // 初始化元素 41 | initDom () { 42 | // content 43 | this.wxAudioC = document.createElement('div') 44 | this.wxAudioC.className = 'wx-audio-content' 45 | this.wxAudioC.style.width = this.opt.width 46 | this.opt.ele.appendChild(this.wxAudioC) 47 | 48 | // audio 49 | this.wxAudio = document.createElement('audio') 50 | this.wxAudio.className = 'wx-audio-content' 51 | this.wxAudio.src = this.opt.src 52 | if (this.opt.loop) this.wxAudio.setAttribute('loop', this.opt.loop) 53 | this.wxAudioC.appendChild(this.wxAudio) 54 | 55 | // left 56 | this.wxAudioL = document.createElement('div') 57 | this.wxAudioL.className = 'wx-audio-left' 58 | this.wxAudioC.appendChild(this.wxAudioL) 59 | 60 | // left image 61 | this.wxAudioStateImg = document.createElement('img') 62 | this.wxAudioStateImg.className = 'wx-audio-state' 63 | this.wxAudioStateImg.src = pauseImg 64 | this.wxAudioL.appendChild(this.wxAudioStateImg) 65 | 66 | // right 67 | this.wxAudioR = document.createElement('div') 68 | this.wxAudioR.className = 'wx-audio-right' 69 | this.wxAudioC.appendChild(this.wxAudioR) 70 | 71 | // right title 72 | this.wxAudioT = document.createElement('p') 73 | this.wxAudioT.className = 'wx-audio-title' 74 | this.wxAudioT.innerText = this.opt.title 75 | this.wxAudioR.appendChild(this.wxAudioT) 76 | 77 | // right disc 78 | this.wxAudioD = document.createElement('p') 79 | this.wxAudioD.className = 'wx-audio-disc' 80 | this.wxAudioD.innerText = this.opt.disc 81 | this.wxAudioR.appendChild(this.wxAudioD) 82 | 83 | // right progrees 84 | this.wxAudioP = document.createElement('div') 85 | this.wxAudioP.className = 'wx-audio-progrees' 86 | this.wxAudioR.appendChild(this.wxAudioP) 87 | 88 | // right progress detail 89 | this.wxAudioDetail = document.createElement('div') 90 | this.wxAudioDetail.className = 'wx-progrees-detail' 91 | this.wxAudioP.appendChild(this.wxAudioDetail) 92 | 93 | // voice p 94 | this.wxVoiceP = document.createElement('span') 95 | this.wxVoiceP.className = 'wx-voice-p' 96 | this.wxAudioDetail.appendChild(this.wxVoiceP) 97 | 98 | // buffer p 99 | this.wxBufferP = document.createElement('span') 100 | this.wxBufferP.className = 'wx-buffer-p' 101 | this.wxAudioDetail.appendChild(this.wxBufferP) 102 | 103 | // loading p 104 | this.wxLoading = document.createElement('span') 105 | this.wxLoading.className = 'wx-loading' 106 | this.wxAudioDetail.appendChild(this.wxLoading) 107 | 108 | // laoding wrapper 109 | this.wxLoadingWrapper = document.createElement('span') 110 | this.wxLoadingWrapper.className = 'wx-loading-wrapper' 111 | this.wxLoading.appendChild(this.wxLoadingWrapper) 112 | 113 | // origin 114 | this.wxAudioOrigin = document.createElement('div') 115 | this.wxAudioOrigin.className = 'wx-audio-origin' 116 | this.wxAudioP.appendChild(this.wxAudioOrigin) 117 | 118 | // 音乐时间信息 119 | this.wxAudioTime = document.createElement('div') 120 | this.wxAudioTime.className = 'wx-audio-time' 121 | this.wxAudioR.appendChild(this.wxAudioTime) 122 | 123 | // currentT 124 | this.wxAudioCurrent = document.createElement('span') 125 | this.wxAudioCurrent.className = 'current-t' 126 | this.wxAudioCurrent.innerText = '00:00' 127 | this.wxAudioTime.appendChild(this.wxAudioCurrent) 128 | 129 | // durationT 130 | this.wxAudioDuration = document.createElement('span') 131 | this.wxAudioDuration.className = 'duration-t' 132 | this.wxAudioDuration.innerText = '00:00' 133 | this.wxAudioTime.appendChild(this.wxAudioDuration) 134 | 135 | this.initAudioEvent(); 136 | 137 | if (this.opt.autoplay) { 138 | document.addEventListener('WeixinJSBridgeReady', () => { 139 | this.audioPlay() 140 | }) 141 | } 142 | } 143 | 144 | // 播放 145 | audioPlay () { 146 | this.wxAudio.play() 147 | this.isPlaying = true 148 | } 149 | 150 | // 151 | audioPause () { 152 | this.wxAudio.pause(); 153 | this.isPlaying = false 154 | } 155 | 156 | audioPlayPause () { 157 | if (this.isPlaying) { 158 | this.audioPause(); 159 | } else { 160 | this.audioPlay(); 161 | } 162 | } 163 | 164 | audioCut (src, title, disc) { 165 | this.wxAudio.src = src 166 | this.wxAudioT.innerText = title 167 | this.wxAudioD.innerText = disc 168 | this.durationT = 0 169 | this.currentT = 0 170 | this.currentP = 0 171 | this.dragProgressTo = 0 172 | // 初始化 wxAudioCurrent 的文案 173 | this.wxAudioCurrent.innerText = '00:00' 174 | this.wxAudioOrigin.style.left = '0px' 175 | this.wxVoiceP.style.width = '0px' 176 | this.audioPlay() 177 | } 178 | 179 | showLoading (bool) { 180 | this.loading = bool || false 181 | if (this.loading) { 182 | this.wxLoading.style.display = 'block' 183 | } else { 184 | this.wxLoading.style.display = 'none' 185 | } 186 | } 187 | 188 | initAudioEvent () { 189 | var _this = this 190 | // 音频事件 191 | _this.wxAudio.onplaying = function () { 192 | var date = new Date () 193 | _this.isPlaying = true 194 | _this.reduceTBefore = Date.parse(date) - Math.floor(_this.wxAudio.currentTime * 1000) 195 | _this.wxAudioStateImg.src = playImg 196 | }, 197 | _this.wxAudio.onpause = function () { 198 | _this.isPlaying = false 199 | _this.showLoading(false) 200 | _this.wxAudioStateImg.src = pauseImg 201 | }, 202 | _this.wxAudio.onloadedmetadata = function () { 203 | _this.durationT = _this.wxAudio.duration 204 | // 初始化视频时间 205 | _this.wxAudioDuration.innerText = _this.formartTime(_this.wxAudio.duration) 206 | }, 207 | _this.wxAudio.onwaiting = function () { 208 | if(!_this.wxAudio.paused) { 209 | _this.showLoading(true) 210 | } 211 | }, 212 | _this.wxAudio.onprogress = function () { 213 | if(_this.wxAudio.buffered.length > 0) { 214 | var bufferedT = 0 215 | for (var i = 0; i < _this.wxAudio.buffered.length; i++) { 216 | bufferedT += _this.wxAudio.buffered.end(i) - _this.wxAudio.buffered.start(i) 217 | if(bufferedT > _this.durationT) { 218 | bufferedT = _this.durationT 219 | _this.showLoading(false) 220 | console.log('缓冲完成') 221 | } 222 | } 223 | var bufferedP = Math.floor((bufferedT / _this.durationT) * 100) 224 | _this.wxBufferP.style.width = bufferedP + '%' 225 | } 226 | 227 | // =========================== 228 | var date = new Date () 229 | if(!_this.wxAudio.paused) { 230 | _this.reduceTAfter = Date.parse(date) - Math.floor(_this.currentT * 1000) 231 | if(_this.reduceTAfter - _this.reduceTBefore > 1000) { 232 | _this.showLoading(true) 233 | } else { 234 | _this.showLoading(false) 235 | } 236 | } else { 237 | return 238 | } 239 | }, 240 | // 播放结束事件 241 | _this.wxAudio.onended = function () { 242 | _this.opt.ended() 243 | } 244 | // 绑定进度条 245 | _this.wxAudio.ontimeupdate = function () { 246 | var date = new Date () 247 | if (!_this.isDrag) { 248 | _this.currentT = _this.wxAudio.currentTime 249 | _this.currentP = Number((_this.wxAudio.currentTime / _this.durationT) * 100) 250 | _this.reduceTBefore = Date.parse(date) - Math.floor(_this.currentT * 1000) 251 | _this.currentP = _this.currentP > 100 ? 100 : _this.currentP 252 | _this.wxVoiceP.style.width = _this.currentP + '%' 253 | _this.wxAudioOrigin.style.left = _this.currentP + '%' 254 | // 更改时间进度 255 | _this.wxAudioCurrent.innerText = _this.formartTime(_this.wxAudio.currentTime) 256 | _this.showLoading(false) 257 | } 258 | }, 259 | // 页面点击事件 260 | _this.wxAudioStateImg.onclick = function () { 261 | _this.audioPlayPause() 262 | } 263 | 264 | _this.wxAudioOrigin.onmousedown = function (event) { 265 | _this.isDrag = true 266 | var e = event || window.event 267 | var x = e.clientX 268 | var l = event.target.offsetLeft 269 | _this.maxProgressWidth = _this.wxAudioDetail.offsetWidth 270 | _this.wxAudioC.onmousemove = function (event) { 271 | if (_this.isDrag) { 272 | var e = event || window.event 273 | var thisX = e.clientX 274 | _this.dragProgressTo = Math.min(_this.maxProgressWidth, Math.max(0, l + (thisX - x))) 275 | // update Time 276 | _this.updatePorgress() 277 | } 278 | } 279 | _this.wxAudioC.onmouseup = function () { 280 | if (_this.isDrag) { 281 | _this.isDrag = false 282 | _this.wxAudio.currentTime = Math.floor(_this.dragProgressTo / _this.maxProgressWidth * _this.durationT) 283 | } else { 284 | return 285 | } 286 | } 287 | 288 | _this.wxAudioC.onmouseleave = function () { 289 | if (_this.isDrag) { 290 | _this.isDrag = false 291 | _this.wxAudio.currentTime = Math.floor(_this.dragProgressTo / _this.maxProgressWidth * _this.durationT) 292 | } else { 293 | return 294 | } 295 | } 296 | } 297 | 298 | _this.wxAudioOrigin.ontouchstart = function (event) { 299 | _this.isDrag = true 300 | var e = event || window.event 301 | var x = e.touches[0].clientX 302 | var l = e.target.offsetLeft 303 | 304 | _this.maxProgressWidth = _this.wxAudioDetail.offsetWidth 305 | 306 | _this.wxAudioC.ontouchmove = function (event) { 307 | if (_this.isDrag) { 308 | var e = event || window.event 309 | var thisX = e.touches[0].clientX 310 | _this.dragProgressTo = Math.min(_this.maxProgressWidth, Math.max(0, l + (thisX - x))) 311 | _this.updatePorgress() 312 | } 313 | }, 314 | _this.wxAudioC.ontouchend = function () { 315 | if (_this.isDrag) { 316 | _this.isDrag = false 317 | _this.wxAudio.currentTime = Math.floor(_this.dragProgressTo / _this.maxProgressWidth * _this.durationT) 318 | } else { 319 | return 320 | } 321 | } 322 | } 323 | 324 | _this.wxAudioDetail.onclick = function (event) { 325 | var e = event || window.event 326 | var l = e.layerX 327 | var w = _this.wxAudioDetail.offsetWidth 328 | _this.wxAudio.currentTime = Math.floor(l / w * _this.durationT) 329 | } 330 | } 331 | 332 | isWeiXin () { 333 | const uaLower = window.navigator.userAgent.toLowerCase() 334 | return String(uaLower.match(/MicroMessenger/i)) === 'micromessenger' 335 | } 336 | 337 | updatePorgress () { 338 | this.wxAudioOrigin.style.left = this.dragProgressTo + 'px' 339 | this.wxVoiceP.style.width = this.dragProgressTo + 'px' 340 | var currentTime = Math.floor(this.dragProgressTo / this.maxProgressWidth * this.durationT) 341 | // this.wxAudio.currentTime = currentTime 342 | this.wxAudioCurrent.innerText = this.formartTime(currentTime) 343 | // this.wxAudio.currentTime = Math.floor(this.dragProgressTo / this.maxProgressWidth * this.durationT) 344 | } 345 | 346 | formartTime (seconds) { 347 | var formatNumber = function (n) { 348 | n = n.toString() 349 | return n[1] ? n : '0' + n 350 | } 351 | var m = Math.floor(seconds / 60); 352 | var s = Math.floor(seconds % 60); 353 | return formatNumber(m) + ":" + formatNumber(s); 354 | } 355 | } 356 | -------------------------------------------------------------------------------- /src/lib/wx-audio.less: -------------------------------------------------------------------------------- 1 | @keyframes slidein { 2 | 0% { 3 | -webkit-transform: translateX(-50%); 4 | -moz-transform: translateX(-50%); 5 | -ms-transform: translateX(-50%); 6 | -o-transform: translateX(-50%); 7 | transform: translateX(-50%); 8 | -webkit-transform: translateX(-50%); 9 | -moz-transform: translateX(-50%); 10 | -ms-transform: translateX(-50%); 11 | -o-transform: translateX(-50%); 12 | transform: translateX(-50%); } 13 | 100% { 14 | -webkit-transform: translateX(0); 15 | -moz-transform: translateX(0); 16 | -ms-transform: translateX(0); 17 | -o-transform: translateX(0); 18 | transform: translateX(0); 19 | -webkit-transform: translateX(0); 20 | -moz-transform: translateX(0); 21 | -ms-transform: translateX(0); 22 | -o-transform: translateX(0); 23 | transform: translateX(0); } } 24 | .wx-audio-content{ 25 | user-select: none; 26 | width: 100%; 27 | display: flex; 28 | align-items: center; 29 | justify-content: center; 30 | min-height: auto; 31 | padding: 8px 12px; 32 | border: 1px solid #efefef; 33 | margin: 0 auto; 34 | font-size: 0; 35 | box-sizing: border-box; 36 | font-family: 'PingFangSC-Regular'; 37 | -webkit-tap-highlight-color:transparent; 38 | background:#fdfdfd; 39 | p{ 40 | margin: 0; 41 | } 42 | .wx-audio-info{ 43 | display: none; 44 | } 45 | .wx-audio-left{ 46 | display: inline-block; 47 | width:42px; 48 | height: 100%; 49 | .wx-audio-state{ 50 | width: 100%; 51 | height: 100%; 52 | } 53 | } 54 | .wx-audio-right{ 55 | display: inline-block; 56 | width: calc(100% - 42px); 57 | font-size: 16px; 58 | box-sizing: border-box; 59 | padding-left:10px; 60 | .wx-audio-title{ 61 | padding-bottom: 6px; 62 | width: 100%; 63 | font-size: 16px; 64 | font-weight: 400; 65 | text-overflow: ellipsis; 66 | overflow: hidden; 67 | white-space: nowrap; 68 | } 69 | .wx-audio-disc{ 70 | width: 100%; 71 | text-overflow: ellipsis; 72 | overflow: hidden; 73 | white-space: nowrap; 74 | padding-bottom: 10px; 75 | font-size: 12px; 76 | color: #8c8c8c; 77 | } 78 | .wx-audio-progrees{ 79 | height: 2px; 80 | width: calc(100% - 4px); 81 | position:relative; 82 | .wx-progrees-detail{ 83 | height: 100%; 84 | width: 100%; 85 | background:#ebebeb; 86 | position:relative; 87 | cursor: pointer; 88 | .wx-voice-p{ 89 | width: 0%; 90 | position: absolute; 91 | top: 0; 92 | bottom: 0; 93 | left: 0; 94 | right: 0; 95 | overflow: hidden; 96 | background:#09bb07; 97 | z-index: 2; 98 | } 99 | .wx-buffer-p{ 100 | width: 0%; 101 | position: absolute; 102 | top: 0; 103 | bottom: 0; 104 | left: 0; 105 | right: 0; 106 | overflow: hidden; 107 | background:#d9d9d9; 108 | z-index: 1; 109 | } 110 | .wx-loading{ 111 | display: none; 112 | position: absolute; 113 | top: 0; 114 | bottom: 0; 115 | left: 0; 116 | right: 0; 117 | overflow: hidden; 118 | .wx-loading-wrapper{ 119 | position: absolute; 120 | top: 0; 121 | bottom: 0; 122 | left: 0; 123 | animation: slidein 6s linear infinite normal; 124 | -webkit-animation: slidein 6s linear infinite normal; 125 | -moz-animation: slidein 6s linear infinite normal; 126 | width: 200%; 127 | max-width: none!important; 128 | background-image: -owg-repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 129 | background-image: -webkit-repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 130 | background-image: -moz-repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 131 | background-image: -o-repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 132 | background-image: repeating-linear-gradient(-15deg, #d9d9d9, #d9d9d9 2px, #ebebeb 2px, #ebebeb 4px); 133 | } 134 | } 135 | } 136 | .wx-audio-origin{ 137 | width: 6px; 138 | height: 6px; 139 | margin-top: -3px; 140 | margin-left: 0; 141 | border-radius: 50%; 142 | -moz-border-radius: 50%; 143 | -webkit-border-radius: 50%; 144 | background-color: #09bb07; 145 | position: absolute; 146 | left: 0; 147 | top: 50%; 148 | z-index: 2; 149 | &:before{ 150 | content: " "; 151 | display: block; 152 | // z-index: 2; 153 | position: absolute; 154 | width: 24px; 155 | height: 24px; 156 | border-radius: 50%; 157 | -moz-border-radius: 50%; 158 | -webkit-border-radius: 50%; 159 | // background-color: rgba(9,187,7,0.3); 160 | background-image: radial-gradient(rgba(9,187,7,0.3) 20%, transparent 40%); 161 | top: 50%; 162 | margin-top: -12px; 163 | margin-left: -9px; 164 | cursor: pointer; 165 | outline: 0; 166 | -webkit-tap-highlight-color: rgba(0,0,0,0); 167 | } 168 | } 169 | } 170 | .wx-audio-time{ 171 | width: 100%; 172 | padding-top: 6px; 173 | height: auto; 174 | display: flex; 175 | align-items: center; 176 | justify-content: space-between; 177 | overflow: hidden; 178 | span{ 179 | font-size: 12px; 180 | color: #8c8c8c; 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/style.less: -------------------------------------------------------------------------------- 1 | body,html{ 2 | margin: 0; 3 | padding: 0; 4 | height:100%; 5 | background: #fff; 6 | } 7 | 8 | .colortext-lt (@color1, @color2) { 9 | position: relative; 10 | background: -webkit-linear-gradient(left top, @color1 , @color2); /* Safari 5.1 - 6.0 */ 11 | background: -o-linear-gradient(bottom right, @color1, @color2); /* Opera 11.1 - 12.0 */ 12 | background: -moz-linear-gradient(bottom right, @color1, @color2); /* Firefox 3.6 - 15 */ 13 | background: linear-gradient(to bottom right, @color1 , @color2); /* 标准的语法 */ 14 | -webkit-background-clip: text; 15 | -webkit-text-fill-color: transparent; 16 | } 17 | 18 | body{ 19 | // background: red; 20 | display: flex; 21 | width: 100%; 22 | height: 100%; 23 | align-items: center; 24 | flex-direction: column; 25 | justify-content: center; 26 | .title{ 27 | font-size: 42px; 28 | display: inline-block; 29 | .colortext-lt(rgba(50, 219, 154, 0.856), rgba(209, 163, 47, 0.808)); 30 | margin-top: 0; 31 | } 32 | .disc{ 33 | font-size: 14px; 34 | color: #f1f1f1; 35 | } 36 | .github-info{ 37 | margin-top: 40px; 38 | text-align: center; 39 | display: flex; 40 | justify-content: center; 41 | span{ 42 | color: #ffffff; 43 | font: Arial,"Helvetica Neue",Helvetica,"Microsoft Yahei","Hiragino Sans GB","Heiti SC","WenQuanYi Micro Hei",sans-serif; 44 | font-size:14px; 45 | } 46 | } 47 | .btn{ 48 | width: 320px; 49 | line-height: 40px; 50 | background: #999; 51 | cursor: pointer; 52 | color: #fff; 53 | text-align: center; 54 | margin-top: 30px; 55 | } 56 | } -------------------------------------------------------------------------------- /tea.yaml: -------------------------------------------------------------------------------- 1 | # https://tea.xyz/what-is-this-file 2 | --- 3 | version: 1.0.0 4 | codeOwners: 5 | - '0x18fb62c5c736405ece7E8e7a2F01D084fFa77B6c' 6 | quorum: 1 7 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); // 用于访问内置插件 2 | const path = require('path'); 3 | 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const ExtractTextPlugin = require("extract-text-webpack-plugin"); 6 | const WebpackPromptPlugin = require("@dw/webpack-prompt-plugin") 7 | 8 | const extractSass = new ExtractTextPlugin({ 9 | filename: "wx-audio.css", 10 | disable: process.env.NODE_ENV === "development" 11 | }); 12 | 13 | const resolve = function (dir) { 14 | return path.resolve(__dirname, dir); 15 | } 16 | 17 | module.exports = { 18 | entry: { 19 | index: 'src/lib/wx-audio.js' 20 | // index: './src/index.js' 21 | }, 22 | output: { 23 | path: path.resolve(__dirname, 'lib'), 24 | filename: 'wx-audio.js', 25 | libraryTarget: 'var', 26 | library: 'WxAudio', 27 | libraryExport: 'default' 28 | }, 29 | module: { 30 | rules: [ 31 | { 32 | test: /\.css$/, 33 | use: ExtractTextPlugin.extract({ 34 | fallback:"style-loader", 35 | use:["css-loader"] 36 | }) 37 | }, 38 | { 39 | test: /\.less$/, 40 | use: ExtractTextPlugin.extract({ 41 | fallback:"style-loader", 42 | use:[ 43 | { 44 | loader: 'css-loader' 45 | }, 46 | { 47 | loader: 'less-loader' 48 | } 49 | ] 50 | }) 51 | }, 52 | { 53 | test: /\.(ttf|eot|svg|woff|woff2)$/, 54 | use: [ 55 | { 56 | loader: 'url-loader' 57 | } 58 | ] 59 | }, 60 | { 61 | test: /\.js$/, 62 | exclude: /(node_modules)/, 63 | use: { 64 | loader: 'babel-loader', 65 | options: { 66 | presets: ["env"] 67 | } 68 | } 69 | }, 70 | { 71 | test: /\.(png|jpg|gif)$/, 72 | use: [ 73 | { 74 | loader: 'url-loader', 75 | options: { 76 | limit: 8192 77 | } 78 | } 79 | ] 80 | }, 81 | ] 82 | }, 83 | plugins: [ 84 | // new HtmlWebpackPlugin ({ 85 | // filename: 'index.html', 86 | // template: 'index.html', 87 | // inject: true 88 | // }), 89 | extractSass, 90 | new WebpackPromptPlugin() 91 | ], 92 | devServer: { 93 | // 当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html。通过传入以下启用: 94 | contentBase: "./", 95 | host: '0.0.0.0', 96 | // 端口号 97 | port: 1997, 98 | //当有编译器错误或警告时,在浏览器中显示全屏覆盖。默认禁用。如果您只想显示编译器错误: 99 | noInfo: true, 100 | // 配置端口号 101 | overlay: true, 102 | }, 103 | resolve: { 104 | alias: { 105 | 'src': resolve('src'), 106 | 'commonjs': resolve('src/commonjs'), 107 | 'scss': resolve('src/scss'), 108 | 'stylus': resolve('src/stylus'), 109 | 'script': resolve('src/script'), 110 | 'static': resolve('static'), 111 | } 112 | }, 113 | optimization: { 114 | splitChunks: { 115 | chunks: "all", 116 | minSize: 30000, 117 | minChunks: 3, 118 | maxAsyncRequests: 5, 119 | maxInitialRequests: 3, 120 | name: true, 121 | cacheGroups: { 122 | default: { 123 | minChunks: 2, 124 | priority: -20, 125 | reuseExistingChunk: true, 126 | }, 127 | vendors: { 128 | test: /[\\/]node_modules[\\/]/, 129 | priority: -10 130 | } 131 | } 132 | } 133 | } 134 | } 135 | --------------------------------------------------------------------------------