아바타 업로드 처리를 위한 HTML5 Canvas 이미지 및 텍스트 코드에 대한 자세한 소개

黄舟
풀어 주다: 2017-03-07 16:02:15
원래의
1762명이 탐색했습니다.

최근 커뮤니티 시스템은 사용자 아바타 업로드와 관련된 모바일 단말기를 지원해야 합니다. 아바타는 대, 중, 소의 세 가지 크기로 제공됩니다. PC 측에서는 커뮤니티가 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'));
    };
};
로그인 후 복사

캔버스 요소 크기 제한 문제

clipSquareImage 함수에서는 canvas.toDataURL 인터페이스가 너비 및 높이 매개변수를 제공하지 않기 때문에 한 번에 전체 캔버스 화면 데이터만 캡처할 수 있으므로 캔버스의 스크린샷을 찍기 전에 먼저 캔버스 요소의 크기를 설정해야 합니다. 하지만 모바일 사진의 해상도는 매우 높으며 너비와 높이가 대부분 3000을 넘습니다. 사진의 최소 너비와 높이를 기준으로 Canvas의 크기를 설정할 때 Canvas 요소의 최소 너비도 다음과 같습니다. 3000 이상으로 높습니다.

문제는 각 플랫폼마다 캔버스 크기에 제한이 있다는 것입니다. 캔버스의 너비나 높이가 플랫폼 제한을 초과하면 캔버스는 렌더링할 수 없으며 canvas.toDataURL는 렌더링만 할 수 있습니다. 투명한 이미지 데이터를 얻습니다.

캔버스 요소의 최대 크기는 일부 플랫폼에서의 캔버스 크기 제한을 언급합니다.

chrome          = 32767x32767
iPod Touch 16GB = 1448x1448
iPad Mini       = 2290x2289
iPhone 3        = 1448x1448
iPhone 5        = 2290x2289
로그인 후 복사

위 데이터를 참조하여 먼저 캔버스의 최대 너비를 설정합니다.

var MAX_WIDTH = 1000;
로그인 후 복사

clipSquareImage 기능에 최대 너비 감지를 추가합니다. 제한을 초과하는 경우 이미지 크기 조정을 위한 임시 캔버스를 만들고 마지막으로 임시 캔버스를 중앙에서 자릅니다.

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에서는 drawImage 인터페이스가 매우 편리한 스케일링 기능을 제공합니다:

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

그러나 큰 이미지를 줄이기 위해 drawImage를 직접 사용하면 이미지가 들쭉날쭉하게 보일 수 있습니다. 스택 오버플로에서 HTML5 캔버스 drawImage: 안티앨리어싱 적용 방법 제안: 이미지를 같은 비율로 여러 번 줄이고 최종적으로 대상 크기로 확대:

아바타 업로드 처리를 위한 HTML5 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));
로그인 후 복사

참조

  • 다음을 사용하여 Base64로 인코딩된 캔버스 이미지를 png 파일에 저장합니다. PHP

  • Html5 canvas drawImage: 앤티앨리어싱 적용 방법

  • 캔버스 요소의 최대 크기

  • base64 데이터 문자열에서 서버측 PNG 이미지를 저장하는 방법

  • jQuery에서 Ajax 요청을 사용하여 FormData 객체를 보내는 방법

위 내용은 HTML5 Canvas 처리 아바타입니다. 업로드된 그래픽 코드를 자세히 소개하고 있으니 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!



관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿