详解微信小程序canvas圆角矩形的绘制的方法


Posted in Javascript onAugust 22, 2018

微信小程序允许对普通元素通过 border-radius 的设置来进行圆角的绘制,但有时候在使用 canvas 绘图的时候,也需要圆角,例如需要将页面上某块区域导出为图片下载到本地的时候,常用的解决方法就是使用 canvas 将这块区域绘制出来,最后导出 canvas 即可,但是 canvas 没有直接提供圆角的绘制 api ,所以需要 曲线救国

圆角矩形与一般矩形的区别在于,前者的四个角都是圆弧,所以只需要将一般矩形的四个角切掉,换成圆弧即可,如下图就是一个一般矩形被切掉了四个角的样子:

详解微信小程序canvas圆角矩形的绘制的方法

很明显,切掉了四个角的矩形,剩下其实就是四条 line ,既然如此,完全可以跳过绘制矩形然后切角这一步,因为切角的结果就是四条边( line ),直接绘制四条边即可。 然后在每两条边的缺角处绘制弧度为 0.5 * Math.PI 的圆弧,最后这四条边与四个圆弧所封闭的图形就是圆角矩形:

详解微信小程序canvas圆角矩形的绘制的方法

原理知道了,代码就很好写了,这里只说几个注意点:

封闭图形的 fillStyle 颜色设置为 transparent

想将封闭路径的图形绘制下来,需要调用 strokefill 方法,默认 strokefill 的颜色是 black ,但是这里有个问题, 圆弧的绘制可能会出现锯齿或者糊边,如果 strokefill 的颜色,与你所需要绘制的圆角矩形的边缘色调不一致,这种糊边的感觉会比二者色调一致的更明显, 下图第一个为色调一致,第二个为色调不一致的情况:

详解微信小程序canvas圆角矩形的绘制的方法

详解微信小程序canvas圆角矩形的绘制的方法

不过据我观测,只要不是特意放大仔细看,无论是色调是否一致,其实一般人很难注意到糊边的事情

clip

绘制好了圆角选区之后,还需要调用 ctx.clip 方法来裁剪选区

saverestore

如果这个矩形选区只是 canvas 画布的一部分,为了避免对后续的影响,最好在 beginPath 之前,将之前的动作 save ,然后画完后再 restore

一个关于 canvas 上绘制圆角图片,并下载到本地 的可运行示例代码已经放到 github 上了,注释也比较详细,需要的可自取

其中关键代码如下:

/**
 * 
 * @param {CanvasContext} ctx canvas上下文
 * @param {number} x 圆角矩形选区的左上角 x坐标
 * @param {number} y 圆角矩形选区的左上角 y坐标
 * @param {number} w 圆角矩形选区的宽度
 * @param {number} h 圆角矩形选区的高度
 * @param {number} r 圆角的半径
 */
function roundRect(ctx, x, y, w, h, r) {
 // 开始绘制
 ctx.beginPath()
 // 因为边缘描边存在锯齿,最好指定使用 transparent 填充
 // 这里是使用 fill 还是 stroke都可以,二选一即可
 ctx.setFillStyle('transparent')
 // ctx.setStrokeStyle('transparent')
 // 左上角
 ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)

 // border-top
 ctx.moveTo(x + r, y)
 ctx.lineTo(x + w - r, y)
 ctx.lineTo(x + w, y + r)
 // 右上角
 ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)

 // border-right
 ctx.lineTo(x + w, y + h - r)
 ctx.lineTo(x + w - r, y + h)
 // 右下角
 ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)

 // border-bottom
 ctx.lineTo(x + r, y + h)
 ctx.lineTo(x, y + h - r)
 // 左下角
 ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)

 // border-left
 ctx.lineTo(x, y + r)
 ctx.lineTo(x + r, y)

 // 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
 ctx.fill()
 // ctx.stroke()
 ctx.closePath()
 // 剪切
 ctx.clip()
}

ps:微信小程序canvas把正方形图片绘制成圆形

<canvas style="width: 400px; height: 400px;border:1px solid red" canvas-id="firstCanvas"></canvas>
//index.js
Page({
 data: {
  image: {
   src: "/1.png",
   width: 200,
   heigth: 200
  }
 },
 onLoad: function () {
  let that = this;
  var contex = wx.createCanvasContext('firstCanvas')
  contex.save(); // 先保存状态 已便于画完圆再用
  contex.beginPath(); //开始绘制
  //先画个圆
  contex.arc(100, 100, 100, 0, Math.PI * 2, false);
  contex.clip();//画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
  contex.drawImage(that.data.image.src, 0, 0, that.data.image.width, that.data.image.heigth); // 推进去图片
  contex.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 可以继续绘制
  contex.draw();
 }
})

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript中巧用“闭包”实现程序的暂停执行功能
Apr 04 Javascript
javascript学习(二)javascript常见问题总结
Jan 02 Javascript
自己写的Javascript计算时间差函数
Oct 28 Javascript
js获取电脑分辨率的思路及操作
Nov 22 Javascript
node.js中的fs.fstat方法使用说明
Dec 15 Javascript
jQuery中的jQuery()方法用法分析
Dec 27 Javascript
JavaScript将一个数组插入到另一个数组的方法
Mar 19 Javascript
JS高仿抛物线加入购物车特效实现代码
Feb 20 Javascript
vue 文件目录结构详解
Nov 24 Javascript
图文讲解用vue-cli脚手架创建vue项目步骤
Feb 12 Javascript
vue 对axios get pust put delete封装的实例代码
Jan 05 Javascript
JS实现简单的表格增删
Jan 16 Javascript
解决element UI 自定义传参的问题
Aug 22 #Javascript
微信小程序chooseImage的用法(从本地相册选择图片或使用相机拍照)
Aug 22 #Javascript
解决element-ui中下拉菜单子选项click事件不触发的问题
Aug 22 #Javascript
微信小程序 Animation实现图片旋转动画示例
Aug 22 #Javascript
Vue动态获取width的方法
Aug 22 #Javascript
微信小程序调用摄像头隐藏式拍照功能
Aug 22 #Javascript
Vue2.2.0+新特性整理及注意事项
Aug 22 #Javascript
You might like
PHP中防止直接访问或查看或下载config.php文件的方法
2012/07/07 PHP
php获取当前时间的毫秒数的方法
2014/01/26 PHP
PHP5多态性与动态绑定介绍
2015/04/03 PHP
PHP进制转换实例分析(2,8,16,36,64进制至10进制相互转换)
2017/02/04 PHP
THINKPHP在添加数据的时候获取主键id的值方法
2017/04/03 PHP
jQuery 使用手册(四)
2009/09/23 Javascript
javascript 日期时间 转换的方法
2013/02/21 Javascript
点击进行复制的JS代码实例
2013/08/23 Javascript
jQuery中ajax的load()方法用法实例
2014/12/26 Javascript
jQuery插件bxSlider实现响应式焦点图
2015/04/12 Javascript
Javascript中级语法快速入手
2016/07/30 Javascript
轻松实现js弹框显示选项
2016/09/13 Javascript
AngularJS Phonecat实例讲解
2016/11/21 Javascript
JS使用tofixed与round处理数据四舍五入的区别
2017/10/25 Javascript
webpack多入口文件页面打包配置详解
2018/01/09 Javascript
vue 移动端适配方案详解
2018/11/15 Javascript
JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】
2019/02/18 Javascript
javascript实现智能手环时间显示
2020/09/18 Javascript
python使用rsa加密算法模块模拟新浪微博登录
2014/01/22 Python
python编程实现12306的一个小爬虫实例
2017/12/27 Python
Python cookbook(数据结构与算法)将多个映射合并为单个映射的方法
2018/04/19 Python
python实现抽奖小程序
2020/04/15 Python
java判断三位数的实例讲解
2019/06/10 Python
python进行参数传递的方法
2020/05/12 Python
自学python用什么系统好
2020/06/23 Python
Python使用Turtle模块绘制国旗的方法示例
2021/02/28 Python
深入探究HTML5的History API
2015/07/09 HTML / CSS
htnl5利用svg页面高斯模糊的方法
2018/07/20 HTML / CSS
Madda Fella官网:美国冒险家服装品牌
2020/01/16 全球购物
在对linux系统分区进行格式化时需要对磁盘簇(或i节点密度)的大小进行选择,请说明选择的原则
2012/11/24 面试题
房屋买卖委托公证书
2014/04/08 职场文书
2014年学校办公室工作总结
2014/12/19 职场文书
大学团日活动总结书
2015/05/11 职场文书
施工安全协议书
2016/03/22 职场文书
教师师德承诺书2016
2016/03/25 职场文书
2019生态环境保护倡议书!
2019/07/03 职场文书