项目中复制而出,如有多余代码删除即可
坑:ios系统不同版本相机拍出的照片有点会有旋转 和 拍照时拍摄去比例也有关
本文以ios 13.5 和 照片旋转数 为判断条件
<div class="s-page-content" id="s-page-content">
<div class="poster_content" id="poster_content" v-show="!isGeneratePosters">
<div class="content_top" :style="{'height' : posterImgHeight}">
<img class="posters_img select_none"
style="height:100%;"
@load="isLoad"
:src="postersImg" alt="">
<div class="zzc" v-show="!isAddImg"></div>
<div class="add_img" v-show="!isAddImg && !isShowUserImgUp">
<p @click="addImg" style="color:#fff">上传图片</p>
<input id="uploadImg" style="display:none" @change="getImgUrl" type="file" accept="image/jpeg, image/png" />
</div>
</div>
<div class="content_bottom">
<div class="text">
<!-- <img class="text_title" src="/refactor/public/image/active_posters_title.png" alt=""> -->
<p class="text_tips">111111<br>2222</p>
</div>
<div class="ewm">
<!-- 生成二维码 -->
<div id="QRCodeNone" style="display:none"></div>
<div id="qrcode"></div>
<p class="ewm_tips">111111<br>222222</p>
</div>
</div>
</div>
<!-- 存放生成出来的图片 -->
<div id="canvas_img"></div>
</div>
<div class="bottom_btn">
<div @click="isImgLoadComplete" v-text="isGeneratePosters ? '图片已生成' : '生成图片'"></div>
</div>
<div class="img_loading" v-if="isShowImgLoading">
<img src="/res/image/data_load.gif" alt="">
</div>
<!-- 图片剪辑框 -->
<div class="s_image_intercept" v-show="isShowTailoring">
<div class="intercept_content">
<div class="intercept_bgn">
<p @click="hideTailoring">取消</p>
<p @click="sureSava">确定</p>
</div>
<div class="container">
<div class="img-container">
<img id="imgT" :src="imgUrl" ref="image" alt="">
</div>
<div class="afterCropper">
<img :src="afterImg" alt="">
</div>
</div>
</div>
</div>
插件引用 vue自行引入
//图片截切插件 cropperjs 文档地址: https://fengyuanchen.github.io/cropper/
<script src="https://cdn.bootcdn.net/ajax/libs/exif-js/2.3.0/exif.js"></script>
<script type="text/javascript" src="/res/js/jquery-2.1.4.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/cropperjs/1.5.11/cropper.min.js"></script>
//截屏插件
<script type="text/javascript" src="/res/js/html2canvas.js"></script>
<script type="text/javascript" src="/res/js/canvas2image.js"></script>
//生成二维码插件 不需要二维码则不需要
<script type="text/javascript" src="/res/js/qrCode.js"></script>
变量
isAddImg: false,
postersImg: '/refactor/public/image/111.jpg',
posterImgHeight: 'auto',
isGeneratePosters: false, //是否生成图片
isShowUserImgUp: false, //是否显示用户未上传图片
isShowImgLoading: true,
appCode: '',
imgUrl: '/refactor/public/image/active_posters_home.png',
myCropper: null,
afterImg: '',
isShowTailoring: false,
mounted: function() {
this.init();
},
methods: {
init: function() {
this.getEwm(); //获取二维码
this.initCropper(); //初始话剪切框
},
getEwm() {
var self = this;
// var url = '';
// axios.get(url).then(function(data) {
self.drawFollowEwm('你的二维码地址');
// }).catch(function (error) {
// console.log(JSON.stringify(error));
// });
},
drawFollowEwm(url) {
new QRCode(document.getElementById('QRCodeNone'), url);
var myCanvas = document.getElementsByTagName('canvas')[0];
var img = this.convertCanvasToImage(myCanvas);
$("#qrcode").append(img);
var self = this;
$('#qrcode img').load(function() {
self.isShowImgLoading = false;
})
},
convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/jpg");
return image;
},
generateCanvas() {
// 截屏
var self = this;
var content = document.getElementById("poster_content");
var width = content.offsetWidth; //获取dom 宽度
var height = content.offsetHeight;
var scale = 4;
var canvas = document.createElement("canvas");
canvas.width = width * scale;
canvas.height = height * scale;
canvas.getContext("2d").scale(scale, scale);
html2canvas(content, {
useCORS: true, //允许跨域
width: width, //dom 原始宽度
height: height,
scale: scale,
dpi: window.devicePixelRatio,
taintTest: false
}).then((canvas) => {
var context = canvas.getContext('2d');
// 【重要】关闭抗锯齿
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
var img = Canvas2Image.convertToJPEG(canvas, canvas.width, canvas.height);
document.getElementById("canvas_img").appendChild(img);
self.isGeneratePosters = true;
setTimeout(function() {
self.isShowImgLoading = false;
}, 100);
$$.browsingHistory('auto_poster', 'activePosters', this.appCode);
})
},
isImgLoadComplete() {
if(!this.isAddImg) {
this.isShowUserImgUp = true;
return;
}
if(this.isGeneratePosters) {
return;
}
this.isShowImgLoading = true;
document.getElementById('s-page-content').scrollTop = 0;
this.inspectImgLoad();
},
inspectImgLoad() {
// 检查图片是否全都加载完成
var self = this;
var imgdefereds = [];
var imgs = $("#poster_content img");
imgs.each(function () {
var dfd = $.Deferred();
$(this).bind('load', function () {
dfd.resolve();
}).bind('error', function () {
//图片加载错误,加入错误处理
// dfd.resolve();
})
if (this.complete) setTimeout(function () {
dfd.resolve();
}, 1000);
imgdefereds.push(dfd);
})
$.when.apply(null, imgdefereds).done(function () {
self.generateCanvas();
self.posterImgHeight = $('.posters_img').width() * 1.5 + 'px';
})
},
addImg() {
$('#uploadImg').attr('type', 'file');
$('#uploadImg').trigger('click');
},
getImgUrl() {
var file = $('#uploadImg').get(0).files[0];
var _this = this;
_this.isShowImgLoading = true;
EXIF.getData(file, function() { // file input[type=file]的文件
EXIF.getAllTags(this);
var orientation = EXIF.getTag(this, 'Orientation'); //图片的旋转角度 针对ios
var str = navigator.userAgent.toLowerCase();
var ver = str.match(/cpu iphone os (.*?) like mac os/); //获取ios 系统版本
if(ver) {
var editionNum = parseFloat(ver[1].replace(/_/g, '.'));
// 注意: ios系统不同版本 横竖屏拍摄的照片会有旋转
if(editionNum > 13.5) { // 测试 大于13.5版本不需要旋转 非一定准确
_this.setImageUrl(_this.getObjectURL(file));
_this.isShowImgLoading = false;
return;
}
}
if(!orientation || 1 == orientation) {
if(_this.getObjectURL(file)) {
_this.setImageUrl(_this.getObjectURL(file));
_this.isShowImgLoading = false;
}
return;
}
// // 使用FileReader读取文件流,file为上传的文件流
const reader = new FileReader();
reader.readAsDataURL(file);
// /* eslint-disable func-names */
// // 箭头函数会改变this,所以这里不能用肩头函数
reader.onloadend = function () {
// this.result就是转化后的结果
const result = this.result;
// 将base64添加到图片标签上
const img = new Image();
img.src = result;
img.onload = function () {
// 这里添加旋转图片的代码
_this.getRotateImg(img, orientation, function(data) {
_this.setImageUrl(data);
_this.isShowImgLoading = false;
});
};
};
});
},
getRotateImg(img, or, callback) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 图片原始大小
const width = img.width;
const height = img.height;
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
switch (or) {
case 6: // 顺时针旋转90度
this.rotateImg(img, 'right', canvas, null, callback);
break;
case 8: // 逆时针旋转90度
this.rotateImg(img, 'left', canvas, null, callback);
break;
case 3: // 顺时针旋转180度
this.rotateImg(img, 'right', canvas, 2, callback);
break;
default:
break;
}
},
rotateImg (img, dir = 'right', canvas, s, callback) {
s = s ? s : 1;
const MIN_STEP = 0;
const MAX_STEP = 3;
const width = canvas.width || img.width;
const height = canvas.height || img.height;
let step = 0;
if (dir === 'right') {
step += s;
step > MAX_STEP && (step = MIN_STEP);
} else {
step -= s;
step < MIN_STEP && (step = MAX_STEP);
}
const degree = step * 90 * Math.PI / 180;
const ctx = canvas.getContext('2d');
switch (step) {
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height, width, height);
callback(canvas.toDataURL("image/jpeg", 0.8));
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height, width, height);
callback(canvas.toDataURL("image/jpeg", 0.8));
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0, width, height);
callback(canvas.toDataURL("image/jpeg", 0.8));
break;
default:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
callback(canvas.toDataURL("image/jpeg", 0.8));
break;
}
},
getObjectURL(file) {
var url = null;
if (window.createObjectURL!=undefined) {
url = window.createObjectURL(file) ;
} else if (window.URL!=undefined) { // mozilla(firefox)
url = window.URL.createObjectURL(file) ;
} else if (window.webkitURL!=undefined) { // webkit or chrome
url = window.webkitURL.createObjectURL(file) ;
}
return url ;
},
isLoad() {
this.posterImgHeight = $('.posters_img').width() * 1.5 + 'px';
},
initCropper() {
var self = this;
this.myCropper = new Cropper(this.$refs.image, {
aspectRatio: 1 / 1.5,
viewMode: 1,
dragMode: 'move',
initialAspectRatio: 1,
background: false,
autoCropArea: 0.9,
zoomOnWheel: false,
center: true,
movable: true,
cropBoxMovable: false,
})
},
setImageUrl(url) {
$('#uploadImg').attr('type', 'text')
this.isShowTailoring = true;
this.myCropper.replace(url, false);
},
sureSava() {
// 截切框 保存的图片
this.isShowTailoring = false;
this.postersImg = this.myCropper.getCroppedCanvas({
imageSmoothingQuality: 'high'
}).toDataURL('image/jpeg')
this.isAddImg = true;
},
hideTailoring() {
this.isShowTailoring = false;
}
}
希望对你有帮助!