使用canvas画布绘制任意角度线性渐变色

一、引言

最近做一个小需求,用到了canvas的渐变色API createLinearGradient,突发奇想怎么设置旋转角度?看了mdn的文档好像没有角度参数啊?问题不大,自己写!

使用canvas画布绘制任意角度线性渐变色

二、首先简单介绍一下如何使用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.接下来就是计算角度线和平行线的交点,因为是中心对称,所以只需计算第一象限的点

使用canvas画布绘制任意角度线性渐变色

用三角函数计算坐标点

1.一些特殊的角度需要单独处理,对传入的角度限制在第一象限内计算。计算完毕后转化为canvas坐标系

使用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 作者:跟你拼了

(0)
上一篇 2024年2月21日 上午10:21
下一篇 2024年2月21日 上午10:32

相关推荐

发表回复

登录后才能评论