为了账号安全,请及时绑定邮箱和手机立即绑定

HTML5 Canvas 如何绘制带有渐变边框的圆角?

HTML5 Canvas 如何绘制带有渐变边框的圆角?

婷婷同学_ 2021-07-01 10:11:43
在我谷歌搜索了很多之后,我找不到任何回答如何在 HTML5 画布中绘制方圆形状的教程,请原谅我,因为我的数学很差。我尝试达到的效果:
查看完整描述

2 回答

?
MMTTMM

TA贡献1869条经验 获得超4个赞

如果我们阅读关于 squircles的维基百科文章,我们会看到这只是使用 2 或更高幂的未加权椭圆函数,这意味着我们可以很容易地计算给定“x”值的“y”值并以这种方式绘制东西,但是这样做会给我们带来极不均匀的片段:微小的变化x会导致y起点和终点的巨大变化,而y中点的微小变化。


相反,让我们将方圆建模为参数函数,因此我们改变一个控制值并获得合理均匀的间隔来使用。我们可以在关于超椭圆函数的维基百科文章中找到解释:


x = |cos(t)^(2/n)| * sign(cos(t))

y = |sin(t)^(2/n)| * sign(sin(t))

对于t从 0 到 2π,半径固定为 1(因此它们从乘法中消失)。


如果我们实现了这一点,那么我们几乎可以事后添加彩虹色,分别绘制每个路径段strokeStyle,使用 HSL 颜色的着色,其中色调值根据我们的t值发生变化:


// alias some math functions so we don't need that "Math." all the time

const abs=Math.abs, sign=Math.sign, sin=Math.sin, cos=Math.cos, pow=Math.pow;


// N=2 YIELDS A CIRCLE, N>2 YIELDS A SQUIRCLE

const n = 4;


function coord(t) {

  let power = 2/n;

  let c = cos(t), x = pow(abs(c), power) * sign(c);

  let s = sin(t), y = pow(abs(s), power) * sign(s);

  return { x, y };

}


function drawSegmentTo(t) {

  let c = coord(t);

  let cx = dim + r * c.x;     // Here, dim is our canvas "radius",

  let cy = dim + r * c.y;     // and r is our circle radius, with

  ctx.lineTo(cx, cy);         // ctx being our canvas context.


  // stroke segment in rainbow colours

  let h = (360 * t)/TAU;

  ctx.strokeStyle = `hsl(${h}, 100%, 50%)`;

  ctx.stroke();  


  // start a new segment at the end point

  ctx.beginPath();

  ctx.moveTo(cx, cy);

}

然后我们可以将它与一些标准的 Canvas2D API 代码结合使用:


const PI = Math.PI,

      TAU = PI * 2,

      edge = 200, // SIZE OF THE CANVAS, IN PIXELS

      dim = edge/2,

      r = dim * 0.9,

      cvs = document.getElementById('draw');


// set up our canvas

cvs.height = cvs.width = edge;

ctx = cvs.getContext('2d');

ctx.lineWidth = 2;

ctx.fillStyle = '#004';

ctx.strokeStyle = 'black';

ctx.fillRect(0, 0, edge, edge);

完成所有设置后,绘制代码非常简单:


// THIS DETERMINES HOW SMOOTH OF A CURVE GETS DRAWN

const segments = 32;


// Peg our starting point, which we know is (r,0) away from the center.

ctx.beginPath();

ctx.moveTo(dim + r, dim)


// Then we generate all the line segments on the path

for (let step=TAU/segments, t=step; t<=TAU; t+=step) drawSegmentTo(t);


// And because IEEE floats are imprecise, the last segment may not

// actually reach our starting point. As such, make sure to draw it!

ctx.lineTo(dim + r, dim);

ctx.stroke();

运行这将产生以下squircle:

//img1.sycdn.imooc.com//60e6d8420001ceca01940197.jpg

使用 jsbin,您可以玩数字:https ://jsbin.com/haxeqamilo/edit?js,output

当然,您也可以采用完全不同的方式:使用一个元素创建一个 SVG 元素(因为 SVG 是 HTML5 的一部分)<path>并适当地设置宽度、高度和视图框,然后生成一个d属性和渐变颜色,但这就是绝对更挑剔


查看完整回答
反对 回复 2021-07-08
  • 2 回答
  • 0 关注
  • 479 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信