使用canvas实现仿新浪微博头像截取上传功能

最近看到微博头像上传功能很感兴趣,于是就使用canvas写了一个,本文写的不好还请见谅。本程序目前在谷歌浏览器和火狐浏览器测试可用,ie浏览器无法支持。

因为ie的安全机制不允许img使用本地路径,所以若想ie支持本程序,必须先将图片上传,然后给img对象上传后的图片地址。

我在这里没写,是因为暂时没写上传功能的后端代码,并且还不确定有没有更好的解决办法。

如下是新浪的

如下是我做的截取部分

代码:

var canvas = document.getElementById('canvas'),
    context = canvas.getContext('d'),
    canvas = document.getElementById('canvas_dp'),
    context = canvas.getContext('d'),
    image = new Image(),//document.getElementById('myimg'),
    imageData,
   scale,//缩放比例
   rubberbandRectangle = {left:,top:,width:,height:},
   resize = ;
   oldRubberbandRectangle = {};
   dragging = false,
   extending = false,
   mousedown = {};
 // Functions.....................................................
 function windowToCanvas(canvas, x, y) {
   var canvasRectangle = canvas.getBoundingClientRect();
   return {
        x: x - canvasRectangle.left,
        y: y - canvasRectangle.top
      };
 }
 //将截取的图片画在小的canvas中
 function captureCanvasPixels() {
    context.drawImage(image,rubberbandRectangle.left/scale,rubberbandRectangle.top/scale,rubberbandRectangle.width/scale,rubberbandRectangle.height/scale,,,,);
 }
 function drawRubberband() {
   context.save();
   context.beginPath();//开始新的路径
     rect(rubberbandRectangle.left,
      rubberbandRectangle.top,
      rubberbandRectangle.width,
      rubberbandRectangle.height);
   context.fillStyle='rgba(,,,.)';
   addRectanglePath();
   context.fill();//填充路径
   context.fillStyle='rgba(,,,)';
   captureCanvasPixels();//将选取的图像copy到预览canvas中
   context.beginPath();
   context.strokeStyle = '#';
   context.lineWidth = .;
   context.arc(rubberbandRectangle.left+rubberbandRectangle.width,rubberbandRectangle.top+rubberbandRectangle.height,,,Math.PI*,true);
   context.fill();//填充路径
   context.stroke();//填充路径
   context.restore();
 }
 function rect(x, y, w, h, direction){
   if(direction){//逆时针
     context.moveTo(x, y);
     context.lineTo(x, y + h);
     context.lineTo(x + w, y + h);
     context.lineTo(x + w, y);
   }else{//顺时针
     context.moveTo(x, y);
     context.lineTo(x + w, y);
     context.lineTo(x + w, y + h);
     context.lineTo(x, y + h);
   }
   context.closePath();
 }
 function addRectanglePath(){
   rect(,,canvas.width,canvas.height,true);
 }
 function startDragging(loc){
   mousedown.x = loc.x;
   mousedown.y = loc.y;
   oldRubberbandRectangle.left = rubberbandRectangle.left;
   oldRubberbandRectangle.top = rubberbandRectangle.top;
 }
 function updateRubberbandRectangle(loc){
   var left = oldRubberbandRectangle.left + loc.x-mousedown.x;
   var top = oldRubberbandRectangle.top + loc.y - mousedown.y;
   rubberbandRectangle.left = (left<) ? : left;
   rubberbandRectangle.top = (top < ) ? : top;
   if(rubberbandRectangle.left + rubberbandRectangle.width > image.width * scale)rubberbandRectangle.left = image.width * scale - rubberbandRectangle.width;
   if(rubberbandRectangle.top + rubberbandRectangle.height > image.height * scale)rubberbandRectangle.top = image.height * scale - rubberbandRectangle.height;
   drawRubberband();
 }
 function startExtendSelection(loc){
   mousedown.x = loc.x;
   mousedown.y = loc.y;
   oldRubberbandRectangle.width = rubberbandRectangle.width;
   oldRubberbandRectangle.height = rubberbandRectangle.height;
 }
 function extendSelection(loc){
   var width = parseInt(oldRubberbandRectangle.width) + parseInt(loc.x)-parseInt(mousedown.x);
   var height = parseInt(parseInt(oldRubberbandRectangle.height) * parseInt(width)/parseInt(oldRubberbandRectangle.width));
   rubberbandRectangle.width = width;
   rubberbandRectangle.height = height;
   drawRubberband();
 }
 function clearRubberbandRectangle(){
   context.clearRect(, , canvas.width, canvas.height);
   context.putImageData(imageData, ,);
 }
 // Event handlers...............................................
 canvas.onmousedown = function(e){
   e.preventDefault();
   var loc = windowToCanvas(canvas, e.clientX, e.clientY);
   if(rubberbandRectangle.left < loc.x && rubberbandRectangle.top < loc.y && (rubberbandRectangle.left + rubberbandRectangle.width) > loc.x && (rubberbandRectangle.top + rubberbandRectangle.height) > loc.y){
     dragging = true;
     startDragging(loc);
   }else if((rubberbandRectangle.left + rubberbandRectangle.width - ) < loc.x && (rubberbandRectangle.top + rubberbandRectangle.height - ) < loc.y && (rubberbandRectangle.left + rubberbandRectangle.width +) > loc.x && (rubberbandRectangle.top + rubberbandRectangle.height + ) > loc.y){
     extending = true;
     startExtendSelection(loc);
   }
 }
 canvas.onmousemove = function (e) {
  e.preventDefault();
  var loc = windowToCanvas(canvas, e.clientX, e.clientY);
   if(rubberbandRectangle.left < loc.x && rubberbandRectangle.top < loc.y && (rubberbandRectangle.left + rubberbandRectangle.width) > loc.x && (rubberbandRectangle.top + rubberbandRectangle.height) > loc.y){
     canvas.style.cursor='move';
   }else if((rubberbandRectangle.left + rubberbandRectangle.width - ) < loc.x && (rubberbandRectangle.top + rubberbandRectangle.height - ) < loc.y && (rubberbandRectangle.left + rubberbandRectangle.width +) > loc.x && (rubberbandRectangle.top + rubberbandRectangle.height + ) > loc.y){
     canvas.style.cursor='nw-resize';
   }else{
     canvas.style.cursor='';
   }
  if (dragging) {
    clearRubberbandRectangle();
    updateRubberbandRectangle(loc);
   }
  if(extending){
    canvas.style.cursor='nw-resize';
    clearRubberbandRectangle();
    extendSelection(loc);
  }
 }
 canvas.onmouseup = function(e){
   e.preventDefault();
   dragging = false;
   extending = false;
 }
 // Initialization..............................................
 var myfileInput = document.getElementById('myfileInput');
 myfileInput.onchange=function(){
   setImage(myfileInput);
 };
 function setImage(fileObj){
   if (fileObj.files && fileObj.files[]) {
     //火狐下,谷歌下都是支持的
     image.src = window.URL.createObjectURL(fileObj.files[]);
   } else {
     alert('对不起,您的浏览器不支持');
   }
 }
 image.src = '';
 image.onload = function () {
   console.log(image);
   var w,h;
   //计算图片缩放比例
   if(image.width>canvas.width){
     console.log();
     w = canvas.width;
     h = canvas.width*image.height/image.width
   }else if(image.height>canvas.height){
     console.log();
     h = canvas.height;
     w = canvas.height*image.width/mage.height
   }else if(image.width/image.height >= canvas.width/canvas.height){
     console.log();
     w = canvas.width;
     h = canvas.width*image.height/image.width;
   }else if(image.width/image.height < canvas.width/canvas.height){
     console.log();
     w = canvas.height*image.width/image.height
     h = canvas.height;
   }
   scale = w/image.width;
   context.clearRect(,,canvas.width,canvas.height);
  context.drawImage(image, , ,w, h);
  console.log( w+':'+h+'###'+canvas.width+':'+canvas.height);
  imageData= context.getImageData(, , canvas.width, canvas.height);
   drawRubberband();
 };

html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-">
    <title>CarlZhang</title>
  </head>
  <body>
    <div name="container" style="height:px;width:px;border:#BB px solid;text-align:center">
      <canvas id="canvas" style="z-index: ; " height="" width=""></canvas>
    </div>
    <!--预览-->
    <div name="display" style="height:px;width:px;border:#BB px solid;position:absolute;left:px;top:px;">
      <canvas id="canvas_dp" style="z-index: ; " height="" width=""></canvas>
    </div>
    <!--上传-->
    <input id="myfileInput" type="file" accept="image/gif, image/jpeg, image/x-png"/>
    <script src="js/cavas_img_upload.js" type="text/javascript" charset="utf-"></script>
  </body>
</html>

以上代码很简单吧,附有注释,有不同见解的朋友,欢迎给我留言,共同交流学习进步。欲了解更多有关canvas头像截取上传问题,请持续关注本站,本站每天都有新的内容更新。

(0)

相关推荐

  • H5移动端图片压缩上传开发流程

    H5活动已十分普遍,其中一种形式是让用户上传图片进行参与.移动端上传图片,用户一般都是上传手机相册中的图片,而现在手机的拍摄质量越来越高,一般单张照片的尺寸都在3M左右.若直接上传,十分耗流量,并且体验效果也不佳.因此需要在上传之前,先进行本地压缩. 接下来总结在h5活动的开发中图片压缩上传的功能,并标记其中踩过的几个坑,分享给大家: 小白区必看 对于移动端图片上传毫无概念的话,需要补充FileReader.Blob.FormData三个概念. 1.FileReader 定义 使用FileRea

  • canvas实现手机端用来上传用户头像的代码

    废话不多说了直接给大家介绍canvas实现手机端用来上传用户头像的代码,具体代码如下所示: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> label{ height:40px; width:100px; border:1px solid #666; display:block; text-alig

  • 移动端利用H5实现压缩图片上传功能

    此前有同事跟我聊过关于移动端用canvas压缩图片后再上传的功能,最近有了点空闲时间,所以就实践了一下.demo效果链接在文章底部贴出. 在做移动端图片上传的时候,用户传的都是手机本地图片,而本地图片一般都相对比较大,拿iphone6来说,平时拍很多图片都是一两M的,如果直接这样上传,那图片就太大了,如果用户用的是移动流量,完全把图片上传显然不是一个好办法. 目前来说,HTML5的各种新API都在移动端的webkit上得到了较好的 实现.根据查看caniuse,本demo里使用到的FileRea

  • vuejs开发组件分享之H5图片上传、压缩及拍照旋转的问题处理

    一.前言 三年.net开发转前端已经四个月了,前端主要用webpack+vue,由于后端转过来的,前端不够系统,希望分享下开发心得与园友一起学习. 图片的上传之前都是用的插件(ajaxupload),或者传统上传图片的方式,各有利弊:插件的问题是依赖jq并且会使系统比较臃肿,还有传统的web开发模式 前后端偶尔在一起及对用户体验要求低,现在公司采用webpack+vue+restfullApi开发模式 前后端完全分离,遵从高内聚,低偶尔的原则,开发人员各司其职,一则提升开发效率(从长期来看,短期

  • js生成缩略图后上传并利用canvas重绘

    一般在处理图片上传时,通常的逻辑都是将源图片上传到服务器端,再由服务器端的语言进行缩放大小的操作. 此种模式一般可以满足大部分的需求,但当我们所需要的图片仅仅是一个符合规定大小的源图片的缩略图,再使用此种模式,将是一种浪费服务端资源以及带宽的方式,故我们考虑在浏览器端生成小图后再进行上传操作. //以下为源代码 复制代码 代码如下: function drawCanvasImage(obj,width, callback){ var $canvas = $('<canvas></canv

  • 利用H5特性FormData实现不刷新文件上传

    之前朋友说的不刷新上传文件.最暴力的解决方案就是上网上搜各种JS库,附带多图上传,预览,甚至是图片处理等特技.那么如果不接触第三方的库,可不可以利用ajax来做.就这个问题,有人给出的解决方案是借助iframe,这里就不赘述了.但是Html5是个好东西,他提供了FormData,FormData可以帮助我们拼凑参数,乃至文件资源.这样,我们就可以轻松用$.ajax不刷新上传.当然也不需要iframe. 代码 下列是前端部分. <!DOCTYLE html> <meta charset=u

  • Angular下H5上传图片的方法(可多张上传)

    最近做的项目中用到了angular下上传图片功能,在做的过程中遇到了许多问题,最终都得以解决 angular上传时和普通上传时过程差不多,只不过是要不一些东西转化为angular的东西. 1.ng-file-select,指令angular是没此功能的,其实也是转化成了change事件,不多说,直接上代码 angular.module('myApp') .directive('ngFileSelect', [ '$parse', '$timeout', function($parse, $tim

  • 使用canvas实现仿新浪微博头像截取上传功能

    最近看到微博头像上传功能很感兴趣,于是就使用canvas写了一个,本文写的不好还请见谅.本程序目前在谷歌浏览器和火狐浏览器测试可用,ie浏览器无法支持. 因为ie的安全机制不允许img使用本地路径,所以若想ie支持本程序,必须先将图片上传,然后给img对象上传后的图片地址. 我在这里没写,是因为暂时没写上传功能的后端代码,并且还不确定有没有更好的解决办法. 如下是新浪的 如下是我做的截取部分 代码: var canvas = document.getElementById('canvas'),

  • Ajax实现注册并选择头像后上传功能

    在初次接触ajax后,我们做了一个crm训练的项目,大多数小组都有注册用户这一项,但是都忽略掉了一个功能,那就是,很多网站的注册是可以上传头像的,在这里我做了一个在已有的头像数组里选择图片上传作头像的小型crm(当然,可以从本地照片上传并裁剪的那种我还没做出来,不过只要有时间我就会研究的,相信时间也不会太久的). 1.先写出一个注册页面以及css样式我命名为regist.html,css文件名为regist.css,在这里我省略掉具体代码,上图看效果吧:(页面有点丑,别介意) 还有一个用于显示添

  • Android 高仿微信朋友圈拍照上传功能

    模仿微信朋友圈发布动态,输入文字支持文字多少高度自增,有一个最小输入框高度,输入文字有限制,不过这些都很easy! 1. PhotoPicker的使用 这是一个支持选择多张图片,点击图片放大,图片之间左右滑动互相切换的库,同时支持图片删除的库,效果类似微信. (1) 添加PhotoPicker的架包 (2) 使用 选择图片:安卓6.0以后需要在代码中添加读写sd卡和相机的权限 当然清单文件中也需要添加的 PhotoPicker.builder() .setPhotoCount(maxPhoto)

  • 针对多用户实现头像上传功能PHP代码 适用于登陆页面制作

    一个网站,其实说白了就是某几个特定功能的组合,而更换用户头像就在这些功能之中.今天就来做个测试,针对不同的用户,实现头像上传功能. -------------------------------------------------------------------------------- 成品图 思路  •针对不同的用户上传头像,我们要为每一个已登录的用户创建一个文件夹,文件夹的名称以当前用户的用户名为准. •用户上传成功后,跳转到用户登录成功后的页面,并刷新用户头像. 登陆页面 表单制作

  • vue-cropper插件实现图片截取上传组件封装

    基于vue-cropper插件实现图片截取上传组件封装的具体代码,供大家参考,具体内容如下 需求场景: 后台开发需要上传图片并进行相应比例尺寸图片的截取,本组件开发采用Ant Design Vue组件库搭配vue-cropper插件进行封装 实现如下 html <template> <div> <a-upload name="avatar" list-type="picture-card" class="avatar-uplo

  • Vue vant-ui使用van-uploader实现头像上传功能

    效果图: 项目中是使用有赞vant-ui框架实现的头像上传替换功能 代码布局结构: <van-row class="sendInfo"> <van-col span="24" class="flex colorf topInfo p20"> <!--左边头像部分--> <van-uploader :after-read="afterCard" :before-read="be

  • Java编程之如何通过JSP实现头像自定义上传

    目录 开发概述 开发环境 开发过程 1.JSP前台页面 样式图: JS操作 2.数据库的设计 数据库表: 实体类:UsersInfo.java 3.数据库操作 UsersMapper UsersMapper.xml 4.Servlet 5.工具类 DownloadImage:下载指定路径下的文件到本地指定目录 TimeRandom:生成年月日时分秒+8位随机数 6.最终效果展示 总结 开发概述 本次项目意在实现一种可以在本地选择图片,然后将其上传至服务器指定文件目录下,并可以通过服务器自动生成的

  • node.js(express)中使用Jcrop进行图片剪切上传功能

    需求说明 简单来说就是要实现用户上传头像,并且要保存用户裁切后的部分作为用户头像. 第一步,选择图片: 第二步,在弹窗页面中展现并进行裁切: 第三步,点击"保存",上传服务器. 实现过程 说来有点坎坷,相当于做了2遍,走了弯路. 第1遍是用户一选择图片,就进行了上传,然后返回一个地址,所以在弹层上展现的图片已经是服务器上的图片了,然后进行裁切,再保存. 第2遍找到的一个方法,是在第1遍做到裁切处理时候想到的,即弹层展现的是用户机器上选择的图片,不用先上传,但是用image/base64

  • Servlet实现多文件上传功能

    一.Servlet实现文件上传,需要添加第三方提供的jar包 下载地址: 1) commons-fileupload-1.2.2-bin.zip : 点击打开链接 2) commons-io-2.3-bin.zip :  点击打开链接 接着把这两个jar包放到 lib文件夹下: 二.文件上传的表单提交方式必须是POST方式 编码类型:enctype="multipart/form-data",默认是 application/x-www-form-urlencoded 比如:<fo

随机推荐