搜索
首页web前端H5教程HTML5 Canvas处理头像上传的图文代码详细介绍

最近社区系统需要支持移动端,其中涉及到用户头像上传,头像有大中小三种尺寸,在PC端,社区用Flash来处理头像编辑和生成,但该Flash控件的界面不友好而且移动端对Flash的支持不好,考虑到这些问题,最后我们选用Canvas来完成图像尺寸缩放和图片数据获取。

等边处理

头像一般都是正方形,首先我们需要获取图片宽度和高度的最小值,用该最小值作为边长居中裁剪图片,最终得到一个正方形的图片:

var ImageEditor = function() {
    // 用离线canvas处理图片数据
    this.canvas = document.createElement('canvas');
    this.context = this.canvas.getContext('2d');
};
var fn = ImageEditor.prototype;
fn.resizeCanvas = function(width, height) {
    this.canvas.width = width;
    this.canvas.height = height;
};
fn.clipSquareImage = function(url, callback) {
    var that = this,
        img = new Image();
    img.src = url;
    img.onload = function() {
        // 取宽高最小值作为正方形边长
        var eLength = Math.min(img.width, img.height),
            picture = img;
        // canvas不支持局部截屏,截屏前必须先调节canvas的宽高
        that.resizeCanvas(eLength, eLength);
        // 将图片以居中裁剪的方式画到canvas中。
        // drawImage支持9个参数:图片对象,图片上的剪切坐标XY,
        // 剪切宽高,图片在canvas上的坐标XY及图片宽高
        that.context.drawImage(picture,
            (picture.width - eLength) / 2, (picture.height - eLength) / 2,
            eLength, eLength, 0, 0, eLength, eLength);
        // 截屏,即获取base64数据
        callback.call(that, that.canvas.toDataURL('image/png'));
    };
};

Canvas元素大小限制问题

上述clipSquareImage函数中,由于canvas.toDataURL接口不提供宽高参数,只能够一次性把整个canvas的屏幕数据截取下来,所以在对Canvas截屏前,我们必须先设置Canvas元素的大小。然而移动端拍照的分辨率极高,宽高大多会在3000以上,当我们根据相片宽高的最小值来设置Canvas的尺寸时,Canvas元素的最小宽度也高达到3000以上。

问题在于,每个平台对Canvas的大小都有限制,如果Canvas的宽度或高度任意一个值超过了平台限制,Canvas将无法进行渲染,canvas.toDataURL只能获取一张透明的图片数据。

Maximum size of a canvas element中提到了部分平台下Canvas的尺寸限制:

chrome          = 32767x32767
iPod Touch 16GB = 1448x1448
iPad Mini       = 2290x2289
iPhone 3        = 1448x1448
iPhone 5        = 2290x2289

参考以上数据,我们先给Canvas设置一个最大的宽度:

var MAX_WIDTH = 1000;

clipSquareImage函数中加入最大宽度的检测,如果超过限制,则创建一个临时的canvas进行图片缩放处理,最后对该临时的Canvas进行居中剪切:

fn.clipSquareImage = function(url, callback) {
    var that = this,
        img = new Image();
    img.src = url;
    img.onload = function() {
         // 取图片宽高和Canvas的最大宽度的最小值作为等边长
        var eLength = Math.min(img.width, img.height, MAX_WIDTH),
            // 剪切对象
            picture = img,
            tempEditor,
            ratio;
            // 如果图片尺寸超出限制
            if (eLength === MAX_WIDTH) {
                // 创建一个临时editor
                tempEditor = new ImageEditor();
                ratio = img.width / img.height;
                // 按图片比例缩放canvas
                img.width < img.height ?
                    tempEditor.resizeCanvas(MAX_WIDTH * ratio, MAX_WIDTH) :
                    tempEditor.resizeCanvas(MAX_WIDTH, MAX_WIDTH / ratio);
                tempEditor.context.drawImage(img, 0, 0, tempEditor.canvas.width, tempEditor.canvas.height);
                // 将临时Canvas作为剪切对象
                picture = tempEditor.canvas;
                eLength = Math.min(tempEditor.canvas.width, tempEditor.canvas.height);
            }
            // 居中剪切
            // ... ...
            // 截屏操作
            // ... ...
    };
};

Canvas锯齿问题

上面我们已经能够通过Canvas裁剪出一张正方形的图片,接下来我们还需要处理头像图片大中小三种尺寸。在Canvas中,drawImage接口提供非常方便的缩放功能:

var editor = new ImageEditor;
// 将图片缩放到300x300
// drawImage支持5个参数:图片对象,及图片在canvas上的坐标和宽高
editor.context.drawImage(squareImage, 0, 0, 300, 300);

然而大尺寸图片直接用drawImage进行缩小处理会导致图片出现锯齿。在stack overflow上HTML5 canvas drawImage: how to apply antialiasing提出了一个方案:对图片进行若干次的等比例缩小,最后再放大到目标尺寸:

canvas高清缩放

参考这个方案,我们可以实现antialiasScale抗锯齿缩放函数:

fn.antialisScale = function(img, width, height) {
    var offlineCanvas = document.createElement(&#39;canvas&#39;),
        offlineCtx = offlineCanvas.getContext(&#39;2d&#39;),
        sourceWidth = img.width,
        sourceHeight = img.height,
        // 缩小操作的次数
        steps = Math.ceil(Math.log(sourceWidth / width) / Math.log(2)) - 1,
        i;
    // 渲染图片
    offlineCanvas.width = sourceWidth;
    offlineCanvas.height = sourceHeight;
    offlineCtx.drawImage(img, 0, 0, offlineCanvas.width, offlineCanvas.height);
    // 缩小操作
    // 进行steps次的减半缩小
    for(i = 0; i < steps; i++) {
        offlineCtx.drawImage(offlineCanvas, 0, 0,
            offlineCanvas.width * 0.5, offlineCanvas.height * 0.5);
    }
    // 放大操作
    // 进行steps次的两倍放大
    this.context.drawImage(offlineCanvas, 0, 0,
        offlineCanvas.width * Math.pow(0.5, steps), 
        offlineCanvas.height * Math.pow(0.5, steps),
        0, 0, width, height);
};

我们可以用这个函数代替drawImage完成缩放工作,生成头像图片的三种尺寸:

fn.scaleSquareImage = function(url, sizes, callback) {
    var that = this;
    // 先裁剪一个正方形
    that.clipSquareImage(url, sizes, function(data) {
        var squareImage = new Image(),
            result = [],
            i;
        squareImage.src = data;
        // 抗锯齿缩放
        for (i = 0; i < sizes.length; i++) {
            that.antialisScale(squareImage, sizes[i], size[i]);
            result.push(that.canvas.toDataURL(&#39;image/png&#39;));    
        }
        callback.call(that, result);
    });
};

PHP存储base64图片数据

Canvas.toDataURL()获取的默认图像数据格式是:data:image/png;base64, + base64数据:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC

当把Canvas截屏数据传给后台时,后台需要截断开头的字段data:image/png;base64,,获取后面那串真正的base64数据:

<?php
    $imgData = $_POST[&#39;imgData&#39;];
    // 截取有用的部分
    list($type, $imgData) = explode(&#39;;&#39;, $imgData);
    list(, $imgData)      = explode(&#39;,&#39;, $imgData);
    // base64 编码中使用了加号,
    // 如果通过url传递base64数据,+号会转换成空格
    $imgData = str_replace(&#39; &#39;, &#39;+&#39;, $imgData);
    // 存储文件
    $success = file_put_contents(&#39;PATH/XXX.png&#39;, base64_decode($imgData));

参考

  • Save a Base64 Encoded Canvas image to a png file using PHP

  • Html5 canvas drawImage: how to apply antialiasing

  • Maximum size of a canvas element

  • How to save a PNG image server-side, from a base64 data string

  • How to send FormData objects with Ajax-requests in jQuery

 以上就是HTML5 Canvas处理头像上传的图文代码详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!



声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
H5代码:Web结构的初学者指南H5代码:Web结构的初学者指南May 08, 2025 am 12:15 AM

HTML5构建网站的方法包括:1.使用语义化标签定义网页结构,如、、等;2.嵌入多媒体内容,使用和标签;3.应用表单验证和本地存储等高级功能。通过这些步骤,你可以创建一个结构清晰、功能丰富的现代网页。

H5代码结构:组织内容以实现可读性H5代码结构:组织内容以实现可读性May 07, 2025 am 12:06 AM

通过合理的H5代码结构可以让页面在众多内容中脱颖而出。1)使用语义化标签如、、等组织内容,使结构清晰。2)通过CSS布局如Flexbox或Grid控制页面在不同设备上的呈现效果。3)实现响应式设计,确保页面在不同屏幕尺寸上自适应。

H5与较旧的HTML版本:比较H5与较旧的HTML版本:比较May 06, 2025 am 12:09 AM

HTML5(H5)与旧版本HTML的主要区别包括:1)H5引入了语义化标签,2)支持多媒体内容,3)提供离线存储功能。H5通过新标签和API增强了网页的功能和表现力,如和标签,提高了用户体验和SEO效果,但需注意兼容性问题。

H5与HTML5:澄清术语和关系H5与HTML5:澄清术语和关系May 05, 2025 am 12:02 AM

H5和HTML5的区别在于:1)HTML5是网页标准,定义结构和内容;2)H5是基于HTML5的移动网页应用,适用于快速开发和营销。

HTML5特征:H5的核心HTML5特征:H5的核心May 04, 2025 am 12:05 AM

HTML5的核心特性包括语义化标签、多媒体支持、表单增强和离线存储与本地存储。1.语义化标签如、等提高了代码可读性和SEO效果。2.多媒体支持通过和标签简化了嵌入媒体内容的过程。3.表单增强引入了新的输入类型和验证属性,简化了表单开发。4.离线存储和本地存储通过ApplicationCache和localStorage等提高了网页性能和用户体验。

H5:探索最新版本的HTMLH5:探索最新版本的HTMLMay 03, 2025 am 12:14 AM

html5isamajorrevisionofthehtmlStandardThatRevolutionsWebDevelopmentBybyIntroDucingNewSemanticeLementSemelementsandAndCapabilities.1)itenhancesCodereAdabilityAndSeowitability andSeowithelientsLike,and.2)

超越基础:H5代码中的高级技术超越基础:H5代码中的高级技术May 02, 2025 am 12:03 AM

H5的高级技巧包括:1.利用进行复杂图形绘制,2.使用WebWorkers提升性能,3.通过WebStorage增强用户体验,4.实现响应式设计,5.利用WebRTC实现实时通信,6.进行性能优化和最佳实践。这些技巧帮助开发者构建更动态、互动和高效的Web应用。

H5:网络内容和设计的未来H5:网络内容和设计的未来May 01, 2025 am 12:12 AM

H5(HTML5)将通过新元素和API提升网页内容和设计。1)H5增强了语义化标记和多媒体支持。2)它引入了Canvas和SVG,丰富了网页设计。3)H5的工作原理是通过新标签和API扩展HTML功能。4)基本用法包括使用创建图形,高级用法涉及WebStorageAPI。5)开发者需注意浏览器兼容性和性能优化。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用