要求实现下面这个效果:
观察图片,我们的需求如下:
-
准备画布和上下文:在开始绘制之前,需要有一个HTML5
<canvas>
元素,并且获取其绘图上下文(context
),这是进行绘图操作的基础。 -
定义形状和样式:对于想要绘制的每个形状(文本、矩形、圆形),需要定义它们的位置、尺寸和样式。这通常涉及到创建包含这些属性的对象。
-
编写绘制函数:需要编写或使用现有的函数来绘制这些形状。这些函数通常会接受上下文和形状的属性作为参数,并使用Canvas API进行绘制。
-
添加视觉效果:增强视觉效果,添加阴影和渐变色。这通常涉及到使用Canvas API中的阴影和渐变相关方法。
-
组合元素:将所有的绘制操作组合在一起,形成一个完整的绘图流程。确保每一步都按照正确的顺序执行,以实现预期的视觉效果。
function drawCanvas() {// 设置文本位置var text = {x: canvas.width / 2,y: canvas.height / 2};drawText(context, text, 1, 64);// 设置矩形位置和尺寸var rect = {x: canvas.width / 2 - 35,y: canvas.height / 2 - 40,h: 70,w: 70};drawRectPath(context, rect, 1);// 设置圆形位置和半径var circle = {x: canvas.width / 2,y: canvas.height / 2 - 5,r: 80,clockwise: false};drawCirclePath(context, circle, 0, 1);// 添加阴影效果putShadowOnPath(context, "yellow", 10, -10, 20);// 创建并应用渐变色var grd = createLinearGradient(context, 150, 150, canvas.width - 150, canvas.height - 150, colors);putColorOnPath(context, grd, 1, 5);
}
上面的代码提供了一个框架,具体的每个函数实现还需要更进一步设计,我将提供一些参考:
/*** 绘制文本* @author zjvivi* @version 1.0* @buildDate 2024-9-22* @param {Object} context 绘制的目标context* @param {Object} text 包括字体及大小的font,起始点水平对齐align,起始点垂直基线baseline,起始点坐标(x,y)等信息* @param {String} style 填充色/描边色/其他样式* @param {Number} isFill 是否填充,true/1表示填充,反之描边* @param {Number} lineWidth 绘制线条的宽度*/
function drawText(context,text,isFill,lineWidth) {context.font=`${text.fontSize}px ${text.font}` ; //设置字体大小context.textAlign=text.align;context.textBaseline=text.baseline;if(isFill){context.fillStyle=text.style;context.fillText(text.text, text.x,text.y); //绘制填充文本}else{context.strokeStyle=text.style;context.lineWidth=lineWidth || 1;context.strokeText(text.text, text.x,text.y); //绘制描边文本}
}
/*** 绘制矩形路径* @author zjvivi* @version 1.0* @buildDate 2024-9-22* @param {Object} context 绘制的目标context* @param {Object} rect 包括绘制起始点坐标(x,y)、宽度width和高度height信息* @param {*} isNewPath 是否开启新路径 是否开启新路径,true/1表示开启,反之不开启*/
function drawRectPath(context,rect,isNewPath) {if(isNewPath) context.beginPath();context.rect(rect.x, rect.y, rect.w, rect.h);
}
/*** 绘制圆形路径* @author zjvivi* @version 1.0* @buildDate 2024-9-22* @param {Object} context 绘制的目标context* @param {Object} cirle包括绘制圆心坐标(x,y)、半径r、起始弧度startAngle、终止弧度endAngle和是否顺时针clockwise信息* @param {Boolean} isNewPath 是否开启新路径 是否开启新路径,true/1表示开启,反之不开启* @param {Boolean} isClosePath 是否闭合路径 true/1表示闭合,反之不闭合*/
function drawCirclePath(context,circle,isNewPath,isClosePath){if(isNewPath) context.beginPath();context.arc(circle.x,circle.y,circle.r,circle.sAngle,circle.eAngle,!circle.clockwise);if(isClosePath) context.closePath();
}
/*** 设置路径阴影* @author zjvivi* @version 1.0* @buildDate 2024-9-22* @param {Object} context 绘制的目标canvas* @param {String} color 阴影颜色* @param {*} offsetX * @param {*} offsetY * @param {*} blur */
function putShadowOnPath(context,color,offsetX,offsetY,blur) {if(blur!==undefined) context.shadowBlur=blur;if(color!==undefined) context.shadowColor=color;if(offsetX!==undefined) context.shadowOffsetX=offsetX;if(offsetY!==undefined) context.shadowOffsetY=offsetY;}
/*** 创建线性渐变对象* @author zjvivi* @version 1.0* @buildDate 2024-9-22* @param {*} context 绘制目标context对象* @param {*} x1 起始点的x坐标* @param {*} y1 起始点的y坐标* @param {*} x2 终止点的x坐标* @param {*} y2 终止点的x坐标* @param {*} colors 颜色数组colors=[{pos:0,color:'orange'},...]* @returns */
function createLinearGradient(context,x1,y1,x2,y2,colors){let grd=context.createLinearGradient(x1, y1, x2, y2);for(let i=0;i<colors.length;i++){grd.addColorStop(colors[i].pos, colors[i].color);}return grd;
}
/*** 设置路径样式* @author zjvivi* @version 1.0* @buildDate 2024-9-22* @param {Object} context 绘制的目标context* @param {String} style 填充色/描边色/其他样式* @param {Number} isFill 是否填充,true/1表示填充,反之描边* @param {Number} lineWidth 绘制线条的宽度*/
function putColorOnPath(context,style,isFill,lineWidth) {if(isFill){context.fillStyle=style;context.fill(); }else{context.strokeStyle=style;context.lineWidth=lineWidth || 1;context.stroke();}
}
这些函数被设计为通用函数,可作为函数库在后续开发中使用。将html,js代码都结合起来就可以实现前文的图形效果了。