一、引言
最近做一个小需求,用到了canvas的渐变色API createLinearGradient,突发奇想怎么设置旋转角度?看了mdn的文档好像没有角度参数啊?问题不大,自己写!
二、首先简单介绍一下如何使用createLinearGradient
1.createLinearGradient函数参数只有两个坐标点
2.通过addColorStop添加不同颜色以及权重。
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const gradient = ctx.createLinearGradient(0, 0, 200, 200);
gradient.addColorStop(0, "red");
gradient.addColorStop(0.5, "#66ccff");
gradient.addColorStop(1, "red");
这样就可以绘制出一个从(0, 0)到(200, 200)的渐变色
三、构思功能实现
1.要实现旋转渐变色,需要把旋转中心置于形状中心,等计算完毕后再转化到canvas坐标系。
2.考虑到是线性渐变,这里可以用与角度垂直的两条平行线框出一片最小区域,只要把这部分区域应用上渐变色,就可以实现带角度的渐变
3.接下来就是计算角度线和平行线的交点,因为是中心对称,所以只需计算第一象限的点
用三角函数计算坐标点
1.一些特殊的角度需要单独处理,对传入的角度限制在第一象限内计算。计算完毕后转化为canvas坐标系
const calcAngle = (angle, width, height) => {
if (angle == 0) {
return [0, 0, width, 0];
} else if (angle == 90) {
return [0, height, 0, 0];
} else if (angle == 180) {
return [width, 0, 0, 0];
} else if (angle == 270) {
return [0, 0, 0, height];
}
// 移动坐标系到形状中心
width = width / 2;
height = height / 2;
const limitRange = Math.abs(angle % 90);
const r = Math.sqrt(width ** 2 + height ** 2);
let rectAngle = Math.atan(height / width);
let radian = (limitRange * Math.PI) / 180;
let linearRectWidth = r * Math.cos(rectAngle - radian);
let x2 = linearRectWidth * Math.cos(radian);
let y2 = linearRectWidth * Math.sin(radian);
let x1 = -x2;
let y1 = -y2;
// 计算完成,移回原坐标系
x1 = width + x1;
y1 = height - y1;
x2 = width + x2;
y2 = height - y2;
return [x1, y1, x2, y2];
}
将计算出的点应用到canvas画布上
const draw = (ctx, width, height, rect) => {
const rect = calAngle(30, width, height);
const colorList = ["#66ccff", "#fff", "#66ccff"];
const linearGradient = ctx.createLinearGradient(...rect);
for(let i = 0; i < colorList.length; i++) {
let step = i / (colorList.length - 1);
linearGradient.addColorStop(step, colorList[i])
}
ctx.fillStyle = linearGradient;
ctx.fillRect(0, 0, width, height);
}
四、总结
计算两个坐标点实现任意角度的线性渐变,主要难点在转化坐标系计算
demo:
原文链接:https://juejin.cn/post/7337269117970464806 作者:跟你拼了