前端(十八):移动端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
    });
};
目录
相关文章
|
8天前
|
JSON 前端开发 安全
前端开发中的跨域解决方案探究
跨域是前端开发中常见的问题之一,本文将探讨跨域的概念、产生的原因,以及常见的解决方案,包括JSONP、CORS、代理等。通过本文的学习,读者可以深入了解跨域问题及解决方案,为自己的前端开发工作提供参考。
|
8天前
|
JSON 前端开发 安全
前端开发中的跨域问题及解决方案
在前端开发中,跨域是一个常见但又令人头疼的问题。本文将深入探讨跨域产生的原因以及一些常见的解决方案,帮助开发者更好地理解和处理跨域情况。
|
2天前
|
Web App开发 前端开发 UED
前端开发之移动端体验优化
在一个前端项目中,面对移动端网页加载慢的问题,团队使用Chrome开发者工具和Lighthouse进行性能分析,发现资源加载、重绘回流和首屏空白是瓶颈。通过压缩图片和视频、使用懒加载、优化CSS样式、预加载内容及利用阿里云CDN,成功提升加载速度,改善用户体验,强调了前端性能优化的关键性。
76 0
前端开发之移动端体验优化
|
2天前
|
缓存 监控 前端开发
前端性能优化以及解决方案
前端性能优化关乎用户体验和网站竞争力,包括减少HTTP请求、使用CDN、压缩资源、延迟加载、利用浏览器缓存等策略。制定优化计划,使用监控工具,遵循最佳实践并持续学习,能提升网站速度和稳定性。
19 0
|
8天前
|
编解码 前端开发 JavaScript
【Web 前端】移动端适配方案有哪些?
【4月更文挑战第22天】【Web 前端】移动端适配方案有哪些?
|
8天前
|
前端开发 安全 JavaScript
有哪些常见的前端问题和解决方案
【4月更文挑战第13天】前端开发常见问题及解决方案:页面渲染性能优化(减少重绘、回流,利用GPU加速,代码拆分)、响应式设计(媒体查询、弹性布局)、浏览器兼容性(使用前缀,兼容性库,浏览器嗅探)、事件处理(事件委托、防抖节流)、代码组织(模块化、构建工具)、安全性(输入验证、HTTPS、安全HTTP头)和资源加载(CDN、资源优化、错误处理)。
30 6
|
8天前
|
Web App开发 移动开发 运维
跨域解决方案[前端+后端]
跨域解决方案[前端+后端]
36 0
|
8天前
|
前端开发
无法解锁/var/lib/dpkg/lock-frontend和无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend)【解决方案】
无法解锁/var/lib/dpkg/lock-frontend和无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend)【解决方案】
|
8天前
|
前端开发 JavaScript NoSQL
从前端到后端:构建全栈应用的技术挑战与解决方案
在当今互联网时代,全栈开发成为越来越受欢迎的技术趋势。本文将深入探讨从前端到后端的全栈开发过程中所面临的技术挑战,并提出相应的解决方案,涵盖前端框架选择、后端技术架构、数据库设计以及跨平台兼容性等关键问题。
|
8天前
|
前端开发
前端性能优化:掌握解决方案
我们常说性能永远是第一需求,作为一个前端工程师,不管使用什么框架,不管从事什么类型的网站或应用开发,只要是项目被用户使用,性能优化就永远是你需要关注的问题。通常情况下,工程师们在深入了解前端技术的原理后,才能总结出性能优化的方案,需要多年经验的积累。前端技术日新月异,优秀的性能优化方案在近几年也层出不穷。本课程带你使用当今行业中非常前沿&专业的方案,解决前端性能优化问题。无论是为了解决工作中的实际问题,还是为了提升能力,这门课都能帮到你。
18 2
前端性能优化:掌握解决方案