作者:issac_宝华
链接:http://www.jianshu.com/p/9a6ee2648d6f
來源:简书

在html中做圆框图片很容易,只需要简单的 border-radius: 50%; 当然,为了兼容性,还有必要做带前缀的兼容性写法。但总的来说还是很简单。

<style>
img{
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
}
</style>

但是在canvas上做起来就有点麻烦了,在canvas画布上画图片,可以使用canvas的 drawImage接口,但是这个接口也仅仅是将图片画在画布上,并没有如css那样提供做圆角的接口。

网上常看到这样的做法(最先是在张鑫旭的blog上看到的):

通过纹理实现
<canvas id="canvas"></canvas>
<script>
CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) {
var min_size = Math.min(w, h);
if (r > min_size / 2) r = min_size / 2; // 开始绘制
this.beginPath();
this.moveTo(x + r, y);
this.arcTo(x + w, y, x + w, y + h, r);
this.arcTo(x + w, y + h, x, y + h, r);
this.arcTo(x, y + h, x, y, r);
this.arcTo(x, y, x + w, y, r);
this.stroke();
this.closePath();
return this;
}
var canvas = document.querySelector("#canvas");
var context = canvas.getContext("2d");
var img = new Image();
img.src = 'images.jpg';
var pattern = context.createPattern(img, "no-repeat");
context.roundRect(0, 0, img.width, img.height, 0);
context.fillStyle = pattern;
context.fill();
</script>

这样做是可以的,这个做法的关键道具是createPattern 这是一个专门用来作纹理的API:

但是,如果你将该形状右移50px就会发现问题所在,图片没有跟着形状(圆框)一起移动:

其实,看第二个画布应该可以看出图片是对画布的左上角做定位的。如果图片没有移动,那么想办法移动图片就好啦!然而,可悲的是没有方法。因此,这是一种比较鸡肋的做法。

通过裁剪画布部分区域实现

这是我最后使用的方法,这个方法的关键道具是clip()API,这个API,可以用你指定的形状在画布上裁剪一部分出来,然后,接下来你在画布上的操作只有在该形状区域内可见,如果还有后续还有对画布的其他地方有操作,可以使用restore()接口恢复,但是必须在使用clip接口前用 save() 接口保存canvas的状态。

<canvas id="canvas" style="border: 1px solid;"></canvas>
<script>
var canvas = document.querySelector("#canvas");
var context = canvas.getContext("2d");
var img = new Image();
img.src = 'image.jpg'; // 首先是先画一个圆形,因为现在我们不是画圆角矩形,所以就不用“张鑫旭”画圆的做法,我们直接使用 `arc` 接口
context.save();
context.arc(100, 100, 50, 0, 2 * Math.PI); // 从画布上裁剪出这个圆形
context.clip();
context.drawImage(img, 50, 50, 100, 100);
</script>
两个值得注意的点,比较容易让误解的API:
  • clip()

这是w3c的例子,或许有部分人(在说自己),会误以为,在使用clip以后,接下来的操作都是相对于这个被剪切出来的部分做定位,特别是下面这张图:

灰色框是画布
更加容易让人误以为真是如此,其实不然,其实还是相对画布的左上角做定位,用了clip后只是变成,只有clip区域可见而已。
  • arcTo()

一个用来画弧线的api

关于这个API的参数说明是这样的:[传送门]

上面的参数说明中的起点和终点,比较容易让人误以为是下面两个点:

然而上面的(x1,y1)和(x2,y2)其实是分别指下图上的上面一点和下面一点:

继续看下图:

顺道说一下,canvas的坐标,x轴由原点左到右从0开始递增,y轴由原点上到下,从0开始递增。
A点是直线的末点,这个点一般是有lineTo接口写出,或者moveTo接口,比如moveTo(50,50),而B点则是arcTo中的x1,x2,B(100, 50), C点则是arcTo中的x2,y2,C(100, 100),而arcTo中的r则是AB或者CD。
[传送门:demo]

以上来自简书,顺便在此基础上封装了一个简单的方法,该方法可以用来画圆角矩形
/*
* 圆角矩形
* @parama int/float x 矩形位置x坐标
* @parama int/float y 矩形位置y坐标
* @parama int/float w 矩形宽度
* @parama int/float h 矩形高度
* @parama int/float r 圆角半径
* @parama object <img> 矩形背景图
*/
function drawRoundedImg(x,y,w,h,r,bgimg){
ctx.save();
ctx.beginPath();
ctx.moveTo(x+r,y);
ctx.arcTo(x+w,y,x+w,y+h,r);
ctx.arcTo(x+w,y+h,x,y+h,r);
ctx.arcTo(x,y+h,x,y,r);
ctx.arcTo(x,y,x+w,y,r);
ctx.stroke();
ctx.clip();
ctx.drawImage(bgimg, x, y, w, h);
ctx.restore();
ctx.closePath();
}

canvas实现圆框图片的更多相关文章

  1. canvas实现圆角、圆框图片

    参考资料: http://www.zhangxinxu.com/study/201406/image-border-radius-canvas.html https://www.jianshu.com ...

  2. Canvas 画圆

    原文地址:http://hi.baidu.com/lj2tj/item/557d8d1a65adfa721009b58b --------------------------------------- ...

  3. canvas代替img渲染图片

    移动端用canvas代替img渲染图片,可以提高性能 var oImg = new Image(); oImg.src = url; oImg.onload = function(){ var cvs ...

  4. canvas 绘圆加边框

    HTML5中canvas元素,绘制圆形需要使用路径,开始时要取得图形上下文,首先使用路径来勾勒图形的轮廓,然后设置颜色,进行绘制. arc(cx,cy,radius,start_angle,end_a ...

  5. 解决html5 canvas 绘制字体、图片与图形模糊问题

    html5 canvas 绘制字体.图片与图形模糊问题 发生情况 多出现在高dpi设备,这意味着每平方英寸有更多的像素,如手机,平板电脑.当然很多高端台式电脑也有高分辨率高dpi的显示器. canva ...

  6. canvas绘制圆图输出图片格式

    function drawCircleImage(url, callback) { const canvas = document.createElement('canvas'); const img ...

  7. html5 canvas从圆开始

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. canvas练习 - 圆

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. js使用canvas在前端压缩图片

    HTML代码: <input id="file" type="file"> JS代码: var eleFile = document.querySe ...

随机推荐

  1. 关于Android开发数据存储的方式(一)

    关于Android开发数据存储方式(一) 在厦门做Android开发也有两个月了,快情人节了.我还在弄代码. 在微信平台上开发自己的APP,用到了数据存储的知识,如今总结一下: 整体的来讲.数据存储方 ...

  2. centos改动sshport

    vi /etc/ssh/sshd_config 找到#Port 22一段,这里是标识默认使用22port.加入一行例如以下: Port 34981 然后保存退出 然后service sshd rest ...

  3. C++高精度性能測试函数

    在实际software开发工作中.我们常常会測试某个module或者function的执行效率.或者是某个算法的时间复杂度(尽管时间复杂度一定程度上依赖于机器性能.但在同一台computer上,经过算 ...

  4. velocity简单样例

    velocity简单样例整体实现须要三个步骤,详细例如以下: 1.创建一个Javaproject 2.导入须要的jar包 3.创建须要的文件 ============================= ...

  5. 好记性不如烂笔头——DML/DDL/DCL/TCL,OLTP/OLAP

    DML:数据操作语言,就是增删改之类的语句 DDL:数据定义语言,创建.修改.删除表等 ALTER 语句 (Transact-SQL) CREATE 语句 (Transact-SQL) DISABLE ...

  6. webService总结(一)——使用CXF公布和调用webService(不使用Spring)

    CXF和Axis2是两个比較流行的webService框架,接下来我会写几篇博客简介怎样使用这两种框架. 首先,先简介一下CXF的使用. CXF公布webService有多种方法.这里我介绍三种: 1 ...

  7. P1121 环状最大两段子段和

    P1121 环状最大两段子段和 题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的 ...

  8. mac os lscpu 【转】

    CPU Information on Linux and OS X This is small blog post detailing how to obtain information on you ...

  9. Fisher 线性判别

    Multiplying both sides of this result by wT and adding w0, and making use of y(x)=wTx+w0 and  y(xΓ)= ...

  10. bzoj3436: 小K的农场(差分约束)

    3436: 小K的农场 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1575  Solved: 690[Submit][Status][Discus ...