2 回答
![?](http://img1.sycdn.imooc.com/54584ed2000152a202200220-100-100.jpg)
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:
使用 jsbin,您可以玩数字:https ://jsbin.com/haxeqamilo/edit?js,output
当然,您也可以采用完全不同的方式:使用一个元素创建一个 SVG 元素(因为 SVG 是 HTML5 的一部分)<path>
并适当地设置宽度、高度和视图框,然后生成一个d
属性和渐变颜色,但这就是绝对更挑剔。
添加回答
举报