要求实现下面这个效果:
观察图片,我们的需求如下:
-
准备画布和上下文:在开始绘制之前,需要有一个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代码都结合起来就可以实现前文的图形效果了。