展示

展示

布局样式

<script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>

<style>
    canvas{
        width: 200px;
        height: 200px;
        opacity: 0;
    }
    .upload{
        width: 200px;
        height: 200px;
        display: inline-block;
        border-radius: 10px;
        border: 1px dashed rgb(122, 201, 221);
        background-color: rgb(188, 224, 223);
        overflow: hidden;
        position: relative;
        display: inline-block;
    }
    #upload-img{
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
    input[type='file']{
        position: absolute;
        top: 0;
        left: 0;
        font-size: 1000%;
        opacity: 0;
    }
</style>
<div>
    <div class="upload">
        <img id="upload-img" src="" alt="">
        <input id="file" type="file" capture="camera" accept="image/*" onchange="handleFileChange(this)">
    </div>
    
    <canvas id="canvas" width="200" height="200"></canvas>
</div>

<script src="https://cdn.jsdelivr.net/npm/exif-js"></script>

逻辑

var vConsole = new VConsole();

/**
 * 监听调用摄像头
 */
async function handleFileChange(element) {
    var file = element.files[0];
    const or = await getImageTag(file);
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onloadend = function () {
        const result = this.result;
        const img = new Image();
        img.src = result;
        img.onload = function () {
            const data = getRotateImg(img, or);
            const f = dataURLtoFile(data);

            /*
            // 模拟上传文件后的回显
            const reader1 = new FileReader();
            reader1.readAsDataURL(f);
            reader1.onloadend = function () {
                const result1 = this.result;
                document.getElementById("upload-img").src = result1;
            }
            */
           
        };
    };
}

/**
 * @desc 获取图片旋转方向
 */
const getImageTag = (file) => {
    if (!file) return 0;
    return new Promise((resolve, reject) => {
        EXIF.getData(file, function () {
            const o = EXIF.getTag(this, 'Orientation');
            resolve(o); // 6 1 3 8
        });
    });
};

/**
 * @desc 获取旋转后的图片
 * @param {Object} img 图片文件
 * @param {Number} or 旋转信息
 */
function getRotateImg(img, or) {
    const canvas = document.getElementById('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度
            return rotateImg(img, 'right', canvas);
            break;
        case 8: // 逆时针旋转90度
            return rotateImg(img, 'left', canvas);
            break;
        case 3: // 顺时针旋转180度
            return rotateImg(img, 'right', canvas, 2);
            break;
        default:
            break;
    }
}

/**
 * @desc 旋转canvas,会对源数据canvas进行修改
 * @param {Object} img 图片文件
 * @param {String} dir 方向 left逆时针|right顺时针
 * @param {Object} canvas 画布
 * @param {Number} s 向指定方向旋转几步,1步为90度
 */
const rotateImg = (img, dir = 'right', canvas, 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);
            break;
        case 2:
            canvas.width = width;
            canvas.height = height;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, -height, width, height);
            break;
        case 3:
            canvas.width = height;
            canvas.height = width;
            ctx.rotate(degree);
            ctx.drawImage(img, -width, 0, width, height);
            break;
        default:
            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img, 0, 0, width, height);
            break;
    }

    return canvas.toDataURL('image/jpg');
};


/**
 * @desc 将base64的图片转为文件流
 * @param {String} dataUrl base64数据
 * @return {Object} 文件流
 */
const dataURLtoFile = (dataUrl) => {
    const filename = `img${Date.now()}`;
    const arr = dataUrl.split(',');
    const mime = arr[0].match(/:(.*?);/)[1];
    const bstr = atob(arr[1]);
    let n = bstr.length;
    const u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, {
        type: mime
    });
};
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐