JAVASCRIPT+HTML5 Canvas to implement a local screenshot tutorial _javascript tips

Source: Internet
Author: User

Recently have time to understand the next HTML5 of the API, found that Sina Weibo's avatar set is the use of canvas to achieve screenshots, coupled with the previous period of time to understand the next HTML5 file API FileReader implementation files upload "JavaScript File API files Upload Preview, more feel HTML5 fun, think also try to write this function right when learning canvas it.
Below, I wrote a demo, the code is less, a lot of details will not be processed. If there are inappropriate places to invite advice, thank you ^_^ ^_^
function to achieve the step-playing:

    • First, get the file, read the file and generate the URL
    • Second, the size of the container using canvas to draw pictures
    • Third, use canvas to draw the mask layer
    • Iv. use canvas to draw cropped pictures
    • Five, drag the cropping box, and then crop the picture again

PS: Because it is first to write the demo and then write this article, so the section of the code is directly from the code inside a section of the copy, to pay attention to this object oh
First step: Get the file, read the file and generate the URL
Here I use the HTML5 inside the File API processing local files upload, because this can not upload the picture to the server, and then the server returned to the picture address to do the preview, detailed see: Using the File API FileReader implementation file upload

document.getElementById (' Post_file '). onchange = function () {
  var filelist = this.files[0];
  var ofreader = new FileReader ();
  Ofreader.readasdataurl (filelist);
  Ofreader.onload = function (ofrevent) {//called when the read operation completes successfully.
    Postfile.paintimage (OFREvent.target.result);//To pass the preview picture URL to the function
  };


Step two: Use canvas to draw a picture based on the size of the container

In the previous step, the FileReader with the file API had been given the address needed to upload the picture, and then you would need to use canvas to draw it. Why not just plug in the IMG and repaint it with canvas? Fact If you insert the page directly with IMG, can not adapt to the center, if the use of canvas to draw pictures, not only can make the picture Adaptive center and can be proportional scaling, and convenient to the image of the coordinates, size to the next mask layer, which can be based on the image of the coordinates and the size of the picture to draw a mask layer.
Here is a little attention to the canvas DrawImage method.

Paintimage:function (URL) {var t = this;
  var Createcanvas = T.getimage.getcontext ("2d");
  var img = new Image ();
  img.src = URL; img.onload = Zoom Picture (if the picture is wider than the container) = function () {//) scale the picture is wider = the width of the original picture is high. ///If the width or height of the picture is larger than the container, the width or height = width or height of the container, another height or width scales//t.imgwidth: The width of the picture after drawing; T.imgheight: The height of the picture after drawing; T.px: The x-axis of the picture after drawing; PY: Y-axis of the picture after drawing (Img.width < T.regional.offsetwidth && Img.height < t.regional.offsetheight) {T.I
      Mgwidth = Img.width;
 
    T.imgheight = Img.height;
      else {var pWidth = img.width/(img.height/t.regional.offsetheight);
      var pheight = img.height/(img.width/t.regional.offsetwidth); T.imgwidth = img.width > img.height?
      T.regional.offsetwidth:pwidth; T.imgheight = img.height > img.width?
    T.regional.offsetheight:pheight;
    //Picture coordinates t.px = (t.regional.offsetwidth-t.imgwidth)/2 + ' px ';
     
    t.py = (t.regional.offsetheight-t.imgheight)/2 + ' px '; T.getimage.height = t. imgheight;
    T.getimage.width = T.imgwidth;
    T.getimage.style.left = t.px;
 
    T.getimage.style.top = t.py; Createcanvas.drawimage (img,0,0,t.imgwidth,t.imgheight)//No use to directly insert the background picture and use canvas to draw the picture, in order to adjust the size of the picture in the desired frame T.imgurl =
    T.getimage.todataurl ()///store canvas picture address t.cutimage ();
  T.drag ();
};
  },

The effect is this:

Step three: Use canvas to draw the mask layer
in the previous step, you have drawn the background map you need to crop, now you need to draw the mask layer overlay on the background according to the coordinates and dimensions of the background map, and use the canvas Clearrect method to empty out a trimmed area to make the contrast with the place that does not crop.
(The mask layer is just for display and does not work with cropped pictures.) Do not know this step can be directly removed? Have to know the child shoes trouble tell me. )

Draw Mask Layer:
t.editbox.height = t.imgheight;
T.editbox.width = T.imgwidth;
T.editbox.style.display = ' block ';
T.editbox.style.left = t.px;
T.editbox.style.top = t.py;
 
var cover = T.editbox.getcontext ("2d");
Cover.fillstyle = "Rgba (0, 0, 0, 0.5)";
Cover.fillrect (0,0, T.imgwidth, t.imgheight);
Cover.clearrect (T.SX, T.sy, T.sheight, t.swidth);

Step Fourth: Use canvas to draw the cropped picture
In the third step, the mask layer is drawn, but the mask layer does not have the ability to cut, just to show the clipping area and the area of the contrast only, so here you start to cut the image function. Also use the DrawImage method to canvas.

Draw cut Picture:
t.editpic.height = t.sheight;
T.editpic.width = T.swidth;
var ctx = T.editpic.getcontext (' 2d ');
var images = new Image ();
IMAGES.SRC = T.imgurl;
Images.onload = function () {
  ctx.drawimage (images,t.sx, T.sy, T.sheight, t.swidth, 0, 0, t.sheight, t.swidth);//Crop picture
  document.getElementById (' Show_edit '). getElementsByTagName (' img ') [0].SRC = T.editpic.todataurl ();// Show the cropped picture using an IMG tag

Fifth step: Drag the cropping box to crop the picture again
use screenshots to upload avatar function when we want to be able to crop to the satisfaction of the picture, so the cropping box will need to constantly change to cut out the perfect picture. The first few steps have been to cut the basic skills of the picture can be made, so now need to do is the crop box to follow the mouse movement to crop the picture in real time.

Drag:function () {var t = this;
  var draging = false;
  var startx = 0;
 
  var starty = 0; document.getElementById (' Cover_box '). onmousemove = function (e) {//Get mouse to background picture distance var Pagex = E.pagex-(t.regional
    . offsetleft + this.offsetleft);
    var pagey = E.pagey-(t.regional.offsettop + this.offsettop); Determine if the mouse is in the cropping area: if (Pagex > T.sx && pagex < T.SX + t.swidth && pagey > T.sy && page
       
      Y < T.sy + t.sheight) {this.style.cursor = ' move ';
        This.onmousedown = function () {draging = true;
        Record the coordinates of the last screenshot t.ex = T.SX;
        T.ey = T.sy;
        Record the mouse at the time of the coordinates startx = E.pagex-(t.regional.offsetleft + this.offsetleft);
      Starty = E.pagey-(t.regional.offsettop + this.offsettop);
      } window.onmouseup = function () {draging = false;
        } if (draging) {///when moving the coordinates of the cropped area = Last record positioning + (current mouse position-press mouse position), cropping area can not exceed the mask layer area; if (T.Ex + (PAGEX-STARTX) < 0) {t.sx = 0;
        else if (T.ex + (PAGEX-STARTX) + t.swidth > t.imgwidth) {t.sx = T.imgwidth-t.swidth;
        else {t.sx = T.ex + (PAGEX-STARTX);
 
        };
        if (T.ey + (Pagey-starty) < 0) {t.sy = 0;
        else if (T.ey + (pagey-starty) + t.sheight > t.imgheight) {t.sy = T.imgheight-t.sheight;
        else {t.sy = T.ey + (pagey-starty);
      } t.cutimage ();
    } else{this.style.cursor = ' auto ';
}
  };   
 }

The picture is as follows:


Children's shoes pointed out that every move mouse to crop a picture is not very consuming performance, why not background-position to do when the preview effect to save the time to use canvas to cut out? I thought it was a reasonable suggestion, so I changed the code a little bit in the fourth step. Mouse movement when the preview effect is to change the picture of the Background-position, click the Save button to crop the picture, the cropped pictures to generate a new URL can be passed to the server ~ ~
The following code is corrected, do you have any other good suggestions welcome to point out Oh ^_^ ^_^
Demo complete code is as follows:
Note: Because of the use of Seajs written, so a little attention to the loading of the file
Css:

Body{text-align:center;}
#label {border:1px solid #ccc; Background-color: #fff; text-align:center;height:300px; width:300px;margin:20px auto; position:relative;}
#get_image {position:absolute;}
#edit_pic {position:absolute;display:none;background: #000;}
#cover_box {position:absolute;z-index:9999;display:none;top:0px;left:0px;}
#show_edit {margin:0 auto;display:inline-block;}
#show_pic {height:100px;width:100px;border:2px solid #000; overflow:hidden;margin:0 Auto;display:inline-block;}

Html:

<input type= "File" name= "file" id= "Post_file" >
<button id= "Save_button" > Save </button>
< Div id= "label" >
  <canvas id= "get_image" ></canvas>
  <p>
    <canvas id= "Cover_box" ></canvas>
    <canvas id= "Edit_pic" ></canvas>
  </p>
</div>
<p >
  <span id= "Show_edit" ></span>
  <span id= "show_pic" ></span>
</p>


<script type= "Text/javascript" src= ". /.. /lib/seajs/sea.js "></script>
<script type=" Text/javascript ">
seajs.use ([' _example/ Fileapi/index_v2.js '], function (clipfile) {
  clipfile.init ({
    clippos: {    ///Crop box default size and positioning
      x:15,
      y:15,
      height:100,
      width:100,
    },
  })

; </script>

Js:

Define (function (Require, exports, module) {' Use strict ';
      var postfile = {init:function (options) {var t = this;
      t.regional = document.getElementById (' label ');
      T.getimage = document.getElementById (' get_image ');
      T.clippic = document.getElementById (' edit_pic ');
      T.coverbox = document.getElementById (' Cover_box ');

      T.achieve = document.getElementById (' Show_edit ');

      T.clippos = Options.clippos;

      Initialize picture basic Parameters T.bgpagepos = {x:0, y:0, height:0, width:0};

      Pass into the picture document.getElementById (' Post_file '). AddEventListener ("Change", T.handlefiles, false); Click the Save button and then crop the picture document.getElementById (' Save_button '). onclick = function () {//Draw the Cut Picture: T.clippic.
        Height = t.clippos.height;

        T.clippic.width = T.clippos.width;
        var ctx = T.clippic.getcontext (' 2d ');
        var images = new Image ();
        IMAGES.SRC = T.imgurl; Images.onLoad = function () {//drawimage (images), relative to cropped picture's X, relative to crop the picture's Y, crop height, crop width, display in the canvas of X, displayed in the canvas of Y, show how high the canvas, showing how wide the canvas; Ctx.drawimage (Images,t.clippos.x, T.clippos.y, T.clippos.height, t.clippos.width, 0, 0, T.clippos.height, t.clip Pos.width); Crop the picture document.getElementById (' Show_pic '). getElementsByTagName (' img ') [0].SRC = T.clippic.todataurl ()
        ;

      }
      };
    T.drag ();
      }, Handlefiles:function () {var filelist = this.files[0];

      var ofreader = new FileReader ();

      Read the contents of the file Ofreader.readasdataurl (filelist);
      Called when the read operation completes successfully.
      Ofreader.onload = function (ofrevent) {//The preview picture URL is passed to the function postfile.paintimage (oFREvent.target.result);
    };
      }, Paintimage:function (URL) {var t = this;

      var Createcanvas = T.getimage.getcontext ("2d");
      var img = new Image ();

      img.src = URL; Zoom in on the incoming picture equal scale Img.onload = function () {//equal scale picture (if the picture width is smaller than the container, the picture is drawn wide = The width of the original picture is high.
        ///If the width or height of the picture is larger than the container, the width or height = width or height of the container, and the other height or width scales//t.bgpagepos.width: The width of the picture after drawing;
        T.bgpagepos.height: The height of the picture after drawing;
        T.bgpagepos.x: After drawing the x-axis of the picture; T.bgpagepos.y: The y-axis of the picture after drawing (Img.width < T.regional.offsetwidth && Img.height < t.regional.offsethe
          ight) {t.bgpagepos.width = Img.width;

        T.bgpagepos.height = Img.height;
          else {var pWidth = img.width/(img.height/t.regional.offsetheight);

          var pheight = img.height/(img.width/t.regional.offsetwidth); T.bgpagepos.width = img.width > img.height?
          T.regional.offsetwidth:pwidth; T.bgpagepos.height = img.height > img.width?
        T.regional.offsetheight:pheight;
        //Picture coordinates t.bgpagepos.x = (t.regional.offsetwidth-t.bgpagepos.width)/2 + ' px ';
        
        T.bgpagepos.y = (t.regional.offsetheight-t.bgpagepos.height)/2 + ' px '; T.getimage.height = T.bgpagepos.height;
        T.getimage.width = T.bgpagepos.width;
        T.getimage.style.left = t.bgpagepos.x;

        T.getimage.style.top = T.bgpagepos.y;
        
        Createcanvas.drawimage (img,0,0,t.bgpagepos.width,t.bgpagepos.height)//No use to directly insert the background picture and use canvas to draw the picture, in order to adjust the size of the picture in the desired frame
      T.imgurl = T.getimage.todataurl ()//store canvas picture address t.clipimg ();
    };

      }, Clipimg:function () {var t = this;
      Draw Mask Layer: T.coverbox.height = t.bgpagepos.height;
      T.coverbox.width = T.bgpagepos.width;
      T.coverbox.style.display = ' block ';
      T.coverbox.style.left = t.bgpagepos.x;

      T.coverbox.style.top = T.bgpagepos.y;
      var cover = T.coverbox.getcontext ("2d");
      Cover.fillstyle = "Rgba (0, 0, 0, 0.5)";
      Cover.fillrect (0,0, T.bgpagepos.width, t.bgpagepos.height);

      Cover.clearrect (T.clippos.x, T.clippos.y, T.clippos.height, t.clippos.width); t.achieve.style.background = ' url (' + t.imgurl + ') ' +-t.clippos.x + ' px ' +-t.clippos.y + 'PX No-repeat ';
      T.achieve.style.height = t.clippos.height + ' px ';
    T.achieve.style.width = t.clippos.width + ' px ';
      }, Drag:function () {var t = this;
      var draging = false;

      var _startpos = null;

        T.coverbox.onmousemove = function (e) {e = e | | window.event; 

          if (E.pagex = = null && e.clientx!= null) {var doc = document.documentelement, BODY = document.body; E.pagex = E.clientx + (Doc && Doc.scrollleft | | body && Body.scrollleft | | 0)-(Doc &&amp ; Doc.clientleft | | Body && Body.clientleft | |
          0);
        E.pagey = E.clienty + (Doc && Doc.scrolltop | | body && body.scrolltop); 
          //Get mouse to background picture of the distance var _mousepos = {Left:e.pagex-(t.regional.offsetleft + this.offsetleft), Top:e.pagey-(T.regional.offsettop + this.offsettop)}//Determine if the mouse is inside the cropping area: if (_mous Epos.left > T.clippos.x;& _mousepos.left < t.clippos.x + t.clippos.width && _mousepos.top > T.clippos.y && _mousepos.t
          
          Op < T.clippos.y + t.clippos.height) {this.style.cursor = ' move ';
            This.onmousedown = function () {draging = true; 
            Record the coordinates of the last screenshot t.ex = t.clippos.x;

            T.ey = T.clippos.y;
              Record the mouse at the time of the coordinates _startpos = {Left:e.pagex-(t.regional.offsetleft + this.offsetleft),
            Top:e.pagey-(T.regional.offsettop + this.offsettop)}} if (draging) {
            The coordinates of the cropping area when moving = the position of the last record + (the current mouse position-the position of the mouse), and the cropped area cannot exceed the area of the mask layer;
            if (T.ex + (_mousepos.left-_startpos.left) < 0) {t.clippos.x = 0; else if (T.ex + _mousepos.left-_startpos.left) + t.clippos.width > T.bgpagepos.width) {T.clippo
            S.x = T.bgpagepos.width-t.clippos.width;
    } else {          T.clippos.x = T.ex + (_mousepos.left-_startpos.left);

            };
            if (T.ey + (_mousepos.top-_startpos.top) < 0) {t.clippos.y = 0; else if (T.ey + _mousepos.top-_startpos.top) + t.clippos.height > T.bgpagepos.height) {T.clippo
            S.y = T.bgpagepos.height-t.clippos.height;
            else {t.clippos.y = T.ey + (_mousepos.top-_startpos.top);
          } t.clipimg ();
            } document.body.onmouseup = function () {draging = false;
            Document.onmousemove = null;
          Document.onmouseup = null;
        } else{this.style.cursor = ' auto ';
    }
      };
} return postfile;
 });

The above is the entire content of this article, I hope to help you learn.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.