需要实现的页面效果:
点击头像进行图片上传;再次点击可以修改
遇到的问题:上传图片反显到框里面 图片旋转
最终解决方案:
<div style={
{padding:'10px 0'}}>
<span className={s.fileStyle}>
<img src={this.state.imgSrc} alt="" className={s.imgs} id='imgBox'/>
<ImagePicker
length={1}
files={this.state.files}
onChange={this.onChange}
onImageClick={(index, fs) => console.log(index, fs)}
selectable={true}
accept="image/gif,image/jpeg,image/jpg,image/png"
disableDelete
/>
</span>
</div>
//js代码
onChange = (files, type, index) => {
console.log(files, type, index);
if (type == 'add') {
this.setState({
files,
});
var file=files[files.length - 1].file;
const windowURL = window.URL || window.webkitURL;//实现预览
var u = navigator.userAgent;
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
if(isiOS){
console.log('ios');
console.log(file.size/1024+'kb')
const isLt400K = file.size /1024 < 200;
if(!isLt400K){
return this.getsmallpic(file)
}else{
this.setState({
imgArr:files[files.length - 1].file,
imgSrc:files[files.length - 1].url
})
}
}else if(isAndroid){
console.log('Android');
var that=this;
this.rotateImg(files[files.length - 1].file).then(blob => {
document.getElementById('imgBox').src = URL.createObjectURL(blob) // 转换后的img
this.blobToDataURL(blob, function(dataurl) {
console.log(file.size/1024+'kb')
const isLt400K = file.size /1024 < 200;
if(!isLt400K){
return that.getsmallpic(that.dataURLtoFile(dataurl,file.name))
}else{
this.setState({
imgArr:files[files.length - 1].file
})
}
});
});
}else{
console.log('pc')
console.log(file.size/1024+'kb')
const isLt400K = file.size /1024 < 200;
if(!isLt400K){
return this.getsmallpic(file)
}else{
this.setState({
imgArr:files[files.length - 1].file,
imgSrc:files[files.length - 1].url
})
}
}
}
}
blobToDataURL(blob, callback) {
var a = new FileReader();
a.onload = function(e) {
callback(e.target.result);
}
a.readAsDataURL(blob);
return a;
}
//图片翻转
rotateImg(file) {
return new Promise((resolve, reject) => {
let img = new Image();
img.src = window.URL.createObjectURL(file);
img.onload = () => {
util.addScript('https://cdn.jsdelivr.net/npm/exif-js', () => {
var EXIF=window.EXIF;
// 获取图片源数据 上面已经引入EXIF全局变量
EXIF.getData(img, function () {
// 获取图片orientation值
console.log(EXIF.getAllTags(this))
let orientation = EXIF.getTag(this, "Orientation");
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
switch (orientation) {
case 3: // 旋转180°
canvas.width = img.width;
canvas.height = img.height;
ctx.rotate((180 * Math.PI) / 180);
ctx.drawImage(img, -img.width, -img.height, img.width, img.height);
break;
case 6: // 旋转90°
canvas.width = img.height;
canvas.height = img.width;
ctx.rotate((90 * Math.PI) / 180);
ctx.drawImage(img, 0, -img.height, img.width, img.height);
break;
case 8: // 旋转-90°
canvas.width = img.height;
canvas.height = img.width;
ctx.rotate((-90 * Math.PI) / 180);
ctx.drawImage(img, -img.width, 0, img.width, img.height);
break;
default: // 没有源信息的图片和正常的图片是不需要旋转的
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
break;
}
// 处理完返回 (这里返回都是被压缩的,根据实际情况更改正常的图片处理方式)
canvas.toBlob(file => resolve(file), 'image/jpeg', 0.8)
})
});
}
})
}
//图片压缩
dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
// 图片压缩
getsmallpic(file){
return new Promise((resolve,reject)=>{
//对图片进行压缩
const reader = new FileReader()
const image = new Image()
image.onload = (imageEvent) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = image.width * 0.5
const height = image.height * 0.5
canvas.width = width;
canvas.height = height;
context.clearRect(0, 0, width, height);
context.drawImage(image, 0, 0, width, height);
const dataUrl = canvas.toDataURL(file.type);
const blobData = this.dataURLtoFile(dataUrl,file.name);
if(blobData){
if(blobData.size /1024 < 400){
Object.assign(blobData,{uid:blobData.lastModified});
const windowURL = window.URL || window.webkitURL;//实现预览
resolve(blobData)
this.setState({
imgSrc:windowURL.createObjectURL(blobData)
})
this.setState({
imgArr:blobData
})
}else{
this.getsmallpic(blobData)
}
}else{
reject()
}
}
reader.onload = (e => { image.src = e.target.result; });
reader.readAsDataURL(file);
})
}
//css片段
.fileStyle{
position: relative;
display: block;
width: 160px;
height: 160px;
border-radius: 50%;
text-align: center;
background: #f5f5f5;
margin: 0 auto;
border: 1px solid #0486FE;
overflow: hidden;
}
.imgs {
width: 160px !important;
height: 160px !important;
border-radius: 50%;
position: relative;
}
.fileStyle input {
position: absolute;
left: 0;
top: 0;
z-index: 9;
width: 160px;
height: 160px;
opacity: 0;
}
:global(.am-image-picker .am-image-picker-list .am-flexbox){
width: 165px !important;
height: 165px !important;
border-radius: 50%;
position: absolute;
top:0;
left: 0;
background-color: transparent!important;
}
:global(.am-image-picker-list){
padding: 0 0 0 0!important;
margin-bottom: 0!important;
}
:global(.am-image-picker-upload-btn){
border-radius: 50% !important;
border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item .am-image-picker-item-content){
border-radius: 50% !important;
border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item){
opacity: 0!important;
}
解题历程:
1.原始问题:刚开始使用input type类型为file上传文件 获取图片路径反显到img里面;遇到了几部手机会出现图片反显翻转的问题
<img src={this.state.imgSrc} alt="" className={s.imgs} id='imgBox'/>
<input
accept="image/png, image/jpeg,image/jpg"
type = "file"
id = "faceHuman"
className={s.input}
onChange={this.humanChange.bind(this)}
/>
//js方法
humanChange(e){
const windowURL = window.URL || window.webkitURL;//实现预览
const file = document.getElementById('faceHuman').files[0];
console.log(file.size/1024+'kb')
const isLt400K = file.size /1024 < 200;
if(!isLt400K){
return this.getsmallpic(file) //压缩图片的方法
}else{
this.setState({
imgSrc:windowURL.createObjectURL(file)
})
this.setState({
imgArr:file
})
}
}
//图片压缩的方法
dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
// 图片压缩
getsmallpic(file){
return new Promise((resolve,reject)=>{
//对图片进行压缩
const reader = new FileReader()
const image = new Image()
image.onload = (imageEvent) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = image.width * 0.5
const height = image.height * 0.5
canvas.width = width;
canvas.height = height;
context.clearRect(0, 0, width, height);
context.drawImage(image, 0, 0, width, height);
const dataUrl = canvas.toDataURL(file.type);
const blobData = this.dataURLtoFile(dataUrl,file.name);
if(blobData){
if(blobData.size /1024 < 400){
Object.assign(blobData,{uid:blobData.lastModified});
const windowURL = window.URL || window.webkitURL;//实现预览
resolve(blobData)
this.setState({
imgSrc:windowURL.createObjectURL(blobData),
class:1
})
this.setState({
imgArr:blobData
})
}else{
this.getsmallpic(blobData)
}
}else{
reject()
}
}
reader.onload = (e => { image.src = e.target.result; });
reader.readAsDataURL(file);
})
}
反显到不同的手机上会出现不同的翻转情况;各种百度之后;找到了一个exif的插件;在方法上进行了修改
2.第一次解决方法:(使用exif插件翻转处理图片)
<img src={this.state.imgSrc} alt="" className={s.imgs} id='imgBox'/>
<input
accept="image/png, image/jpeg,image/jpg"
type = "file"
id = "faceHuman"
className={s.input}
onChange={this.humanChange.bind(this)}
/>
//js方法
humanChange(e){
const windowURL = window.URL || window.webkitURL;//实现预览
const file = document.getElementById('faceHuman').files[0];
this.rotateImg(file).then(blob => {
document.getElementById('imgBox').src = URL.createObjectURL(blob) // 转换后的img
})
this.setState({
imgArr:file
})
}
//图片旋转的方法&压缩
rotateImg(file) {
return new Promise((resolve, reject) => {
let img = new Image();
img.src = window.URL.createObjectURL(file);
img.onload = () => {
util.addScript('https://cdn.jsdelivr.net/npm/exif-js', () => {
var EXIF=window.EXIF;
// 获取图片源数据 上面已经引入EXIF全局变量
EXIF.getData(img, function () {
// 获取图片orientation值
console.log(EXIF.getAllTags(this))
let orientation = EXIF.getTag(this, "Orientation");
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
switch (orientation) {
case 3: // 旋转180°
canvas.width = img.width;
canvas.height = img.height;
ctx.rotate((180 * Math.PI) / 180);
ctx.drawImage(img, -img.width, -img.height, img.width, img.height);
break;
case 6: // 旋转90°
canvas.width = img.height;
canvas.height = img.width;
ctx.rotate((90 * Math.PI) / 180);
ctx.drawImage(img, 0, -img.height, img.width, img.height);
break;
case 8: // 旋转-90°
canvas.width = img.height;
canvas.height = img.width;
ctx.rotate((-90 * Math.PI) / 180);
ctx.drawImage(img, -img.width, 0, img.width, img.height);
break;
default: // 没有源信息的图片和正常的图片是不需要旋转的
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
break;
}
// 处理完返回 (这里返回都是被压缩的,根据实际情况更改正常的图片处理方式)
canvas.toBlob(file => resolve(file), 'image/jpeg', 0.8)
})
});
}
})
}
结论:公司里除了一部苹果11的手机之外都展示正常 but 领导手机型号很巧的和这位同学型号一致 so~ 继续找方法
3.第二次解决方案:由于这个移动端基于ant-mobile框架写的 所以我决定使用一下这个里面的上传图片的组件
ImagePicker (由于组件上这个方法和实际使用中有点差别 所以原有的组件上进行了样式修改)
<div style={
{padding:'10px 0'}}>
<span className={s.fileStyle}>
<img src={this.state.imgSrc} alt="" className={s.imgs} id='imgBox'/>
<ImagePicker
length={1}
files={this.state.files}
onChange={this.onChange}
onImageClick={(index, fs) => console.log(index, fs)}
selectable={true}
accept="image/gif,image/jpeg,image/jpg,image/png"
disableDelete
/>
</span>
</div>
//js代码
onChange = (files, type, index) => {
console.log(files, type, index);
if (type == 'add') {
this.setState({
files,
});
this.rotateImg(files[files.length - 1].file).then(blob => {
document.getElementById('imgBox').src = URL.createObjectURL(blob) // 转换后的img
})
this.setState({
imgArr:files[files.length - 1].file
})
}
}
//css代码
/*修改选择弹框的样式*/
:global(.am-image-picker .am-image-picker-list .am-flexbox){
width: 165px !important;
height: 165px !important;
border-radius: 50%;
position: absolute;
top:0;
left: 0;
background-color: transparent!important;
}
:global(.am-image-picker-list){
padding: 0 0 0 0!important;
margin-bottom: 0!important;
}
:global(.am-image-picker-upload-btn){
border-radius: 50% !important;
border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item .am-image-picker-item-content){
border-radius: 50% !important;
border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item){
opacity: 0!important;
}
结论:使用组件测试之后,得出结论:安卓手机直接使用这个组件会翻转;最后决定写个判断 如果是安卓手机 使用exif插件进行图片处理反显;如果是苹果手机原来得组件赋值。
4.第三次解决方案:(翻转完成后 可以适配)
<div style={
{padding:'10px 0'}}>
<span className={s.fileStyle}>
<img src={this.state.imgSrc} alt="" className={s.imgs} id='imgBox'/>
<ImagePicker
length={1}
files={this.state.files}
onChange={this.onChange}
onImageClick={(index, fs) => console.log(index, fs)}
selectable={true}
accept="image/gif,image/jpeg,image/jpg,image/png"
disableDelete
/>
</span>
</div>
//js代码
onChange = (files, type, index) => {
console.log(files, type, index);
if (type == 'add') {
this.setState({
files,
});
var u = navigator.userAgent;
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
if(isiOS){
console.log('ios')
this.setState({
imgArr:files[files.length - 1].file,
imgSrc:files[files.length - 1].url
})
}else if(isAndroid){
console.log('Android')
this.rotateImg(files[files.length - 1].file).then(blob => {
document.getElementById('imgBox').src = URL.createObjectURL(blob) // 转换后的img
})
this.setState({
imgArr:files[files.length - 1].file
})
}else{
console.log('pc')
this.setState({
imgArr:files[files.length - 1].file,
imgSrc:files[files.length - 1].url
})
}
}
}
//图片翻转&压缩
rotateImg(file) {
return new Promise((resolve, reject) => {
let img = new Image();
img.src = window.URL.createObjectURL(file);
img.onload = () => {
util.addScript('https://cdn.jsdelivr.net/npm/exif-js', () => {
var EXIF=window.EXIF;
// 获取图片源数据 上面已经引入EXIF全局变量
EXIF.getData(img, function () {
// 获取图片orientation值
console.log(EXIF.getAllTags(this))
let orientation = EXIF.getTag(this, "Orientation");
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
switch (orientation) {
case 3: // 旋转180°
canvas.width = img.width;
canvas.height = img.height;
ctx.rotate((180 * Math.PI) / 180);
ctx.drawImage(img, -img.width, -img.height, img.width, img.height);
break;
case 6: // 旋转90°
canvas.width = img.height;
canvas.height = img.width;
ctx.rotate((90 * Math.PI) / 180);
ctx.drawImage(img, 0, -img.height, img.width, img.height);
break;
case 8: // 旋转-90°
canvas.width = img.height;
canvas.height = img.width;
ctx.rotate((-90 * Math.PI) / 180);
ctx.drawImage(img, -img.width, 0, img.width, img.height);
break;
default: // 没有源信息的图片和正常的图片是不需要旋转的
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
break;
}
// 处理完返回 (这里返回都是被压缩的,根据实际情况更改正常的图片处理方式)
canvas.toBlob(file => resolve(file), 'image/jpeg', 0.8)
})
});
}
})
}
//css片段
.fileStyle{
position: relative;
display: block;
width: 160px;
height: 160px;
border-radius: 50%;
text-align: center;
background: #f5f5f5;
margin: 0 auto;
border: 1px solid #0486FE;
overflow: hidden;
}
.imgs {
width: 160px !important;
height: 160px !important;
border-radius: 50%;
position: relative;
}
.fileStyle input {
position: absolute;
left: 0;
top: 0;
z-index: 9;
width: 160px;
height: 160px;
opacity: 0;
}
:global(.am-image-picker .am-image-picker-list .am-flexbox){
width: 165px !important;
height: 165px !important;
border-radius: 50%;
position: absolute;
top:0;
left: 0;
background-color: transparent!important;
}
:global(.am-image-picker-list){
padding: 0 0 0 0!important;
margin-bottom: 0!important;
}
:global(.am-image-picker-upload-btn){
border-radius: 50% !important;
border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item .am-image-picker-item-content){
border-radius: 50% !important;
border: 0 !important;
}
:global(.am-image-picker-list .am-image-picker-item){
opacity: 0!important;
}
结论:图片上传到后台没有压缩 之后进行图片压缩处理
之后解决方法为最上面的解决方案
完美解决~