|
|
2
Community Egal
4 年前
路径和渲染变换
创建路径时,它使用调用路径函数时当前的变换,使用填充或笔划时,可以设置另一个变换。
这允许您使用单独的坐标系,一个用于形状,一个用于填充,一个用于笔划。
如果对填充和笔划使用单独的样式,这将非常有用。
将渐变拟合到路径的示例
该示例显示了缩放和转换的两个渐变,以适合在其自己的坐标系中创建的3个形状的填充和笔划。
中风有一个警告。
lineWidth
是一种样式,在以下情况下由当前变换进行变换:
stroke
被调用。这将限制您仅使用统一比例,并且必须反转
线宽
大小请参见如何在代码中执行。
const ctx = canvas.getContext("2d");
const grad1 = [[0, "green"], [0.45, "gold"], [0.55, "gold"], [1, "green"]];
const grad2 = [[0, "red"], [0.25, "black"], [0.75, "black"], [1, "red"]];
const addColStops = (g,s) => s.forEach(s => g.addColorStop(...s));
const style = {lineWidth: 5};
//==============================================================
// fill gradient
style.fillStyle = ctx.createLinearGradient(0, 0, 20, 0);
// to simplify I attach the coords to the gradient so that it can be scaled to
// fit the rendered content
style.fillStyle.coords = { w: 20, h: 0 };
addColStops(style.fillStyle, grad1);
//==============================================================
// stroke gradient
style.strokeStyle = ctx.createLinearGradient(0, 0, 0, 20);
style.strokeStyle.coords = { w: 0, h: 20 };
addColStops(style.strokeStyle, grad2);
//==============================================================
// 3 example boxes
drawBox(10, 10, 60, 130, style);
style.lineWidth += 4;
drawBox(90, 10, 80, 130, style);
style.lineWidth += 8;
drawBox(200, 10, 140, 130, style);
//==============================================================
// draw box
function drawBox(x, y, width, height, style) {
// shape drawn in default coordinates
ctx.setTransform(1, 0, 0, 1, 0, 0); // default transform
Object.assign(ctx, style); // set the style
//============================================================
// create the shape
ctx.beginPath();
ctx.rect(x, y, width, height);
//============================================================
// Make the gradient fit the stroke
const s = style.strokeStyle.coords;
// uniform scale for strokes only and correct for line width
var scale = (width + ctx.lineWidth) / (s.w ? s.w : 1);
if (s.w === 0) { scale = (height + ctx.lineWidth) / (s.h ? s.h : 1) }
ctx.setTransform(
scale, 0, 0, scale,
x - ctx.lineWidth / 2, // correct for line width
y - ctx.lineWidth / 2
);
// invert the lineWidth to correct its scale
ctx.lineWidth /= scale;
ctx.stroke();
//============================================================
// Make the fill gradient fit the rect
const f = style.fillStyle.coords;
ctx.setTransform(
width / (f.w ? f.w : 1), // scale grad width if needed
0, 0,
height / (f.h ? f.h : 1), // scale grad heigh if needed
x, y
);
ctx.fill();
}
<canvas id=canvas width="400"></canvas>
|