原生 js 实现一个有动画效果的进度条插件 progress

效果图:项目地址:https://github.com/biaochenxuying/progress效果体验地址: https://biaochenxuying.github.io/progress/index.html1. 原理一个用于装载进度条内容的 div (且叫做 container)。然后在 container 里面动态生成三个元素,一个是做为背景的 div (且叫做 progress),一个是做为显示进度的 div (且叫做 bar),还有一个是显示文字的 span (且叫做 text)。progress 的宽为 100%,bar 的宽根据传入数值 target 的值来定( 默认为 0 ,全部占满的值为 100 ),text 展示的文字为 bar 的宽占 progress 宽的百分比。bar 的宽从 0 逐渐增加到的 target 值的过程( 比如: 0 > 80 ),给这个过程添加一个逐渐加快的动画。2. 代码实现具体的过程请看代码:/** author: https://github.com/biaochenxuying*/(function() { function Progress() { this.mountedId = null; this.target = 100; this.step = 1; this.color = ‘#333’; this.fontSize = ‘18px’; this.borderRadius = 0; this.backgroundColor = ‘#eee’; this.barBackgroundColor = ‘#26a2ff’; } Progress.prototype = { init: function(config) { if (!config.mountedId) { alert(‘请输入挂载节点的 id’); return; } this.mountedId = config.mountedId; this.target = config.target || this.target; this.step = config.step || this.step; this.fontSize = config.fontSize || this.fontSize; this.color = config.color || this.color; this.borderRadius = config.borderRadius || this.borderRadius; this.backgroundColor = config.backgroundColor || this.backgroundColor; this.barBackgroundColor = config.barBackgroundColor || this.barBackgroundColor; var box = document.querySelector(this.mountedId); var width = box.offsetWidth; var height = box.offsetHeight; var progress = document.createElement(‘div’); progress.style.position = ‘absolute’; progress.style.height = height + ‘px’; progress.style.width = width + ‘px’; progress.style.borderRadius = this.borderRadius; progress.style.backgroundColor = this.backgroundColor; var bar = document.createElement(‘div’); bar.style.float = ’left’; bar.style.height = ‘100%’; bar.style.width = ‘0’; bar.style.lineHeight = height + ‘px’; bar.style.textAlign = ‘center’; bar.style.borderRadius = this.borderRadius; bar.style.backgroundColor = this.barBackgroundColor; var text = document.createElement(‘span’); text.style.position = ‘absolute’; text.style.top = ‘0’; text.style.left = ‘0’; text.style.height = height + ‘px’; text.style.lineHeight = height + ‘px’; text.style.fontSize = this.fontSize; text.style.color = this.color; progress.appendChild(bar); progress.appendChild(text); box.appendChild(progress); this.run(progress, bar, text, this.target, this.step); }, /** * @name 执行动画 * @param progress 底部的 dom 对象 * @param bar 占比的 dom 对象 * @param text 文字的 dom 对象 * @param target 目标值( Number ) * @param step 动画步长( Number ) */ run: function(progress, bar, text, target, step) { var self = this; ++step; var endRate = parseInt(target) - parseInt(bar.style.width); if (endRate <= step) { step = endRate; } var width = parseInt(bar.style.width); var endWidth = width + step + ‘%’; bar.style.width = endWidth; text.innerHTML = endWidth; if (width >= 94) { text.style.left = ‘94%’; } else { text.style.left = width + 1 + ‘%’; } if (width === target) { clearTimeout(timeout); return; } var timeout = setTimeout(function() { self.run(progress, bar, text, target, step); }, 30); }, }; // 注册到 window 全局 window.Progress = Progress;})();3. 使用方法 var config = { mountedId: ‘#bar’, target: 8, step: 1, color: ‘green’, fontSize: “20px”, borderRadius: “5px”, backgroundColor: ‘#eee’, barBackgroundColor: ‘red’, }; var p = new Progress(); p.init(config);4. 最后笔者的博客后花圆地址如下:github :https://github.com/biaochenxuying/blog个人网站 :http://biaochenxuying.cn/main.html如果您觉得这篇文章不错或者对你有所帮助,请给个赞呗,你的点赞就是对我最大的鼓励,谢谢。微信公众号:BiaoChenXuYing分享 前端、后端开发等相关的技术文章,热点资源,随想随感,全栈程序员的成长之路。关注公众号并回复 福利 便免费送你视频资源,绝对干货。福利详情请点击: 免费资源分享–Python、Java、Linux、Go、node、vue、react、javaScript ...

February 26, 2019 · 2 min · jiezi

react-native 上传图片和视频到阿里云, 带进度条

实现上面的效果需要的库如下react-native-image-pickerreact-native-progress先来说下是如何实现点击上传图标弹出optionModal上传选项的动画的.整个optionModal区域是一个Animated.View, render 的时候他的position 是 absolute的, 整个位置是隐藏在屏幕下的, bottom: - 200. 点击按钮之后,用Animated.spring 把 bottom 的值 调整到 0 , 这样隐藏的部分就弹出来了。const styles = StyleSheet.create({ container: { backgroundColor: theme.screen_background_color, zIndex: 100, height: 200, width: ‘100%’, position: ‘absolute’, bottom: - 200), backgroundColor: ‘rgb(255,255,255)’, alignItems: ‘center’, borderTopWidth: 1, borderTopColor: theme.divider_color, } showOptionModal() { Animated.spring( this.modalPos, { toValue: 0, } ).start();<Animated.View style={[styles.container, { bottom: this.modalPos }]}> </Animated.View>还有就是区域里面的upload video 和 upload photos 图标动画有个先后顺序,这里的处理就是upload video 这个图标用了个settimeout, 让他的动画触发晚了个 0.1秒而已。实现的方法也是跟optionModal弹出的方法一样。接下来就是选择手机里面的图片或者视频了,这里我们会用一个库叫做 react-native-image-picker, 这个库应该是大家很经常会使用到的, 就是选择手机里面的视频和图片,或者可以用摄像头拍摄图片. 当我们点击 upload photos 的时候, 触发下面的代码就可以开始选择图片了 ImagePicker.showImagePicker({ title: null, cancelButtonTitle: ‘cancel’, allowsEditing: true, chooseFromLibraryButtonTitle: ‘choose from camera roll’, takePhotoButtonTitle: type===‘video’?null:‘open camera’, mediaType: type, noData: true, quality: 0.5, videoQuality: ‘medium’, storageOptions: { skipBackup: true, cameraRoll: true, waitUntilSaved: true, }, }, (response) => { if (!response.didCancel && !response.error) { //可以在这里上传图片了 this.startUpload(response); } return null; }); }当图片选择完毕之后, 就会触发this.startUpload(response); 了, 下面就是如何处理图片上传阿里云的部分了。 在上传文件到阿里云oss 之前呢 需要从Oss获取几个配置项,OSSAccessKeyId,Signature,key, police, 可以看下Oss 文档,这个需要你自己搞定啦。startUpload(response){ const uploadMediaData = new FormData(); uploadMediaData.append(‘OSSAccessKeyId’, accessKeyId); uploadMediaData.append(‘policy’, policy); uploadMediaData.append(‘Signature’, signature); uploadMediaData.append(‘key’, key); uploadMediaData.append(‘success_action_status’, 201); uploadMediaData.append(‘file’, { uri: response.uri, type: ‘multipart/form-data’, name: response.fileName, }); // 上传成功 successResponse = (xhr) => { let returnKey = xhr.responseText.match(/<Key>([^<]*)</Key>/)[1]; //这个key 就是你上传文件在oss 的地址了, }; //上传失败 failResponse = () => { // to do }; //开始上传 const OSS_UPLOAD_URI = ‘http://xxxxx.oss-us-east-1.aliyuncs.com’ futch(OSS_UPLOAD_URI, { method: ‘POST’, body: uploadMediaData, extra: null, }, (progressEvent) => { // progress 就是上穿的进度, 更新 state 里面的uploadProgress const progress = (progressEvent.loaded / progressEvent.total); this.setState({ uploadProgress: progress, }) }, (xhr) => successResponse(xhr), failResponse) .then((res) => console.log(res), (err) => console.log(’error’ + err));}//这个方法就是具体上传的代码了futch = (url, opts = {}, onProgress, successResponse, failResponse) => { return new Promise((res, rej) => { let xhr = new XMLHttpRequest(); xhr.open(opts.method || ‘get’, url); for (let k in opts.headers || {}) xhr.setRequestHeader(k, opts.headers[k]); xhr.onload = e => res(e); xhr.onreadystatechange = (e) => { if (xhr.readyState !== 4) { return; } //阿里云的状态码201 才有返回的信息 if (xhr.status === 201) { xhr.extra = opts.extra; successResponse(xhr); } else { xhr.extra = opts.extra; failResponse(xhr); } }; xhr.onerror = rej; if (xhr.upload && onProgress) xhr.upload.onprogress = onProgress; xhr.setRequestHeader(‘Content-Type’, ‘multipart/form-data’); xhr.send(opts.body); });}如果一切都ok 的话, 这个时候在上传的过程中就应该出现进度条了,上面提到了,this.state.uploadProgress 是用来存储上传进度的, 我们就利用这个作为进度条的数据源了, 因为我们用的是圆形的进度条,这里需要另外一个库, ’ react-native-progress’.import ProgressCircle from ‘react-native-progress/Circle’;//render 的时候只要把this.state.uploadProgress 丢进去就行了 <ProgressCircle size={30} showsText={true} size={100} progress={uploadProgress} color={‘#32CDFF’} thickness={4} borderWidth={2} style={styles.progressCircle} />这里特别提出一下,oss 的上传成功的返回代码是201。这样整个过程就结束了, 其中有些细节没提出来,需要大家自己完善,但是大概的流程应该都写出来了. 希望对大大家有用。 ...

December 21, 2018 · 2 min · jiezi