自定義input上傳圖片組件,美化樣式
前段時間由於項目需求,作過一個上傳圖片組件,這裏分享下大體思路,但願對有須要的童鞋有所幫助~~~javascript
功能需求:1.上傳圖片限制大小、分辨率、類型 2.上傳圖片支持自由裁剪 3.圖片上傳後支持預覽和刪除
效果圖,只截取了一小部分,大體看下就ok啦,是否是感受比原生的好看多了^_^
css
項目是基於react
框架寫的,話很少說,開始擼代碼~~~html
Step1:編寫基礎html結構
<div> <input type="file" accept="image/jpeg, image/gif, image/png, image/bmp" styleName="input-file" /> <label htmlFor="file" styleName="ant-upload"> {uploadButton} </label> </div> // uploadButton組件代碼以下: const uploadButton = ( <div styleName="upload-plus-text"> <Icon type="plus" /> <div className="ant-upload-text">上傳照片</div> </div> );
Step2:基礎樣式
input-file { width: 0.1px; height: 0.1px; opacity: 0; overflow: hidden; position: absolute; z-index: -1; } .ant-upload { @w: 100px; width: @w; height: @w; padding: 5px; background-color: #fafafa; border: 1px dashed #d9d9d9; border-radius: 4px; display: block; cursor: pointer; position: relative; } .upload-plus-text { width: 100%; text-align: center; position: absolute; left: 0; top: 50%; transform: translateY(-50%); i { font-size: 28px; color: #999; } .ant-upload-text { margin-top: 8px; font-size: 12px; color: #666; } }
Step3:添加事件處理
對上傳圖片的類型、大小和分辨率進行檢測java
<input type="file" id='file' accept="image/jpeg, image/gif, image/png, image/bmp" styleName="input-file" onChange={e => { this.onFileChange(e); }} /> <label htmlFor="file" styleName="ant-upload"> {uploadButton} </label> </div> // 一些常量定義 const IMAGE_MIN_WIDTH = 1280; // 上傳圖片最小寬 const IMAGE_MIN_HEIGHT = 800; // 上傳圖片最小高 const IMAGE_MAX_SIZE = 1024 * 1024; // 上傳圖片最大大小 // 處理上傳文件 onFileChange(e) { const file = e.target.files[0]; e.target.value = ''; // 再次上傳同一文件進行裁剪 if (this.handleBeforeUpload(file)) { const reader = new FileReader(); reader.onload = e => { const src = e.target.result; const image = new Image(); const _this = this; image.onload = () => { const width = image.width; const height = image.height; if (width >= IMAGE_MIN_WIDTH && height >= IMAGE_MIN_HEIGHT) { _this.setState({ initialImageUrl: src, showCropModal: true }); } else { message.error('照片分辨率小於1280*800'); } }; image.src = src; }; reader.readAsDataURL(file); } } // 檢查照片格式、大小等信息 handleBeforeUpload(file) { if (file) { const sizeOk = file.size < IMAGE_MAX_SIZE; const typeReg = new RegExp(/^image\/bmp|gif|jpg|jpeg|png$/, 'i'); const typeOk = typeReg.test(file.type); if (!typeOk) { message.error('照片格式有誤'); } else if (!sizeOk) { message.error('照片大小超過1M'); } return sizeOk && typeOk; } }
Step4:裁剪功能
代碼較多就不展現了= =,使用的是react-cropperreact
Step5:預覽和刪除功能
預覽功能實現思路就是經過判斷是否已經上傳圖片來展現不一樣的狀態。未上傳展現uploadButton組件,已上傳就展現imagePreview組件。
經過判斷是否已經上傳圖片來控制input標籤的id屬性值,未上傳圖id='file',已上傳圖片將id='',這樣一來,再次去點擊label的時候因爲for屬性找不到對應的id,就不會觸發input上onChange事件git
<div> <input type="file" id={imageUrl ? '' : 'file'} accept="image/jpeg, image/gif, image/png, image/bmp" styleName="input-file" onChange={e => { this.onFileChange(e); }} /> <label htmlFor="file" styleName="ant-upload"> {imageUrl ? imagePreview : uploadButton} </label> </div> <Modal visible={showPreviewModal} title="圖片預覽" footer={null} width={700} onCancel={this.handlePreviewCancel}> <img alt="" style={{ width: '100%' }} src={imageUrl} /> </Modal> // imagePreview組件代碼以下 const imagePreview = ( <div styleName="image-background-preview" style={{ backgroundImage: `url(${imageUrl})` }}> <div styleName="preview-image"> <span styleName="preview-image-btn"> <a title="預覽圖片" href="javascript:;"> <Icon type="eye" styleName="icon-btn" onClick={this.handlePreview} /> </a> <a title="刪除圖片" href="javascript:;"> <Icon type="delete" styleName="icon-btn" onClick={this.swapImageFile} /> </a> </span> </div> </div> ); // 預覽圖片 handlePreview() { this.setState({ showPreviewModal: true }); } // 刪除圖片 swapImageFile() { this.setState({ imageUrl: '' }); }
寫在最後:項目涉及代碼較多,文章只展現了大部分代碼,一些具體細節代碼可能就沒有展現了,還望見諒,第一次寫文章,可能比較混亂,有問題還望你們指出~~~ ^_^github