威尼斯手机平台登陆-官方网站登录

威尼斯手机平台登陆为您带来世界三大博彩公司最新相关资讯,威尼斯官方网站登录充分考虑到不同地域网民的不同需求,威尼斯手机平台登陆良好的用户界面,人性化的操作,实用的功能设计使其广泛受到欢迎,推动实体出版、影视、动漫、游戏等相关文化产业的发展。

您的位置:威尼斯手机平台登陆 > 前端资源 > 威尼斯登录首页canvas 标记的应用功能图像显示和处理,头像有大中小三种尺寸

威尼斯登录首页canvas 标记的应用功能图像显示和处理,头像有大中小三种尺寸

发布时间:2020-03-04 19:11编辑:前端资源浏览(109)

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

    本文是从 HTML5 Canvas Tutorial – Displaying Images 这篇文章翻译而来。

    canvas剪裁图片并上传,前端一步到位,无需用到后端

    背景:

         当前主流的图片剪裁主要有两种实现方式。

         1:flash操作剪裁。2:利用js和dom操作剪裁。

         目前看来这个剪裁主要还是先通过前端上传图片到服务器,然后前端操作后把一些坐标和大小数据传到后台,

    然后后台来执行剪裁。我一直觉得这样有很多问题:

         1.必须要先把图片上传到服务器然后才能执行后面的操作

         2.前后端交互太多,需要几次交互数据

     

    老的实现方法太low了。我想试试canvas来实现剪裁,就网上搜索了下,是有一些canvas剪裁,类似Jcrop这种。但是我发现好多canvas的插件,

    本质还是需要先上传到后台,最后还是后端剪裁,和之前的方式一样,只是用了canvas而已。

     

    自己实现前端剪裁一步到位:

      后来我就想了想canvas能存储base64,就用base64传到后端。

          大致思路是这样的:

               -> 表单选择图片

        -> 读取图片,用FileReader获取到原图的base64码

        -> new 一个image,把base64传给src,然后就可以用这个对象

        -> 需要两个canvas,一个canvas是完整的在下层,一个canvas是我们要剪裁的区域在上层

          (因为canvas不能分层,两个重叠的canvas,下层那个canvas保持不动,上层显示我们要剪裁的区域)

          如图:黑色透明的是下层的原图,箭头指向的是上层显示区域。

          威尼斯登录首页 1

        -> 上图的剪裁区域可以移动和放大,点击保存就会再用一个canvas把剪裁区域 按照原图大小画出来,最后把canvas对象用toDataURL()获取为base64码,就可以上传了。

     

    实现起来有一些技术点:

          1.可以自定义 剪裁的图片的比例和最小尺寸,比如下面,设置了原图的宽高必须大于640px,同时剪裁的比例也始终为width :height,当前就是1:1

    this._option.crop_min_width = 640;
    this._option.crop_min_height = 640;
    

    2.可以自定义 剪裁的容器大小,比如,你只希望它在某个小区域里执行剪裁,设置了这个大小后,会按照正确的比例,把原图缩放在这个容器里供用户操作

    this._option.crop_box_width = 300;
     this._option.crop_box_height = 200;
    
    1. 实现显示区域的拖动和显示区域的大小改变。

      4. 需要给剪裁容器包括里面的节点都添加上css3属性 user-select:none。否则会出现拖动的canvas的bug

    -webkit-user-select:none;-moz-user-select:none;-o-user-select:none;user-select:none
    

    代码写得很乱,封装的也不好,但是实现了想要的功能,点击保存会显示剪裁的图片按照原图比例,获取到的base64码会在控制台里打印出来。

    默认要选择640*640以上的图片,以下是git地址,拉下来试试吧,也许这个方案是一个非常好的方式。

      github地址 https://github.com/zimv/zmCanvasCrop

     

    html5 canvas 自定义画图裁剪图片

    html5 给我们带来了极大惊喜的canvas标签,有了它我们可以在浏览器客户端处理图片,不需要经过服务器周转。可以实现:

     

    1、照片本地处理,ps有的一些基本功能都有

    2、结合js可以实现一些很炫的动画效果

     

    这篇文章实现一个微信上发图片消息的效果最终效果图:

     

    威尼斯登录首页 2

     

     

    下面我们先介绍canvas一些基本的用法,这里可能需要一些基本的几何知识,对小伙伴们来说应该不是问题

    1、创建一个canvas

           var canvas=document.createElement('canvas');或者获取一个已存在的canvas,var canvas=document.getElementById('canvasid');

                 canvas.width=1000;canvas.height=1000;//定义大小

    2、创建绘图的上下文

           var context=canvas.getContext('2d');

    3、画直线

          context.beiginPath();//开始画图

          context.moveTo(100,50) ;//这个方法类似于我们写字时提笔动作,即把笔提起来,放到指定坐标处

          context.lineTo(100,100);//由(100,50)处画到(100,100)处

          context.lienWidth=2;//定义笔的粗细

          context.strokeStyle='red';//定义笔的颜色

          context.stroke();//以指定的粗细和颜色描绘路径。前面的只是有了路径,必须用stroke方法进行描绘,否则看不到任何效果 

    威尼斯登录首页 3

    4、画实心三角形

         context.beginPath();

         context.moveTo(100,110);

         context.lineTo(100,210);

         context.lienTo(150,210);

         //context.lineTo(100,110);//这句要不要都无所谓,因为后面的fill方法自动会将路径闭合

         context.fillStyle=‘green’;//填充颜色

         context.fill();//开始填充  

    威尼斯登录首页 4

    5、画空心三角形(直线加斜线组合)

          context.beiginPath();

          context.moveTo(100,220);

          context.lineTo(100,320);

          context.lineTo(150,320);

          context.closePath();//关闭路径 ,用context.lineTo(100,220)继续画完也可以

          context.lineWidth=3;

          context.stroke();

      威尼斯登录首页 5

    6、画正方形(直线加斜线组合)

          context.beginPath();
          context.moveTo(100,330);
          context.lineJoin='round';
          context.lineTo(100,430);
          context.lineTo(200,430);
          context.lineTo(200,330);
          context.closePath();
          context.lineWidth=10;
          context.strokeStyle='blue';
          context.stroke();

           威尼斯登录首页 6

         眼尖的小伙伴们应该注意到了,四个拐角是圆的,对的,就是context.lineJoin='round'的功劳,除了round还有bevel(斜角)和miter(尖角),默认miter

    7、画圆

          context.beginPath(); 
          context.arc(150500,50,0,2*Math.PI);
          context.lineWidth=2;
          context.strokeStyle='orange';
          context.stroke();  

                威尼斯登录首页 7

     

    8、画曲线

     

         context.beginPath();
         context.moveTo(100,600);
         context.quadraticCurveTo(150,650,100,700);//(150,600)为控制点,(100,700)为曲线终点。可以指定多个控制点,能更精确的控制曲线的走向
         context.stroke();

     

                             威尼斯登录首页 8

    9、裁剪

          //加载图片

          var image=new Image();
          image.src='..Penguins.jpg';

         image.onload=function(){

          context.beginPath();

           //画裁剪区域,此处以圆为例

           context.arc(50,50,50,0,2*Math.PI);
           context.clip();//次方法下面的部分为待剪切区域,上面的部分为剪切区域

           context.drawImage(image,0,0,100,100);

    }

            威尼斯登录首页 9

          

     

     

    注意:

            1、stroke()方法比较耗性能,如果描绘的样式一样的话建议放在最后执行

            2、用slip方法画裁剪区域过程中不能出现moveTo提笔的操作,否则无法形成完整的区域,剪切的效果大家可以试试。

     

    看完以上例子是不是对我们最终要实现的效果有清晰的思路了。

    4条直接+4个圆角+2条斜线就可实现。直线和斜线好画,关键在于圆角,有人说直接用lineJoin不就搞定了吗,大家要清楚,lineJoin画出来的圆角角度大小是根据lineWidth确定的,要达到我们要实现的圆角角度,上面画正方形的圆角lineWidth=10,可我们的图片边框要这么粗?显然不符合要求,且难以控制圆角角度。最佳的办法就是用quadraticCurveTo画曲线替换,关键在于确定曲线的三个点:起点,控制点和终点,下面是完整的代码:

     

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>   
        <script type="text/JavaScript">

            
            window.onload=function(){

                    var image=new Image();

                    image.src='..Penguins.jpg';   

                    image.onload=function(){

                    var canvas=document.createElement('canvas');

                    canvas.width=106;

                    canvas.height=100;

                    context=canvas.getContext('2d');

                    context.moveTo(0, 6);
                    context.lineTo(0, 100-6);
                    context.quadraticCurveTo(0, 100, 6, 100);
                    context.lineTo(100-6, 100);
                    context.quadraticCurveTo(100, 100, 100, 100-6);
                    context.lineTo(100,27);
                    context.lineTo(100+5,22);
                    context.lineTo(100,17);
                    context.lineTo(100, 6);
                    context.quadraticCurveTo(100, 0, 100-6, 0);
                    context.lineTo(6, 0);
                    context.quadraticCurveTo(0, 0, 0, 6);
                    context.lineWidth=0.5;

                    context.stroke();

                    context.clip();

                    context.drawImage(image,0,0,106,100);

                    document.body.appendChild(canvas);

                    }

    }
        </script>
    </head>
    <body style="margin:0px;padding:0px;">
    </body>
    </html>最终效果图:

    威尼斯登录首页 10

    当初为实现这个效果,因为刚接触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'));
        };
    };
    

     

    HTML5 Canvas 实现图片压缩和裁切

    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);
                }
                // 居中剪切
                // ... ...
                // 截屏操作
                // ... ...
        };
    };
    

     

    HTML5 Canvas 实现图片压缩和裁切

    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提出了一个方案:对图片进行若干次的等比例缩小,最后再放大到目标尺寸:

    威尼斯登录首页 11

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

    fn.antialisScale = function(img, width, height) {
        var offlineCanvas = document.createElement('canvas'),
            offlineCtx = offlineCanvas.getContext('2d'),
            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('image/png'));    
            }
            callback.call(that, result);
        });
    };
    

    Canvas 标记很多年前就被当作一个新的 HTML 标记成员加入到了 HTML5 标准中。在此之前,人们要想实现动态的网页应用,只能借助于第三方的插件,比如 Flash 或 Java,而引入了 Canvas 标记后,人们直接打通了通往神奇的动态应用网页的大门。本教程内容只覆盖了一小部分、但却是非常重要的 canvas 标记的应用功能图像显示和处理。

    前面的话

    早些时候用 Node-webkit (现在叫 nw.js) 编写过一个辅助前端切图的工具,其中图片处理部分用到了 gm ,gm 虽然功能强大,但用于 Node-webkit 却有点发挥不了用处,gm 强依赖于用户的本地环境安装 imagemagick 和 graphicsmagick ,而安装 imagemagick 和 graphicsmagick 非常不方便,有时候还需要FQ,所以这个工具大多数时候是我自己在玩。

    为了降低安装成本,这两天开始研究去掉图片处理功能中的 gm 依赖,替换为 HTML5 Canvas 来实现。

    在这之前没有深入研究过 canvas,通过这两天的查资料过程,发现 canvas 的 API 非常丰富,实现本文的功能可以说只用到了 canvas 的冰山一角。

    功能实现主要用到了 CanvasRenderingContext2D.drawImage 和 HTMLCanvasElement.toDataURL 两个方法,接下来先介绍一下这两个方法,如果想直接看结果,可以跳到文章结尾查看完整的例子和代码。

    PHP存储base64图片数据

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

    data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC
    

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

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

     

    CanvasRenderingContext2D.drawImage()

    drawImage 方法是 Canvas 2D 对象的方法,作用是将一张图片绘制到 canvas 画布中。

    创建一个 Canvas 2D 对象:

    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    

    drawImage 有 3 种调用方式:

    ctx.drawImage(image, dx, dy);
    ctx.drawImage(image, dx, dy, dWidth, dHeight);
    ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
    

    各个参数的意义:

    • image 图片元素,除了图片,还支持其他 3 种格式,分别是 HTMLVideoElement HTMLCanvasElement ImageBitmap ,本文只涉及图片,如果想了解其余格式可以参考这里
    • sx 要绘制到 canvas 画布的源图片区域(矩形)在 X 轴上的偏移量(相对源图片左上角)
    • sy 与 sx 同理,只是换成 Y 轴
    • sWidth 要绘制到 canvas 画布中的源图片区域的宽度,如果没有指定这个值,宽度则是 sx 到图片最右边的距离
    • sHeight 要绘制到画布中的源图片区域的高度,如果没有指定这个值,高度则是 sy 到图片最下边的距离
    • dx 源图片左上角在 canvas 画布 X 轴上的偏移量
    • dy 源图片左上角在画布 Y 轴上的偏移量
    • dWidth 绘制图片的 canvas 画布宽度
    • dHeight 绘制图片的画布高度

    是不是有点晕了?下面这张图可以直观地说明它们的关系:

    威尼斯登录首页 12

    还是不好理解?那换个姿势,可以这么理解:首先用 sx 和 sy 这两个值去定位图片上的坐标,再根据这个坐标点去图片中挖出一个矩形,矩形的宽高就是 sWidth 和 sHeight 了。矩形挖出来了,现在要把它绘制到画布中去,这时用 dx 和 dy 两个值来确定矩形在画布中的坐标位置,再用 dWidth 和 dHeight 确定划出多少画布区域给这个矩形。

    参考

    • 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

    图像来源

    HTMLCanvasElement.toDataURL()

    toDataURL 是 canvas 画布元素的方法,返回指定图片格式的 data URI,也就是 base64 编码串。

    toDataURL 方法最多接受两个参数,并且这两个参数都是可选的:

    • type 图片格式。支持 3 种格式,分别是 image/jpeg image/png image/webp ,默认是 image/png 。其中 image/webp 只有 chrome 才支持。
    • quality 图片质量。0 到 1 之间的数字,并且只在格式为 image/jpeg 或 image/webp 时才有效,如果参数值格式不合法,将会被忽略并使用默认值。

    另外,如果对应的 canvas 画布宽度或高度为 0,将会得到字符串 data:, ,若图片格式不是 image/png,却得到一个以 data:image/png 开头的值,则说明不支持此图片格式。

     

    图片质量

    对于图片质量参数的默认值,官方文档并没有说明, 这里 提到 Firefox 的默认值是 0.92,我在最新 chrome 浏览器中测试发现大概也是这个数字。不过要想达到各平台统一表现,最好的办法是手动设置此参数。

    最常见的在 canvas 上画图的方法是使用 Javascript Image 对象。所支持的来源图片格式依赖于浏览器的支持,然而,一些典型的图片格式(png,jpg,gif 等)基本上都没有问题。

    实现图片压缩的关键代码

    HTML:

    <canvas id="canvas"></canvas>
    <img id="preview" src="">
    <img id="source" src="" style="display: none;">
    

    JS:

    var canvas = document.getElementById('canvas');
    var source = document.getElementById('source');
    var preview = document.getElementById('preview');
    
    source.onload = function() {
        var width = source.width;
        var height = source.height;
        var context = canvas.getContext('2d');
    
        // draw image params
        var sx = 0;
        var sy = 0;
        var sWidth = width;
        var sHeight = height;
        var dx = 0;
        var dy = 0;
        var dWidth = width;
        var dHeight = height;
        var quality = 0.92;
    
        canvas.width = width;
        canvas.height = height;
    
        context.drawImage(source, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
    
        var dataUrl = canvas.toDataURL('image/jpeg', quality);
        preview.src = dataUrl;
    };
    
    source.src = 'house.jpg';
    

    编写了一个简单的 Demo ,可输入质量参数查看压缩结果。

     

    图片压缩结果

    用作测试的是一张大小为 146 KB 的 JPG 图片。

    威尼斯登录首页 13

    测试过程分别使用了 50%, 80%, 92%, 95%, 96%, 97%, 98%, 99%, 100% 这八个质量参数,结果如下:

    威尼斯登录首页 14

    查看原图

    换算成图表:

    威尼斯登录首页 15

    图片可以从 DOM 中已经加载的元素中抓取,也可以按需即时创建。

    问题

    从图表中可以看到,压缩比为 95% 时与原图大小最接近,此后,随着压缩参数增大直到 98%,增长比较规律,但从 98 到 99 尤其是 99 到 100,增长突然变陡,比原图大小翻了将近 3 倍!

    这里存在两个问题:

    • 为什么 95% 是最接近原图的压缩比?这是否普遍规律?
    • 为什么 100% 比原图增大了这么多?

    在网上查了一些资料,但并没有找到确切的原因,也没有找到与之相匹配的类似问题。或许是我搜索的方式不对?如果你正好知道,欢迎留言告知。

     

    实现图片裁切的不完全代码

    function cropImage(targetCanvas, x, y, width, height) {
        var targetctx = targetCanvas.getContext('2d');
        var targetctxImageData = targetctx.getImageData(x, y, width, height); // sx, sy, sWidth, sHeight
    
        var c = document.createElement('canvas');
        var ctx = c.getContext('2d');
    
        c.width = width;
        c.height = height;
    
        ctx.rect(0, 0, width, height);
        ctx.fillStyle = 'white';
        ctx.fill();
        ctx.putImageData(targetctxImageData, 0, 0); // imageData, dx, dy
    
        document.getElementById('source2').src = c.toDataURL('image/jpeg', 0.92);
        document.getElementById('source2').style.display = 'initial';
    }
    

    以上代码中,getImageData 和 putImageData 都是 Canvas 2D 对象的方法,前者用于获取画布上根据参数指定矩形的像素数据,返回的是一个多维数组。后者则用于将这些像素数据绘制到画布中,同样可以指定画布中的绘制位置。

    裁切的原理是通过 canvas A 的 getImageData 方法取出图片中指定区域的像素数据,再用 canvas B 的 putImageData 方法将像素数据绘制到 canvas B 中,并保持 canvas B 的尺寸与取出区域的尺寸一致。canvas B 中的图片就是裁切得到的图片区域块。

    比如要裁切女帝的左耳环:

    威尼斯登录首页 16

    简单量一下距离,就可以用下面的代码实现:

    cropImage(canvas, 250, 250, 90, 80)
    

    好了,差不多就是这些。

    // 抓取页面上已有的图片。

    HTML5 本地裁剪图片并上传至服务器(老梗)

    很多情况下用户上传的图片都需要经过裁剪,比如头像啊什么的。但以前实现这类需求都很复杂,往往需要先把图片上传到服务器,然后返回给用户,让用户确定裁剪坐标,发送给服务器,服务器裁剪完再返回给用户,来回需要 5 步。步骤繁琐不说,当很多用户上传图片的时候也很影响服务器性能。

    HTML5 的出现让我们可以更方便的实现这一需求。虽然这里所说的技术都貌似有点过时了(前端界的“过时”,你懂的),但还是有些许参考价值。在这里我只说一下要点,具体实现同学们慢慢研究。

    下面奉上我自己写的一个demo,在输入框中选好自己服务器 url, 生成好图片后点击 Submit 上传,然后自己去服务器里看看效果吧~~

    浏览器要求支持以下 Feature:

    • File API
    • Blob
    • atob
    • canvas

    代码直接从现有项目移植过来,没有经过“太多的”测试,写的很乱,也没注释,大家就慢慢看吧。。。重点就在 js 脚本的 28 行,clipImage 函数中,同学们可以直接跳过去看。

    点击预览

     

    第一步:获取文件

    HTML5 支持从 input[type=file] 元素中直接获取文件信息,也可以读取文件内容。我们用下面代码就可以实现:

    $('input[type=file]').change(function(){
        var file=this.files[0];
        // continue ...
    });
    

    myImage = new Image ();

    第二部:读取文件,并生成 Image 元素

    这一步就需要用到 FileReader 了,这个类是专门用来读取本地文件的。纯文本或者二进制都可以读取,但是本地文件必须是经过用户允许才能读取,也就是说用户要在input[type=file]中选择了这个文件,你才能读取到它。

    通过 FileReader 我们可以将图片文件转化成 DataURL,就是以 data:image/png;base64, 开头的一种URL,然后可以直接放在image.src 里,这样本地图片就显示出来了。

    $('input[type=file]').change(function(){
        var file=this.files[0];
    
        var reader=new FileReader();
        reader.onload=function(){
            // 通过 reader.result 来访问生成的 DataURL
            var url=reader.result;
            setImageURL(url);
        };
        reader.readAsDataURL(file);
    });
    
    var image=new Image();
    function setImageURL(url){
        image.src=url;
    }
    

    Image 就是在 html 里的 <img> 标签,所以可以直接插入到文档流里。

     

    第三步:获取裁剪坐标

    这一步没啥好说的,实现的方法也很多,需要获得下面四个裁剪框的坐标:

    • Y坐标
    • X坐标
    • 高度
    • 宽度

    如下图所示:
    威尼斯登录首页 17

    myImage.src = “image.png”;

    第四部:裁剪图片

    这是时候我们就需要用到 canvas 了,canvas 和图片一样,所以新建 canvas 时就要确定其高宽。这里我们还运用到image.naturalHeight 和 image.naturalWidth 这两个属性来获取图片原始尺寸。

    将图片放置入 canvas 时需要调用 drawImage ,这个接口参数比较多,在 MDN 上有详细的说明。

    drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
    

    威尼斯登录首页 18

    因为我们用 canvas 只是用于裁剪图片的,所以需要新建一个 canvas 让它的尺寸和裁剪之后图片的尺寸相等,此时 canvas 就相当与我们的裁剪框。运用这个函数还可以将大图缩放成小图,同学们自己研究吧。

    // 以下四个参数由第三步获得
    var x,  
        y,
        width,
        height;
    
    var canvas=$('<canvas width="'+width+'" height="'+height+'"></canvas>')[0],
        ctx=canvas.getContext('2d');
    
    ctx.drawImage(image,x,y,width,height,0,0,width,height);
    $(document.body).append(canvas);
    

    将 canvas 加入文档流之后,就可以看到裁剪后的效果了。不过我们还需要将图片上传至服务器里。

     

    第五步:读取裁剪后的图片并上传

    这时我们要获取 canvas 中图片的信息,用 toDataURL 就可以转换成上面用到的 DataURL 。 然后取出其中 base64 信息,再用window.atob 转换成由二进制字符串。但 window.atob 转换后的结果仍然是字符串,直接给 Blob 还是会出错。所以又要用Uint8Array 转换一下。总之这里挺麻烦的。。

    var data=canvas.toDataURL();
    
    // dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
    data=data.split(',')[1];
    data=window.atob(data);
    var ia = new Uint8Array(data.length);
    for (var i = 0; i < data.length; i++) {
        ia[i] = data.charCodeAt(i);
    };
    
    // canvas.toDataURL 返回的默认格式就是 image/png
    var blob=new Blob([ia], {type:"image/png"});
    

    这时候裁剪后的文件就储存在 blob 里了,我们可以把它当作是普通文件一样,加入到 FormData 里,并上传至服务器了。

    FormData 顾名思义,就是用来创建表单数据的,用 append 以键值的形式将数据加入进去即可。但他最大的特点就是可以手工添加文件或者 Blob 类型的数据,Blob 数据也会被当作文件来处理。原生 js 可以直接传递给 xhr.send(fd), jquery 可以放入 data 里请求。

    var fd=new FormData();
    
    fd.append('file',blob);
    $.ajax({
        url:"your.server.com",
        type:"POST",
        data:fd,
        success:function(){}
    });
    

    然后你服务器里应该就可以收到这个文件了~

    大多数支持 canvas 标记的浏览器的当前版本中,当图片还没有加载完成时,如果你要去画它,结果是什么事情都不会发生。也就是说,如果你想画一个图片,你需要等它完全加载。你可以使用图片对象的 onload 函数来进行判断。

     

    // Create an image.

     

    myImage = new Image ();

     

    myImage.onload = function () {

     

    // Draw image.

     

    myImage.src = “image.png”;

     

    在下面的所有例子中,我们的图片源将会使用这个256×256尺寸的大猩猩。

     

    基本绘画

     

    在最基本的画图操作中,你需要的只是希望图像出现处的位置(x和y坐标)。图像的位置是相对于其左上角来判断的。使用这种方法,图像可以简单的以其原尺寸被画在画布上。

     

    drawImage (image, x, y)

     

    var ctx = canvas.getContext (“2d”);ctx.drawImage (myImage, 50, 50);

     

    ctx.drawImage (myImage, 125, 125);

     

    ctx.drawImage (myImage, 210, 210);

     

     

     

    缩放及调整尺寸

     

    改变图像的尺寸,你需要使用重载的 drawImage 函数,提供给它希望的宽度和高度参数。

     

    drawImage (image, x, y, width, border=”1″ Height)

     

    var ctx = canvas.getContext (“2d”);ctx.drawImage (myImage, 50, 50, 100, 100);

     

    ctx.drawImage (myImage, 125, 125, 200, 50);

     

    ctx.drawImage (myImage, 210, 210, 500, 500);

     

    这个例子演示了如何画一个比原图小的图像,一个不同长宽比的图像和一个比原图大的图像的方法。

     

    图像裁剪

     

    最后一个 drawImage 方法的功用是对图像进行裁剪。

     

    drawImage (image,

     

    sourceX,

     

    sourceY,

     

    sourceWidth,

     

    sourceborder=”1″ Height,

     

    destX,

     

    destY,

     

    destWidth,

     

    destborder=”1″ Height)

     

    参数很多,但基本上你可以把它想成从原图中取出一个矩形区域,然后把它画到画布上目标区域里。

     

    var ctx = canvas.getContext (“2d”);ctx.drawImage (myImage, 0, 0, 50, 50, 25, 25, 100, 100);

     

    ctx.drawImage (myImage, 125, 125, 100, 100, 125, 125, 150, 150);

     

    ctx.drawImage (myImage, 80, 80, 100, 100, 250, 250, 220, 220);  这些就是 HTML5 中的 canvas (画布)标记里进行绘图和处理图像的基本操作。

     

     

     

    本文转自HTML5中国官网:


    本文由威尼斯手机平台登陆发布于前端资源,转载请注明出处:威尼斯登录首页canvas 标记的应用功能图像显示和处理,头像有大中小三种尺寸

    关键词: