前端(十八):移动端H5调用摄像头拍照旋转解决方案

简介: 移动端H5调用摄像头拍照旋转解决方案

展示

展示

布局样式

<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
    });
};
目录
相关文章
|
2月前
|
移动开发 前端开发 Android开发
mPaaS 常见问题之移动开发平台 mpaas的H5 前端 Kylin 框架引入vant后包特别大如何解决
mPaaS(移动平台即服务,Mobile Platform as a Service)是阿里巴巴集团提供的一套移动开发解决方案,它包含了一系列移动开发、测试、监控和运营的工具和服务。以下是mPaaS常见问题的汇总,旨在帮助开发者和企业用户解决在使用mPaaS产品过程中遇到的各种挑战
43 0
|
2月前
|
前端开发
前端跳转链接报错403的原因以及解决方案
前端跳转链接报错403的原因以及解决方案
144 1
|
2月前
|
JSON 前端开发 安全
前端开发中的跨域问题及解决方案
在前端开发中,跨域是一个常见但又令人头疼的问题。本文将深入探讨跨域产生的原因以及一些常见的解决方案,帮助开发者更好地理解和处理跨域情况。
|
18天前
|
Web App开发 移动开发 运维
跨域解决方案[前端+后端]
跨域解决方案[前端+后端]
25 0
|
28天前
|
前端开发
无法解锁/var/lib/dpkg/lock-frontend和无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend)【解决方案】
无法解锁/var/lib/dpkg/lock-frontend和无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend)【解决方案】
|
2月前
|
前端开发 JavaScript NoSQL
从前端到后端:构建全栈应用的技术挑战与解决方案
在当今互联网时代,全栈开发成为越来越受欢迎的技术趋势。本文将深入探讨从前端到后端的全栈开发过程中所面临的技术挑战,并提出相应的解决方案,涵盖前端框架选择、后端技术架构、数据库设计以及跨平台兼容性等关键问题。
|
2月前
|
前端开发
前端性能优化:掌握解决方案
我们常说性能永远是第一需求,作为一个前端工程师,不管使用什么框架,不管从事什么类型的网站或应用开发,只要是项目被用户使用,性能优化就永远是你需要关注的问题。通常情况下,工程师们在深入了解前端技术的原理后,才能总结出性能优化的方案,需要多年经验的积累。前端技术日新月异,优秀的性能优化方案在近几年也层出不穷。本课程带你使用当今行业中非常前沿&专业的方案,解决前端性能优化问题。无论是为了解决工作中的实际问题,还是为了提升能力,这门课都能帮到你。
15 2
前端性能优化:掌握解决方案
|
2月前
|
前端开发 安全 开发者
前端开发中的跨域资源共享(CORS)问题及解决方案探讨
在前端开发中,跨域资源共享(CORS)是一个常见且重要的问题。本文将深入探讨CORS的原理、影响以及解决方案,帮助开发者更好地应对跨域请求问题。
|
2月前
|
前端开发 JavaScript 容器
前端vw自适应解决方案,适用pc端以及移动端,适用webpack以及vite,适用vue以及react
前端vw自适应解决方案,适用pc端以及移动端,适用webpack以及vite,适用vue以及react
74 0
|
2月前
|
前端开发
前端播放第三方外链视频报403 forbidden的原因及解决方案
前端播放第三方外链视频报403 forbidden的原因及解决方案
67 0