我的编程空间,编程开发者的网络收藏夹
学习永远不晚

使用canvas怎么绘制一个树形结构的可视图形

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

使用canvas怎么绘制一个树形结构的可视图形

这篇文章给大家介绍使用canvas怎么绘制一个树形结构的可视图形,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

  • 树形分支是后端接口返回数据渲染,可展示多条;

  • 代码可拓展,可封装;

  • 点击节点可查看备注;

使用canvas怎么绘制一个树形结构的可视图形

<canvas id="canvas" width="750" height="800"></canvas>
const canvas_options={    canvasWidth: 750,    canvasHeight: 800,    chartZone: [70,70,750,570], //坐标绘制区域    yAxisLabel: ['0%','10%','20%','30%','40%','50%','60%','70%','80%','90%','100%'],//y轴坐标text    yAxisLabelWidth: 70,//y轴最大宽度    yAxisLabelMax: 100,//y轴最大值    middleLine: 410, //中间线    pillarWidth: 10,//柱子宽度    distanceBetween: 50,//柱状图绘制区域距离两边间隙    pillar: [120,70,700,750],//柱状图绘制区域    mainTrunkHeight: 90,//底部开始主干高度    dialogWidth: 300,//弹窗宽度    dialogLineHeight: 30,//弹窗高度    dialogDrawLineMax: 4,}const nodeClick = [];var chooseNode = null;const datalist={    showDataInfo: {        city:[            {                 name: '项目1',                 status: 1, //状态:0已完成 1进行中                node: [                    { value: 10, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                    { value: 20, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                ]             },            {                 name: '项目2',                 status: 0, //状态:0已完成 1进行中                node: [                    { value: 10, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                    { value: 50, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                    { value: 100, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                ]             },            {                 name: '项目3',                 status: 1, //状态:0已完成 1进行中                node: [                    { value: 20, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                    { value: 30, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                    { value: 40, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                ]             },            {                 name: '项目4',                 status: 1, //状态:0已完成 1进行中                node: [                    { value: 20, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                    { value: 30, date: '2020-03-12 15:50:02', content: '用于组织信息和操作,通常也作为详细信息的入口。' },                ]             },        ]    }}const canvas = document.getElementById("canvas");const ctx = canvas.getContext('2d');ctx.save();drawYLabel(canvas_options,ctx); //绘制y轴坐标drawStartButton(ctx,canvas_options);drawData(ctx,datalist.showDataInfo,canvas_options);canvas.addEventListener("click",event=>{    //清除之前的弹窗    if(chooseNode!=null){        ctx.clearRect(0, 0, canvas.width, canvas.height);        ctx.save();         drawYLabel(canvas_options,ctx); //绘制y轴坐标         drawStartButton(ctx,canvas_options);         drawData(ctx,datalist.showDataInfo,canvas_options);        chooseNode = null    }    //判断点击节点    let rect = canvas.getBoundingClientRect();    let zoom = rect.width/canvas_options.canvasWidth;    let x = (event.clientX/zoom - rect.left/zoom).toFixed(2);    let y = (event.clientY/zoom - rect.top/zoom).toFixed(2);    for(var t=0;t<nodeClick.length;t++){        ctx.beginPath();        ctx.arc(nodeClick[t].x,nodeClick[t].y,15,0,Math.PI*2,true);        if(ctx.isPointInPath(x, y)){            textPrewrap(ctx,`备注描述:${nodeClick[t].date}`,nodeClick[t].x+20,nodeClick[t].y+20,canvas_options.dialogWidth-40);            ctx.restore();            chooseNode=t            break;        }else{            chooseNode=null        }    }});//content:需要绘制的文本内容; drawX:绘制文本的x坐标; drawY:绘制文本的y坐标;//lineMaxWidth:每行文本的最大宽度function textPrewrap(ctx,content,drawX, drawY, lineMaxWidth){    var drawTxt=''; //当前绘制的内容    var drawLine  = 1;//第几行开始绘制    var drawIndex=0;//当前绘制内容的索引    //判断内容是够可以一行绘制完毕    if(ctx.measureText(content).width<=lineMaxWidth){        drawDialog(ctx,canvas_options.dialogWidth,canvas_options.dialogLineHeight,drawX,drawY);        ctx.fillText(content.substring(drawIndex,i),drawX.drawY);    }else{        for(var i=0;i<content.length;i++){            drawTxt += content[i];            if(ctx.measureText(drawTxt).width>=lineMaxWidth){                drawDialog(ctx,canvas_options.dialogWidth,canvas_options.dialogLineHeight,drawX,drawY);                ctx.fillText(content.substring(drawIndex,i+1),drawX,drawY);                drawIndex = i+1;                drawLine+=1;                //drawY+=lineHeight;                drawTxt='';            }else{                //内容绘制完毕,但是剩下的内容宽度不到lineMaxWidth                if(i===content.length-1){                    drawDialog(ctx,canvas_options.dialogWidth,canvas_options.dialogLineHeight,drawX,drawY);                    ctx.fillText(content.substring(drawIndex,i+1),drawX,drawY)                }            }        }    }}function drawDialog(ctx,width,height,x,y){    ctx.beginPath();    ctx.fillStyle="rgba(0,0,0,0.8)";    ctx.fillRect(x,y,width,height);    ctx.font="22px ''";    ctx.fillStyle="#fff";    ctx.textAlign = 'left';    ctx.textBaseline="top";}//绘制y轴坐标function drawYLabel(options,ctx){    let labels = options.yAxisLabel;    let yLength = (options.chartZone[3]-options.chartZone[1])*0.98;    let gap = yLength/(labels.length-1);    labels.forEach((item,index)=>{        //绘制圆角背景        //this.radiusButton(ctx,0,options.chartZone[3]-index*gap-13,50,24,8,"#313947");        //绘制坐标文字        ctx.beginPath();        ctx.fillStyle="#878787";        ctx.font="18px ''";        ctx.textAlign="center";        ctx.fillText(item,25,options.chartZone[3]-index*gap+5);        //绘制辅助线        ctx.beginPath();        ctx.strokeStyle="#eaeaea";        ctx.strokeWidth=2;        ctx.moveTo(options.chartZone[0],options.chartZone[3]-index*gap);        ctx.lineTo(options.chartZone[2],options.chartZone[3]-index*gap);        ctx.stroke();    })}//绘制开始按钮function drawStartButton(ctx,options){    //绘制按钮图形    this.radiusButton(ctx,options.middleLine-(160/2),options.canvasHeight-50,160,50,8,'#F4C63D');    ctx.fillStyle="#fff";    ctx.font="24px ''";    ctx.textAlign="center";    ctx.fillText('开始',options.middleLine,options.canvasHeight-15);    //绘制状态    ctx.beginPath();    ctx.fillStyle="#333";    ctx.font="24px ''";    ctx.textAlign = "left";    ctx.fillText("已完成",0,options.canvasHeight-100);    ctx.fillText("进行中",0,options.canvasHeight-50);    //绘制红色按钮    ctx.beginPath();    ctx.fillStyle="#d35453";    ctx.arc(options.chartZone[0]+30,options.canvasHeight-100-7,8,0,2 * Math.PI,true);    ctx.fill();    ctx.beginPath();    ctx.strokeStyle="#d35453";    ctx.arc(options.chartZone[0]+30,options.canvasHeight-100-7,14,0,2 * Math.PI,true);    ctx.stroke();    //绘制蓝色按钮    ctx.beginPath();    ctx.fillStyle="#24b99a";    ctx.arc(options.chartZone[0]+30,options.canvasHeight-50-8,8,0,2 * Math.PI,true);    ctx.fill();    ctx.beginPath();    ctx.strokeStyle="#24b99a";    ctx.arc(options.chartZone[0]+30,options.canvasHeight-50-8,14,0,2 * Math.PI,true);    ctx.stroke();}//封装绘制圆角矩形函数function radiusButton(ctx,x,y,width,height,radius,color_back){    ctx.beginPath();    ctx.fillStyle= color_back    ctx.moveTo(x,y+radius);    ctx.lineTo(x,y+height-radius);    ctx.quadraticCurveTo(x,y+height,x+radius,y+height);    ctx.lineTo(x+width-radius,y+height);    ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);    ctx.lineTo(x+width,y+radius);    ctx.quadraticCurveTo(x+width,y,x+width-radius,y);    ctx.lineTo(x+radius,y);    ctx.quadraticCurveTo(x,y,x,y+radius);    ctx.fill()}//绘制数据function drawData(ctx,data,options){    //const paths=[];    let number = data.city.length;    //绘制矩形    data.city.forEach((item,index)=>{        let indexVal = number==1?1:index;        let numberVal = number==1?2:number-1        let x0 = options.chartZone[0]+options.distanceBetween+(options.chartZone[2]-options.chartZone[0]-options.distanceBetween*2)/numberVal*indexVal;        let value = item.node[item.node.length-1].value;        let height = (value/options.yAxisLabelMax*(options.chartZone[3]-options.chartZone[0])*0.98).toFixed(2);        let y0=options.chartZone[3] - height;        //柱状图底部        ctx.beginPath();        ctx.fillStyle= '#eee';        ctx.fillRect(x0-5,80,options.pillarWidth,options.chartZone[3]-80);        //贝塞尔曲线        ctx.beginPath();        ctx.strokeStyle = item.status==0?"#d35453":'#24b99a';        ctx.lineWidth=options.pillarWidth;        ctx.moveTo(options.middleLine,options.pillar[3]); //贝塞尔曲线起始点        ctx.lineTo(options.middleLine,options.canvasHeight-50-options.mainTrunkHeight); //贝塞尔曲线中间竖线        ctx.quadraticCurveTo(x0,options.canvasHeight-50-options.mainTrunkHeight,x0,options.chartZone[3]);        //绘制柱状图进度        ctx.lineTo(x0,y0);        ctx.stroke();        //绘制文字        ctx.font="28px ''";        ctx.textAlign='center';        ctx.fillStyle="#333";        ctx.fillText(item.name,x0,options.chartZone[1]-20);        //绘制节点        item.node.forEach((node_item,node_index)=>{            let y1= options.chartZone[3] - (node_item.value/options.yAxisLabelMax*(options.chartZone[3]-options.chartZone[0])*0.98).toFixed(2);            ctx.beginPath();            ctx.arc(x0,y1,15,0,Math.PI*2,true);            ctx.fillStyle="rgba(108,212,148,1)";            ctx.fill();            ctx.beginPath();            ctx.arc(x0,y1,9,0,Math.PI*2,true);            ctx.fillStyle="rgba(255,255,255,0.8)";            ctx.fill();            const pointInfo={                x:x0,                y:y1,                date: node_item.data,                content: node_item.content,                value: node_item.value            };            nodeClick.push(pointInfo);        })    })}

关于使用canvas怎么绘制一个树形结构的可视图形就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

使用canvas怎么绘制一个树形结构的可视图形

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

使用canvas怎么绘制一个树形结构的可视图形

这篇文章给大家介绍使用canvas怎么绘制一个树形结构的可视图形,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。树形分支是后端接口返回数据渲染,可展示多条;代码可拓展,可封装;点击节点可查看备注;2023-06-09

利用canvas怎么绘制一个多边形

利用canvas怎么绘制一个多边形?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1. 初始化js代码 //初始化 (function(){ var canvas =
2023-06-09

使用Css怎么绘制一个扇形

今天就跟大家聊聊有关使用Css怎么绘制一个扇形,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。span { @if $count == 1 { width: $di
2023-06-08

使用canvas怎么绘制一个心电图

这期内容当中小编将会给大家带来有关使用canvas怎么绘制一个心电图,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。思路:1.模拟点(如果你有真实的数据,那就是把数据幻化成canvas对应的坐标点)模拟点时
2023-06-09

使用canvas怎么绘制一个太极图

今天就跟大家聊聊有关使用canvas怎么绘制一个太极图,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。css样式代码.animation{ width: 800px; height
2023-06-09

Python数据可视化之怎么用Matplotlib绘制常用图形

这篇文章主要介绍Python数据可视化之怎么用Matplotlib绘制常用图形,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、散点图散点图用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或
2023-06-15

使用canvas怎么实现一个图形验证码功能

本篇文章给大家分享的是有关使用canvas怎么实现一个图形验证码功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
2023-06-09

Android开发中怎么使用canvas绘制一个统计图

Android开发中怎么使用canvas绘制一个统计图?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。效果如下: 特点:1.使用非常方便,可放在xml布局文件中,然后在代码
2023-05-31

怎么在H5中使用canvas实现一个动态图形功能

怎么在H5中使用canvas实现一个动态图形功能?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。什么是动画?我们在绘制动画之前必须要弄清楚什么是动画,一个动画最起码需要哪些基
2023-06-09

怎么使用js+canvas实现可自动吸附闭合的鼠标绘制多边形

这篇文章主要介绍“怎么使用js+canvas实现可自动吸附闭合的鼠标绘制多边形”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用js+canvas实现可自动吸附闭合的鼠标绘制多边形”文章能帮助大
2023-07-02

使用Canvas怎么绘制一个旋转的太极

今天就跟大家聊聊有关使用Canvas怎么绘制一个旋转的太极,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。cssbody{ background: #ddd;}#canvas{
2023-06-09

利用java怎么构造一个无限层级的树形菜单

这期内容当中小编将会给大家带来有关利用java怎么构造一个无限层级的树形菜单,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1、构造一个实体类,用来存储节点,所以我们构造的需要四个对象(id,pid,nam
2023-05-31

使用递归怎么删除树形结构的所有子节点

使用递归怎么删除树形结构的所有子节点?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1.业务场景有如下树形结构: +—0 +—1 +—2 +—4 +—5 +—3如
2023-05-31

使用Canvas怎么绘制一个未闭合的带进度条圆环

这期内容当中小编将会给大家带来有关使用Canvas怎么绘制一个未闭合的带进度条圆环,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、定义变量定义半径,定义圆环厚度,定义圆心位置、定义默认填充颜色let r
2023-06-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录