写在最前:

  前两天老大跟我说老虎官网上那个自定义头像的功能是flash实现的,没有安装过的还得手动去“允许”falsh的运行。所以让我用canvas实现一个一样的功能,嘿嘿,刚好最近也在研究canvas,所以欣然答应(其实,你没研究过难道就不答应么,哈哈哈哈哈~)

  对了,大佬们记得给我的博客点赞,要星星哦~

成果展示:

Git地址:

github.com/ry928330/po…

功能说明:

  1. 拖拽左侧小方框,或者是鼠标放在小方框右下角,点击拉伸方框,方框覆盖部分的图片被自动截取下来,然后再在右侧的多个容器里面重绘。
  2. 输入宽高,自定义你需要订制的头像大小,目前只支持宽高相同的头像图片。

    实现细节:

  因为你要对图片所在的区域进行截图,所以你得制作一张canvas,盖在图片所在的区域。这里,我们给出了一个函数,根据传入的DOM里面元素的类名创建相同位置的canvas,盖在原来的DOM元素上面:

function createCanvasByClassName(tag) {var canvasInitialWidth = $('.' + tag).width();var canvasInitialHeight = $('.' + tag).height();var left = $('.' + tag).offset().left - $('.' + tag).parent('.portraitContainer').offset().left + 1;var top = $('.' + tag).offset().top - $('.' + tag).parent('.portraitContainer').offset().top + 1;//var left = $('.' + tag).offset().left + 1;//var top = $('.' + tag).offset().top + 1;clearCanvasObj.left = $('.' + tag).offset().left + 1;clearCanvasObj.top = $('.' + tag).offset().top + 1;// clearCanvasObj.left = left;// clearCanvasObj.top = top;var canvasElement = $('<canvas></canvas>');var randomNum = Math.floor(getRandom(0, 10000));clearCanvasObj.canvasId = randomNum;canvasElement.attr({id: 'canvas',width: canvasInitialWidth,height: canvasInitialHeight});canvasElement.css({position: 'absolute',top: top, left: left});//$('body').append(canvasElement);var appendEle = $('.portraitContainer').append(canvasElement);var canvas = document.getElementById('canvas');var ctx = canvas.getContext('2d');//ctx.fillStyle = "rgba(211,211,216,0.5)";ctx.clearRect(0, 0, canvasInitialWidth, canvasInitialHeight);ctx.fillStyle = "rgba(0,0,0, 0.4)";ctx.fillRect(0, 0, canvasInitialWidth, canvasInitialHeight);return canvas;
}复制代码

  有了这张canvas你就可以在你图片所在区域肆意的操作了。首先,降整个区域画上一个浅黑色的阴影,然后再擦除初始小方框区域里面的颜色。然后给整个页面添加mousedown,mousemove,mouseup事件,他们所做的功能就跟你在页面中实现一个拖拽的功能类似,这里重点说下mousemove里面做的操作,代码如下:

function mousemoveFunc(event) {/* Act on the event */var nowMouseX = event.clientX - clearCanvasObj.left;var nowMouseY = event.clientY - clearCanvasObj.top;if (nowMouseX >= clearCanvasObj.xStart && nowMouseX <= clearCanvasObj.xStart + clearCanvasObj.width && nowMouseY >= clearCanvasObj.yStart && nowMouseY <= clearCanvasObj.yStart + clearCanvasObj.height) {clearCanvasObj.isCanvasArea = true;//clearCanvasObj.isRightCorner = false;imgContainerCanvas.style.cursor = 'move';} else if ((nowMouseX >= clearCanvasObj.xStart + clearCanvasObj.width - 10) && (nowMouseX <= clearCanvasObj.xStart+ clearCanvasObj.width + 10) && (nowMouseY >= clearCanvasObj.yStart + clearCanvasObj.height - 10) && (nowMouseY <= clearCanvasObj.yStart + clearCanvasObj.height + 10)) {clearCanvasObj.isCanvasArea = true;//clearCanvasObj.beginDraw = false;imgContainerCanvas.style.cursor = 'se-resize';} else {clearCanvasObj.isCanvasArea = false;//clearCanvasObj.isRightCorner = false;imgContainerCanvas.style.cursor = 'default';}var outerDomWidth = $(".imgContainer").width();var outerDomHeight = $(".imgContainer").height();var xDistance = event.clientX - clearCanvasObj.mouseX;var yDistance = event.clientY - clearCanvasObj.mouseY;//var outerCTX = canvas.getContext('2d');//移动小方框if (clearCanvasObj.beginDraw && clearCanvasObj.isCanvasArea && !clearCanvasObj.isRightCorner) {ry_CTX.fillStyle = clearCanvasObj.color;// console.log('1', clearCanvasObj.xStart, clearCanvasObj.yStart)ry_CTX.fillRect(clearCanvasObj.xStart, clearCanvasObj.yStart, clearCanvasObj.width, clearCanvasObj.height);//outerCTX.fillRect(0, 0, canvas.width, canvas.height);clearCanvasObj.xStart += xDistance;clearCanvasObj.yStart += yDistance;//判断方框是否达到边界if (clearCanvasObj.xStart <= 0) {clearCanvasObj.xStart = 0;}if (clearCanvasObj.yStart <= 0) {clearCanvasObj.yStart = 0;}if ((clearCanvasObj.xStart + clearCanvasObj.width) >= outerDomWidth) {clearCanvasObj.xStart = outerDomWidth - clearCanvasObj.width;}if ((clearCanvasObj.yStart + clearCanvasObj.height) >= outerDomHeight) {clearCanvasObj.yStart = outerDomHeight - clearCanvasObj.height;}// console.log('2', clearCanvasObj.xStart, clearCanvasObj.yStart)ry_CTX.clearRect(clearCanvasObj.xStart, clearCanvasObj.yStart, clearCanvasObj.width, clearCanvasObj.height);produceSmallPic(clearCanvasObj.xStart+clearCanvasObj.left, clearCanvasObj.yStart+clearCanvasObj.top, clearCanvasObj.width, clearCanvasObj.height, imageURL)clearCanvasObj.mouseX = event.clientX;clearCanvasObj.mouseY = event.clientY;}//拖拽小方框if (clearCanvasObj.isRightCorner) {ry_CTX.fillStyle = clearCanvasObj.color;ry_CTX.fillRect(clearCanvasObj.xStart, clearCanvasObj.yStart, clearCanvasObj.width, clearCanvasObj.height);var realDistance = Math.min(xDistance, yDistance)clearCanvasObj.width +=  realDistance;clearCanvasObj.height += realDistance;//拖动时边界条件的判断if (clearCanvasObj.xStart + clearCanvasObj.width >= outerDomWidth) {clearCanvasObj.width = outerDomWidth - clearCanvasObj.xStart;clearCanvasObj.height = outerDomWidth - clearCanvasObj.xStart;}if (clearCanvasObj.yStart + clearCanvasObj.height >= outerDomHeight) {clearCanvasObj.width = outerDomHeight - clearCanvasObj.yStart;clearCanvasObj.height = outerDomHeight - clearCanvasObj.yStart;}if (clearCanvasObj.width <= 10) {clearCanvasObj.width = 10;}if (clearCanvasObj.height <= 10) {clearCanvasObj.height = 10;}ry_CTX.clearRect(clearCanvasObj.xStart, clearCanvasObj.yStart, clearCanvasObj.width, clearCanvasObj.height);produceSmallPic(clearCanvasObj.xStart+clearCanvasObj.left, clearCanvasObj.yStart+clearCanvasObj.top, clearCanvasObj.width, clearCanvasObj.height, imageURL);clearCanvasObj.mouseX = event.clientX;clearCanvasObj.mouseY = event.clientY;}
}复制代码

  函数里面,你需要注意拖拽的边界条件,一个是方框不能拖到图片所在DOM外的边界;另外一个就是当你鼠标放在小方框所在的区域改变鼠标的样式。方框在拖动的过程中,我们不断重绘方框移动的区域(也就是不断的画上阴影),然后在新的位置调用clearRect函数,重新擦出一个小方框出来。在拖拽或是拉伸的过程中,我们会不断调用produceSmallPic函数,在右边的容器(每个容器都是一个canvas)里面不断根据容器大小重绘出所需的头像。代码如下:

function produceSmallPic(imageURL,left, top, width, height) {var img = new Image();img.src = imageURL;var targetCtx = new Array();var targetCanvas = null;img.onload = function() {portraitGroupsArr.forEach(function(item, index) {targetCanvas = document.getElementById(item.class);targetCtx.push(targetCanvas.getContext('2d'));targetCtx[index].clearRect(0,0, item.width, item.height);targetCtx[index].drawImage(img, left - clearCanvasObj.left, top - clearCanvasObj.top, width, height, 0, 0 , item.width, item.height);})}
}复制代码

  我们说下这个函数的作用,这里我们要注意一个参数imageURL,这个URL是由图片所在的DOM转化来的。因为你要把DOM所在的区域变成一张图片,这样你才能在利用drawImage函数截取你所需要的区域。所以我们先利用html2canvas库函数讲图片所在的DOM转化为canvas,这张canvas的内容是包含你所要截取的图片的,然后把这张canvas转化为图片取得图片地址imageURL,代码如下:

html2canvas(document.getElementById('imgContainer'), {onrendered: function(canvas) {var imageURL = canvasTransToImage(canavs);...}})
function canvasTransToImage(canvas) {var imageURL = canvas.toDataURL('image/png');return imageURL;
}复制代码

  接着,你就可以便利右侧的canvas容器,讲图片重回到里面了,整个过程就这样结束,回头看来是不是很简单。

相关依赖:

<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>复制代码

写在最后:

  canvas的操作,要多多注意那些边界条件,什么时候该重绘什么时候该清除,这些是比较重要的。逻辑清晰了,canvas本身的API也就那么几个,操作起来也就没那么麻烦了,最后,谢谢大家查阅,写的不是很清楚,有不懂的可以一起讨论~

canvas之自定义头像功能实现相关推荐

  1. php网页自定义头像系统,怎样用canvas实现自定义头像功能

    这次给大家带来怎样用canvas实现自定义头像功能,用canvas实现自定义头像功能的注意事项有哪些,下面就是实战案例,一起来看一下. 写在最前: 前两天老大跟我说老虎官网上那个自定义头像的功能是fl ...

  2. 头像 HTML5 JSON PHP 摄像头,canvas之自定义头像功能实现代码示例

    写在最前: 前两天老大跟我说老虎官网上那个自定义头像的功能是flash实现的,没有安装过的还得手动去"允许"falsh的运行.所以让我用canvas实现一个一样的功能,嘿嘿,刚好最 ...

  3. 升级IOS8游戏上传自定义头像功能失效的问题

    为了支持arm64,之前已经折腾了很久,昨晚打包准备提交苹果审核时,测试那边的同事反馈说游戏上传自定义头像功能不可用了. 游戏上传自定义功能的简介:卡牌游戏最初是<比武招亲>中有一个充VI ...

  4. 我的世界租赁服务器维护怎么重新刷新,《我的世界》【PC】版大更新!租赁服购买/续租功能,自定义头像功能已开启!...

    原标题:<我的世界>[PC]版大更新!租赁服购买/续租功能,自定义头像功能已开启! 随着今日<我的世界>手游安卓版限号不删档测试的到来 <我的世界>PC版的更新也在 ...

  5. WordPress怎么使用支持注册用户上传自定义头像功能?

    WordPress怎么使用支持注册用户上传自定义头像功能?认Wordpress支持显示Gravatar头像,但目前由于众所周知的原因,申请Gravatar头像比较困难只能显示默认的古怪头像,对注册用户 ...

  6. 仿QQ头像自定义截取功能

    看了android版QQ的自定义头像功能,决定自己实现,随便熟悉下android绘制和图片处理这一块的知识. 先看看效果: 思路分析: 这个效果可以用两个View来完成,上层View是一个遮盖物,绘制 ...

  7. android人脸识显示头像自定义,Android 仿QQ头像自定义截取功能

    看了Android版QQ的自定义头像功能,决定自己实现,随便熟悉下android绘制和图片处理这一块的知识. 先看看效果: 思路分析: 这个效果可以用两个View来完成,上层View是一个遮盖物,绘制 ...

  8. 腾讯QQ2004II Beta3火爆下载 可自定义头像

    昨天(12月9日)腾讯QQ 2004II Beta3正式推出,此次升级增加了自定义头像.多人语音聊天等实用功能,使得QQ功能日益强大. QQ超级语音,超越距离的沟通 QQ2004II beta3全新启 ...

  9. php更换wordpress用户头像,WordPress如何添加用户自定义上传头像功能

    使用WordPress建站的朋友应该知道,WordPress本身是没有上传自定义头像功能的,如果要更换头像,步骤是非常麻烦的. 而在我们开发一款WordPress主题中,特别是多用户的主题,让注册用户 ...

最新文章

  1. H3C 静态默认路由配置
  2. 腾讯云短信出现there are both domestic mobile phone numbers and international mobile phone numbers in the...
  3. 重新探讨一下《APEX英雄》系统设计的亮点
  4. B+/-Tree原理及mysql的索引分析
  5. Java读写二进制文件
  6. linux 端口方法防火墙,Linux 打开端口方法(防火墙操作)
  7. word模板生成word报表文档
  8. vs2010 mysql linq to sql 系列_linq to sql简单使用
  9. 【php更换数据库为orcle】phpstudy+orcle
  10. 模型选择 + 过拟合和欠拟合 动手学深度学习v2 pytorch
  11. w7网络计算机共享,网络共享设置 win7局域网共享设置最简单教程
  12. 什么是宽带薪酬?宽带薪酬系统如何实施?
  13. 连续时间正弦信号和离散时间正弦信号
  14. C 语言do with,Nonverbal (非语言的) communication has to do with gestures, movements andcloseness of two...
  15. python excel表格排序_Python实现EXCEL表格的排序功能
  16. Unity 使用UnityWebRequest问题小结
  17. “物联网开发实战”学习笔记-(二)手机控制智能电灯
  18. DXC Technology任命Luz G. Mauch为汽车部执行副总裁
  19. visualGDB下导入cmake工程
  20. 技术分享 | 《云原生下的IAST落地实践》

热门文章

  1. 【目标管理】企业目标如何落地?
  2. moonlight鼠标延迟解决
  3. 移动电源最好的品牌推荐,移动电源牌子排行榜
  4. xlsx表格怎么做汇总统计_怎样在excel电子表格中对数据进行分类汇总,实例教程...
  5. HPUX 系统安全MC
  6. 使用Fiddler和夜神浏览器对搜狐推荐新闻的抓取
  7. 机器人轨迹规划中经常用到的曲线特性小结:Cn连续与Gn连续、Frenet标架、曲率和挠率
  8. 微分几何笔记(4) —— 二维三维空间中曲线的曲率以及环绕数
  9. 三大运营商2G3G4G频段分布
  10. oracle 9i 下载