1, the picture components
<template>
<div class="imgWrap">
<p class="titleImgWrap">{{Imgtitle}}</p>
<div class="imgBtn">
<span>+</span>
<input style ref="file" type="file" id="upload" accept="image/*" @change="upload">
</div>
</div>
</template>
<script>
import EXIF from "@/utils/small-exif"
export default {
props: {
photoEventNumber: Number,
Imgtitle:String
},
data() {
return {
headerImage: "",
picValue: ""
};
},
mounted() {},
watch: {
photoEventNumber: {
handler() {
var userAgent = navigator.userAgent;
var el = this.$refs.file;
}
}
},
methods: {
upload (e) {
let files = e.target.files || e.dataTransfer.files;
if (!files.length) return;
this.picValue = files[0];
this.imgPreview(this.picValue);
},
imgPreview(file) {
let self = this;
let Orientation;
// to get information when taking pictures, the pictures are rotated to solve the problem
EXIF.getData(file, function () {
Orientation = EXIF.getTag(this, 'Orientation');
});
// FileReader look Yes No
if (!file || !window.FileReader) return;
if (/^image/.test(file.type)) {
// Create a reader
let reader = new FileReader();
// 2 will turn the picture into base64 format
reader.readAsDataURL(file);
After reading success callback //
reader.onloadend = function() {
let result = this.result;
let img = new Image();
img.src = result;
// determine whether the image is greater than 100K, it is uploaded directly, and vice versa compressed picture
if (this.result.length <= 100 * 1024) {
self.headerImage = this.result;
self.postImg ();
} else {
img.onload = function() {
let data = self.compress(img, Orientation);
self.headerImage = data;
self.postImg ();
};
}
};
}
},
Postimg () {
// Here write interface
var photoFile = this.convertBase64UrlToBlob(this.headerImage);
var photo = {};
photo.base64 = this.headerImage;
photo.file = photoFile;
this.$emit("photoData", photo);
},
/ * Url picture will be base64 data into a Blob
* @Param urlData
* Base64 url picture represented by way of data
*/
convertBase64UrlToBlob (URLData) {
var bytes = window.atob (urlData.split ( ",") [1]); // url removing the head, and to a byte
// handle exceptions, will be less than the conversion ascii code 0 is greater than 0
var ab = new ArrayBuffer(bytes.length);
She var = new Uint8Array (ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], {
type: "image/png"
});
},
rotateImg(img, direction, canvas) {
// the minimum and maximum rotational direction, the fourth back to the original picture rotation direction
const min_step = 0;
const max_step = 3;
if (img == null) return;
// img height and width can not be obtained after the img element hiding, or an error occurs
let height = img.height;
let width = img.width;
let step = 2;
if (step == null) {
step = min_step;
}
if (direction == "right") {
step++;
// rotation to the original position, i.e., exceeds the maximum value
step > max_step && (step = min_step);
} else {
step--;
step < min_step && (step = max_step);
}
// rotation angle parameter value in radians
let degree = (step * 90 * Math.PI) / 180;
let ctx = canvas.getContext("2d");
switch (step) {
case 0:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
break;
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height);
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height);
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0);
break;
}
},
compress(img, Orientation) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
// tile canvas
let tCanvas = document.createElement("canvas");
let tctx = tCanvas.getContext("2d");
let initSize = img.src.length;
let width = img.width;
let height = img.height;
// If the picture is greater than four megapixels, calculate the compression ratio and the size of the pressure to 400 million or less
let ratio;
if ((ratio = (width * height) / 4000000) > 1) {
ratio = Math.sqrt(ratio);
width /= ratio;
height /= ratio;
} else {
ratio = 1;
}
canvas.width = width;
canvas.height = height;
// color BEDDING
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// If the picture is larger than 1 million pixels using tiles draw
let count;
if ((count = (width * height) / 1000000) > 1) {
count = ~~ (Math.sqrt (count) + 1); // calculate how many blocks to be divided into tiles
// Calculate the width and height of each tile
let nw = ~~(width / count);
let nh = ~~(height / count);
tCanvas.width = nw;
tCanvas.height = nh;
for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
tctx.drawImage(
img,
i * nw * ratio,
j * nh * ratio,
nw * ratio,
nh * ratio,
0,
0,
nw,
nh
);
ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
}
}
} else {
ctx.drawImage(img, 0, 0, width, height);
}
// repair ios time to upload the pictures are rotated problem
if (Orientation != "" && Orientation != 1) {
switch (Orientation) {
case 6: // need clockwise (left) 90 degree rotation
this.rotateImg(img, "left", canvas);
break;
case 8: // need counterclockwise (right) 90 degree rotation
this.rotateImg(img, "right", canvas);
break;
case 3: // 180 degree rotation required
this.rotateImg (img, "right", canvas); // turn twice
this.rotateImg(img, "right", canvas);
break;
}
}
// minimal compression
let ndata = canvas.toDataURL ( "Image / JPEG", 0.1);
tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
ndata return;
}
}
};
</script>
<style scoped>
* {
margin: 0;
padding: 0;
}
.imgWrap {
display: flex;
align-items: center;
padding: 20px 0;
}
p.titleImgWrap {
font-size: 0.37333rem;
color: #333a44;
padding: 0.26667rem 0.4rem;
}
.imgBtn {
position: relative;
width: 60px;
height: 60px;
background: rgba(242, 246, 252, 1);
text-align: center;
line-height: 60px;
}
.show {
width: 200px;
height: 200px;
overflow: hidden;
position: relative;
border: 1px solid #d5d5d5;
}
.picture {
width: 100%;
height: 100%;
overflow: hidden;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
}
input {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0;
}
</style>
2, using the parent component
html:
<div @click="uploadPhoto">
<uploaderImg :photoEventNumber="photoEventNumber" @photoData="getData" :Imgtitle="Imgtitle"></uploaderImg>
</div>
<div class="showImgs" v-if="imgBase64 && imgBase64.length > 0">
<p v-for="(item,index) in imgBase64" :key="index">
<img :src="BASE_IMG_URL+item" @click="preview(index)">
<span @click="delImg(index)">删除</span>
</p>
</div>
<van-image-preview v-model="show" :images="imgList" showIndex :startPosition="startPosition"></van-image-preview>
</van-cell-group>
js:
data(){
return{
imgBase64: [],
Imgtitle: "Sales contract"
imgList: [],
photo: "",
BASE_IMG_URL: BASE_URL_IMG,
starting position: 0
applicationStepsNeedData: {
type: 3
},
applicationId: "",
photoEventNumber: 1,
}}
methods:{
//upload image
uploadPhoto() {
this.photoEventNumber = ++this.photoEventNumber;
},
getData(datas) {
this.photo = datas.file;
. This $ toast ( "Uploading ...");
uploadImg(this.photo)
.then(res => {
if (res.code == 200) {
this.imgBase64.push(res.msg);
}
})
.catch(err => {
. This $ toast ( "upload failed, please try again");
console.log(err);
});
},
//preview picture
preview(i) {
this.startPosition = i;
this.show = true;
this.imgList = [];
this.imgBase64.map(item => {
this.imgList.push(this.BASE_IMG_URL + item);
});
// console.log(this.imgList);
},
// delete pictures
delImg(index) {
this.imgBase64.splice(index, 1);
},
}
exft.js
was EXIF = {};
var TiffTags = EXIF.TiffTags = {
0x0112: "Orientation"
};
function imageHasData(img) {
return !!(img.exifdata);
}
function getImageData(img, callback) {
function handleBinaryFile(binFile) {
was findEXIFinJPEG data = (binFile);
img.exifdata = data || {};
if (callback) {
callback.call(img);
}
}
if (window.FileReader && (img instanceof window.Blob || img instanceof window.File)) {
var fileReader = new FileReader();
fileReader.onload = function (e) {
handleBinaryFile(e.target.result);
};
fileReader.readAsArrayBuffer(img);
}
}
function findEXIFinJPEG(file) {
var dataView = new DataView(file);
if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {
return false; // not a valid jpeg
}
was offset = 2,
length = file.byteLength,
marker;
while (offset < length) {
if (dataView.getUint8(offset) != 0xFF) {
return false; // not a valid marker, something is wrong
}
marker = dataView.getUint8(offset + 1);
if (marker == 225) {
return readEXIFData(dataView, offset + 4, dataView.getUint16(offset + 2) - 2);
} else {
offset += 2 + dataView.getUint16(offset + 2);
}
}
}
function readTags(file, tiffStart, dirStart, strings, bigEnd) {
var entries = file.getUint16(dirStart, !bigEnd),
tags = {},
entryOffset, tag,
i;
for (i = 0; i < entries; i++) {
entryOffset = dirStart + i * 12 + 2;
tag = strings[file.getUint16(entryOffset, !bigEnd)];
tags[tag] = readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd);
}
return tags;
}
function readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd) {
var type = file.getUint16(entryOffset + 2, !bigEnd),
numValues = file.getUint32(entryOffset + 4, !bigEnd),
valueOffset = file.getUint32(entryOffset + 8, !bigEnd) + tiffStart,
offset,
vals, val, n,
numerator, denominator;
switch (type) {
case 1: // byte, 8-bit unsigned int
case 7: // undefined, 8-bit byte, value depending on field
if (numValues == 1) {
return file.getUint8(entryOffset + 8, !bigEnd);
} else {
offset = numValues > 4 ? valueOffset : (entryOffset + 8);
false = [];
for (n = 0; n < numValues; n++) {
vals[n] = file.getUint8(offset + n);
}
return vals;
}
case 2: // ascii, 8-bit byte
offset = numValues > 4 ? valueOffset : (entryOffset + 8);
return getStringFromDB(file, offset, numValues - 1);
case 3: // short, 16 bit int
if (numValues == 1) {
return file.getUint16(entryOffset + 8, !bigEnd);
} else {
offset = numValues > 2 ? valueOffset : (entryOffset + 8);
false = [];
for (n = 0; n < numValues; n++) {
vals[n] = file.getUint16(offset + 2 * n, !bigEnd);
}
return vals;
}
case 4: // long, 32 bit int
if (numValues == 1) {
return file.getUint32(entryOffset + 8, !bigEnd);
} else {
false = [];
for (n = 0; n < numValues; n++) {
vals[n] = file.getUint32(valueOffset + 4 * n, !bigEnd);
}
return vals;
}
case 5: // rational = two long values, first is numerator, second is denominator
if (numValues == 1) {
numerator = file.getUint32(valueOffset, !bigEnd);
denominator = file.getUint32(valueOffset + 4, !bigEnd);
val = new Number(numerator / denominator);
val.numerator = numerator;
val.denominator = denominator;
return val;
} else {
false = [];
for (n = 0; n < numValues; n++) {
numerator = file.getUint32(valueOffset + 8 * n, !bigEnd);
denominator = file.getUint32(valueOffset + 4 + 8 * n, !bigEnd);
vals[n] = new Number(numerator / denominator);
vals[n].numerator = numerator;
vals[n].denominator = denominator;
}
return vals;
}
case 9: // slong, 32 bit signed int
if (numValues == 1) {
return file.getInt32(entryOffset + 8, !bigEnd);
} else {
false = [];
for (n = 0; n < numValues; n++) {
false [n] = file.getInt32 (Offset value + 4 * n, BIGEND!);
}
return vals;
}
case 10: // signed rational, two slongs, first is numerator, second is denominator
if (numValues == 1) {
return file.getInt32(valueOffset, !bigEnd) / file.getInt32(valueOffset + 4, !bigEnd);
} else {
false = [];
for (n = 0; n < numValues; n++) {
false [n] = file.getInt32 (offset value + 8 * n, BIGEND!) / file.getInt32 (Offset value + 4 + 8 * n, BIGEND!);
}
return vals;
}
}
}
function getStringFromDB(buffer, start, length) {
var outstr = "";
for (var n = start; n < start + length; n++) {
outstr += String.fromCharCode(buffer.getUint8(n));
}
return outstr;
}
function readEXIFData(file, start) {
if (getStringFromDB(file, start, 4) != "Exif") {
return false;
}
was bigEnd,
tags, tag,
exifData, GPS data,
tiffOffset = start + 6;
// test for TIFF validity and endianness
if (file.getUint16(tiffOffset) == 0x4949) {
bigEnd = false;
} else if (file.getUint16(tiffOffset) == 0x4D4D) {
bigEnd = true;
} else {
return false;
}
if (file.getUint16(tiffOffset + 2, !bigEnd) != 0x002A) {
return false;
}
var firstIFDOffset = file.getUint32(tiffOffset + 4, !bigEnd);
if (firstIFDOffset < 0x00000008) {
return false;
}
tags = readTags(file, tiffOffset, tiffOffset + firstIFDOffset, TiffTags, bigEnd);
return tags;
}
EXIF.getData = function (img, callback) {
if ((img instanceof Image || img instanceof HTMLImageElement) && !img.complete) return false;
if (!imageHasData(img)) {
getImageData(img, callback);
} else {
if (callback) {
callback.call(img);
}
}
return true;
}
EXIF.getTag = function (img, tag) {
if (!imageHasData(img)) return;
return img.exifdata[tag];
}
export default EXIF
// page introduction way import EXIF from "@ / utils / small-exif"