本篇的目的是要了解:
- 封装渲染状态
- 提供一个通用的点集绘制函数,可以绘制点线面,封闭与否,及填充与否
1. 提供渲染状态进栈/出栈操作:
pushStates() {
this.context.save();
}
popStates() {
this.context.restore();
}
2. 设置Line相关渲染状态:(lineWidth,lineCap,lineJoin,miterLimit,default值见代码注释)
/*
ctx.lineWidth = value; canvas2d default 1.0
ctx.lineCap = "butt"; canvas2d default
ctx.lineCap = "round";
ctx.lineCap = "square";
ctx.lineJoin = "bevel";
ctx.lineJoin = "round";
ctx.lineJoin = "miter"; canvas2d defaule
ctx.miterLimit = value; canvas2d default 10.0
*/
setLineState(lineWidth = 2.0, lineCap = 'butt', lineJoin = 'round', miterLimit = 10.0) {
let ctx = this.context;
ctx.lineWidth = lineWidth;
ctx.lineCap = lineCap;
ctx.lineJoin = lineJoin;
ctx.miterLimit = miterLimit;
}
3. 设置shadow相关渲染状态:(shadowColor,shadowOffsetX/Y,shadowBlur,default值见代码注释)
/*
ctx.shadowColor = color; canvas2d default rgba(0,0,0,0)
ctx.shadowOffsetX = offset; canvas2d default 0.0
ctx.shadowOffsetY = offset; canvas2d default 0.0
ctx.shadowBlur = level; canvas2d default 0.0
*/
setShadowState(shadowColor = 'rgba(0,0,0,0.5)', shadowOffsetX = 2, shadowOffsetY = 2, shadowBlur = 2) {
let ctx = this.context;
ctx.shadowColor = shadowColor;
ctx.shadowOffsetX = shadowOffsetX;
ctx.shadowOffsetY = shadowOffsetY;
ctx.shadowBlur = shadowBlur;
}
4. 设置文本相关渲染状态:(textAlign,textBaseLine,font,default值见代码注释)
/*
ctx.textAlign = "left" || "right" ||
"center" || "start" ||
"end";
canvas2d default start
ctx.textBaseline = "top" || "hanging" ||
"middle" || "alphabetic" ||
"ideographic" || "bottom";
canvas2d default alphabetic
ctx.font = value; canvas2d default 10px sans-serif
*/
setTextState(textAlign = 'center', textBaseLine = 'middle', font = '14px sans-serif') {
let ctx = this.context;
ctx.textAlign = textAlign;
ctx.textBaseLine = textBaseLine;
ctx.font = font;
}
5. 点集绘制函数:
//通用函数,可以绘制点线面,是否封闭,是否填充
//其他绘制函数,都是该函数的特殊形式
drawPoints(points = [], style = 'red', isClosed = true, isFill = true) {
//必须要大与等于2个点
if (points.length < 2)
return;
let ctx = this.context;
ctx.save();
ctx.beginPath();
//移动到第一个点位置
ctx.moveTo(points[0].x, points[0].y);
//从1-(n-1)循环绘制线段
for (let i = 1; i < points.length; i++) {
ctx.lineTo(points[i].x, points[i].y);
}
//如果需要,封闭路径
if (isClosed == true) {
ctx.closePath();
}
//填充还是描边绘制
if (isFill == true) {
ctx.fillStyle = style;
ctx.fill();
} else {
ctx.strokeStyle = style;
ctx.stroke();
}
ctx.restore();
}
6. 测试:
let canvas = document.getElementById("myCanvas");
let context = canvas.getContext('2d');
let render = new BLFRender(context);
render.clear();
render.drawGrid('white', 'black', 20, 20);
//设置全局的shadow和line,以及文本渲染状态
//影响所有下面的绘制
render.setShadowState();
render.setLineState();
render.setTextState();
render.drawRect(new Rect(10, 10, 80, 40));
render.drawRect(new Rect(110, 10, 80, 40), 'blue', false);
render.drawCircle(new Circle(310, 60, 50));
render.drawCircle(new Circle(410, 60, 50), 'blue', false);
/*
下面两个函数共同点:
1. 圆心都为【600,60】,半径都为50px
2. 起始角都为30度,结束角都为180度
3. isClosed都设置为false,不封闭arc路径
下面两个函数不同点:
1. 上面函数isCCW(是否逆时针) = false,style = red
2. 下面函数isCCW(是否逆时针) = true, style = blue
*/
render.drawArc(new Arc(600, 60, 50, 30, 180, false), 'red', false);
render.drawArc(new Arc(600, 60, 50, 30, 180, false, true), 'blue', false);
let pts = [new Point(700, 50), new Point(790, 50), new Point(790, 200)];
render.drawPoints(pts, 'blue', false, false);
render.drawText(100, 100);
效果:
可以看到阴影出现了,文字变化了,关于线段相关属性,大家可以调整一下lineWidth到例如25,再设置其他属性,就可以明显看到各种变化。具体就自己测试一下吧!
htmlpreview.github.io/?https://github.com/jackyblf/BLF_JS_Demos/blob/master/drawShape.html