背景

某些情况下可能需要使用canvas实现线性渐变,需求是渐变色恰好填充整个画布,并且渐变的方向不是水平或垂直的,而是任意角度的,举个css3实现的栗子:

background: linear-gradient(60deg, red, blue);

如果用canvas实现上面的效果,首先要创建一个渐变对象:

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.createLinearGradient(x0, y0, x1, y1);

x0,y0是渐变起始坐标,x1,y1是渐变结束坐标。

具体请参考API。

那么问题来了,如何确定坐标参数x0, y0, x1, y1?

实现

在确定坐标参数之前,先简单了解下css的实现原理,直接放图:

默认情况下,渐变会平滑地从一种颜色过渡到另一种颜色,也就是说渐变线会通过元素的中点,上面说的渐变色恰好填充整个画布也是这个意思,那么以元素的中点为原点建立坐标系,那么可以得到下面这张图:

其中矩形是元素,M是渐变线,从左下至右上方向,Q、W分别是过矩形的两个对角点,并与M垂直的两条线,颜色渐变的范围就在这两条线之间,(x0’,y0’),(x1’,y1’)分别是两个垂点的坐标,暂且称为I点,J点,而我们要求的(x0,y0),(x1,y1)其实就是将坐标系转换成canvas坐标系(左上角为原点,向下为Y轴正方向)后I点和J点的坐标,有了矩形的宽高和渐变线的角度值,根据简单的几何知识就能算出两点的坐标,不过需要注意的是,渐变线与矩形的交点可能落在水平线上,也可能落在垂直线上,所以需要分两块逻辑进行计算,实现代码如下:

/*** @description: 计算canvas渐变起始坐标* @param {number} canvas width* @param {number} canvas height* @param {number} angle 角度* @return {*}*/
function calculateGradientCoordinate(width,height,angle = 180,
) {if (angle >= 360) angle = angle - 360;if (angle < 0) angle = angle + 360;angle = Math.round(angle);// 当渐变轴垂直于矩形水平边上的两种结果if (angle === 0) {return {x0: Math.round(width / 2),y0: height,x1: Math.round(width / 2),y1: 0,};}if (angle === 180) {return {x0: Math.round(width / 2),y0: 0,x1: Math.round(width / 2),y1: height,};}// 当渐变轴垂直于矩形垂直边上的两种结果if (angle === 90) {return {x0: 0,y0: Math.round(height / 2),x1: width,y1: Math.round(height / 2),};}if (angle === 270) {return {x0: width,y0: Math.round(height / 2),x1: 0,y1: Math.round(height / 2),};}// 从矩形左下角至右上角的对角线的角度const alpha = Math.round((Math.asin(width / Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2))) *180) /Math.PI,);// 当渐变轴分别于矩形的两条对角线重合情况下的四种结果if (angle === alpha) {return {x0: 0,y0: height,x1: width,y1: 0,};}if (angle === 180 - alpha) {return {x0: 0,y0: 0,x1: width,y1: height,};}if (angle === 180 + alpha) {return {x0: width,y0: 0,x1: 0,y1: height,};}if (angle === 360 - alpha) {return {x0: width,y0: height,x1: 0,y1: 0,};}// 以矩形的中点为坐标原点,向上为Y轴正方向,向右为X轴正方向建立直角坐标系let x0 = 0,y0 = 0,x1 = 0,y1 = 0;// 当渐变轴与矩形的交点落在水平线上if (angle < alpha || // 处于第一象限(angle > 180 - alpha && angle < 180) || // 处于第二象限(angle > 180 && angle < 180 + alpha) || // 处于第三象限angle > 360 - alpha // 处于第四象限) {// 将角度乘以(PI/180)即可转换为弧度const radian = (angle * Math.PI) / 180;// 当在第一或第四象限,y是height / 2,否则y是-height / 2const y = angle < alpha || angle > 360 - alpha ? height / 2 : -height / 2;const x = Math.tan(radian) * y;// 当在第一或第二象限,l是width / 2 - x,否则l是-width / 2 - xconst l =angle < alpha || (angle > 180 - alpha && angle < 180)? width / 2 - x: -width / 2 - x;const n = Math.pow(Math.sin(radian), 2) * l;x1 = x + n;y1 = y + n / Math.tan(radian);x0 = -x1;y0 = -y1;}// 当渐变轴与矩形的交点落在垂直线上if ((angle > alpha && angle < 90) || // 处于第一象限(angle > 90 && angle < 180 - alpha) || // 处于第二象限(angle > 180 + alpha && angle < 270) || // 处于第三象限(angle > 270 && angle < 360 - alpha) // 处于第四象限) {// 将角度乘以(PI/180)即可转换为弧度const radian = ((90 - angle) * Math.PI) / 180;// 当在第一或第二象限,x是width / 2,否则x是-width / 2const x =(angle > alpha && angle < 90) || (angle > 90 && angle < 180 - alpha)? width / 2: -width / 2;const y = Math.tan(radian) * x;// 当在第一或第四象限,l是height / 2 - y,否则l是-height / 2 - yconst l =(angle > alpha && angle < 90) || (angle > 270 && angle < 360 - alpha)? height / 2 - y: -height / 2 - y;const n = Math.pow(Math.sin(radian), 2) * l;x1 = x + n / Math.tan(radian);y1 = y + n;x0 = -x1;y0 = -y1;}// 坐标系更改为canvas标准,Y轴向下为正方向x0 = Math.round(x0 + width / 2);y0 = Math.round(height / 2 - y0);x1 = Math.round(x1 + width / 2);y1 = Math.round(height / 2 - y1);return { x0, y0, x1, y1 };
}

canvas线性渐变实现:根据渐变线角度计算坐标x0,y0,x1,y1相关推荐

  1. [Halcon几何] 矩形顶点和对角连线角度计算

    描述:因为halcon中算子求的矩形角度有时候不是我所需要的角度,以算子smallest_rectangle2为例: 1)其获取的矩形角度范围- 90< angle <= 90,即无论通过 ...

  2. 蓝牙AOA定位:如何通过AOA角度计算坐标

    通过金桔AOA网关可以直接取得角度信息(详细见:蓝牙AOA定位网关上报数据格式),该角度的信息示意图如下: Φ角为俯仰角,θ角为方位角,如果设定网关的高度Z0和网关高度H,在已知Φ角的情况下可以推送出 ...

  3. html5线性渐变方向,使用canvas来完成线性渐变和径向渐变的功能的方法示例

    fillStyle的第二种使用情况就是渐变色的填充.渐变色就分为线性渐变色和径向渐变色. 线性渐变:大致分为两步 这里又会使用到canvas的两个新的函数. 第一步 : 使用一个新的函数createL ...

  4. canvas笔记-线性渐变与非线性渐变

    首先来看下线性渐变 //第一步 let grd = context.createLinearGradient(xstart, ystart, xend, yend);//第二步 Grd.addColo ...

  5. android 锥形进度条,canvas锥形进度条怎么渐变

    从一个渐变圆角进度条浅出画一个圆 开始 这一切需要从一个(简单)的需求开始,在最开始对设计第一眼看到这张图的时候,感觉挺简单的嘛,直接用echarts饼图模拟出来一个就好了 echarts 然后上ec ...

  6. CSS 3种渐变效果(线性渐变,径向渐变,圆锥型渐变)

    1 linear-gradient(线性渐变) 1.1按方向渐变 语法: background: linear-gradient(direction, color-stop1, color-stop2 ...

  7. CSS3渐变属性:线性渐变和径向渐变用法教程

    在CSS3之前如果需要添加渐变效果,通常要设置背景图像来实现.而CSS3中增加了渐变属性,通过渐变属性可以轻松实现渐变效果.CSS3的渐变属性主要包括线性渐变和径向渐变,本文转自黑马程序员前端培训课程 ...

  8. css新特性:线性渐变详解(重复性线性渐变、径向渐变、重复性径向渐变的使用)

    线性渐变 线性渐变 重复性线性渐变 径向渐变 重复性径向渐变的使用 线性渐变 线性渐变是向下.向上.向左.向右.对角方向的颜色渐变. 其语法格式为: background-image: linear- ...

  9. 【CSS】线性渐变、径向渐变

    文章目录 线性渐变 线性渐变 语法background-image:linear-gradient(方向,颜色1,颜色2-) 水平竖直方向 默认从上到下 to left 去到左边 从右往左 to ri ...

最新文章

  1. flask sqlalchemy踩坑记录
  2. 招聘|字节跳动计算机视觉算法实习生
  3. Java面试题之一 (转)
  4. putty-psftp
  5. 伟世盾安助国电高级培训中心实现一网双管
  6. boost::units::information相关的测试程序
  7. ABAP和XML数据格式互相转换的两种方式
  8. oracle json入参调用ws服务返回请求失败_Spring 5.2.2技术集成 —Spring HTTP调用程序和JAXWS...
  9. 上传html 0字节,HTML ajax 上传文件限制文件的类型和文件大小
  10. Java枚举:您拥有优雅,优雅和力量,这就是我所爱!
  11. Java基础之路--引用数据类型之数组
  12. T-SQL语句之创建、修改、删除数据库
  13. java泛型与c 泛型,Java泛型代码编译与javac,失败与Eclipse Helios
  14. R语言正则表达式[stringr package]
  15. 牛客 处女座的约会 规律
  16. 详解java静态数组
  17. Rockchip RK3288 Datasheet芯片手册资料
  18. java 计算器 正负号转换_【计算器正负号】一个小程序,有点问题
  19. mysql查询当前月份前两个月的数据_sql查询指定月份之前的几个月
  20. Java 对象 的 比较 - 细节狂魔

热门文章

  1. 720phi10p 和 720p有什么区别_除了情怀还剩什么?索尼Z5 Compact评测
  2. 网卡5790c linux驱动,Linux内核配置(12)
  3. Redis启动和连接
  4. string转换long
  5. 外包?第一份软件测试工作就一路高歌猛进,读书学Z渣一个现在生龙活虎
  6. HTML(HBuilder)作业题4- 隔行换色(jquery)
  7. 何为五笔输入的最高境界?
  8. 2022 CCF中国软件大会(CCF Chinasoft)“约束求解与定理证明”论坛成功召开
  9. 基于51单片机的LED呼吸灯设计(定时器)
  10. 通过Swap函数交换两个变量的值