Skip to content

vue-echarts插件使用(Day9 2/2) ​

本页对应 day9,共 6 段视频,约 1 小时 49 分。

学习目标 ​

  • 能够定位并修复菜单权限递归过滤中因共享引用导致的数据污染问题,使用深拷贝/克隆保证每次过滤基于原始数据。
  • 能够说明数据可视化的概念、常见 2D/3D 图表类型,以及数据大屏中 VW/VH 与 transform 缩放两种适配思路。
  • 能够使用 Canvas API 绘制矩形、文字、弧和线段,并正确设置填充色、描边色、线宽及清除指定画布区域。
  • 能够使用 SVG 标签绘制线段、折线/多边形、矩形、圆/椭圆和路径,并通过属性或样式控制尺寸、颜色与描边。
  • 能够说明 ECharts/vue-echarts 与 Canvas、SVG、WebGL 的关系,并完成基础图表渲染配置。

知识点 ​

先界定本节范围:ECharts 与 vue-echarts 的分层 ​

本节原始笔记没有附图片和代码,因此不虚构截图与代码;只保留转写稿中可确认的调试片段,并标注来源。转写稿里的“一叉/一chance/H叉”应理解为 ECharts,“康va/cavas/comvas”应理解为 canvas,“SVTSV/SVD”应理解为 SVG,“忘GL/wabGL”应理解为 WebGL,“three点GS/reeGS”应理解为 Three.js。

为什么需要:项目要做数据可视化工作报表,Vue 项目需要图表能力。笔记只给了两个关键词,必须先分清“图表库”和“Vue 适配层”。

怎么想:笔记写“echarts插件:angular,react,vue”,说明 ECharts 不绑定单一框架;又写“vue-echarts:vue框架[插件]”,说明 vue-echarts 是 Vue 框架下的插件/适配层,不是另一个图表引擎。转写稿视频2也明确:项目采用 Vue3 结合 ECharts 实现工作报表。

怎么做:在 Vue 项目中先查 package.json,确认是否同时存在 echarts 与 vue-echarts,再确认 Vue 版本;具体安装命令、组件注册和模板写法本节笔记未记录,不能补写,应以课堂后续或官方文档为准。

易错点:把 vue-echarts 当成 ECharts 本身;以为 ECharts 只能用于 Vue;忽略 Vue 版本与插件版本对应;把“插件”理解成独立图表库。

从技术选型看为什么需要 vue-echarts ​

为什么需要:ECharts 可服务 Angular、React、Vue,但在 Vue 中直接操作 DOM、生命周期、resize 和销毁会重复劳动,因此需要 Vue 侧封装。

怎么想:分层理解——ECharts 负责图表能力,vue-echarts 负责 Vue 集成。转写稿视频2提到“Vue3 的项目结合 ECharts 去实现工作报表”,说明业务落点是 2D 数据报表,而不是先做 3D。

怎么做:先确认项目是 Vue3;确认 ECharts 已作为基础依赖;vue-echarts 作为 Vue 插件接入;业务图表优先对应柱状图、折线图等报表形态。转写稿还提到 ECharts 底层会用到 HTML、SVG、canvas、WebGL,所以学插件前了解底层即可。

易错点:把 vue-echarts 当成业务组件;忽略 ECharts 依赖;误以为 vue-echarts 可用于 Angular/React——它是 Vue 框架插件,跨框架的是 ECharts 本身。

转写稿底层推导:canvas/SVG 影响图表调试 ​

为什么需要:ECharts 底层会涉及 canvas/SVG,图表不显示时,先查容器和渲染层,比先怀疑插件更有效。

怎么想:转写稿视频3明确:canvas 是 H5 新增双闭合标签,默认宽高 300×150,浏览器把它当图片;canvas 的宽高不能用样式设置,必须用 width、height 属性,否则会变形。视频6明确:SVG 是矢量,放大不失真,可用样式设大小,图形可绑定点击;canvas 内部矩形不能直接绑点击,只能给 canvas 元素绑。

怎么做:转写稿中的调试片段可整理为(仅说明底层,不是 vue-echarts 写法):

js
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
ctx.fillStyle = 'red'
ctx.fillRect(100, 100, 50, 250)

这里要纠正同音字:fillRect 不是“feel right”,getContext 不是“get contest”,strokeStyle 不是“死joke style”,beginPath 不是“比根”,arc 不是“ARC”。

易错点:用 CSS 给 canvas 设宽高导致坐标错乱;给 canvas 内部图形绑点击;把 SVG 与 canvas 混为一谈;忘记 canvas 坐标 0 点在左上角。

接入与调试核对清单 ​

为什么需要:本节笔记没有记录 vue-echarts 的安装命令、组件模板、配置项,直接写具体 API 会编造。

怎么想:用核对清单替代臆造:框架版本、依赖、容器宽高、渲染器、数据更新、resize、销毁。转写稿视频1的菜单权限问题属于权限递归与深拷贝问题,不是 vue-echarts 问题,不能混入本节。

怎么做:查 package.json;确认 Vue3;确认 echarts 与 vue-echarts;给图表容器明确宽高;窗口变化时处理 resize;组件卸载时销毁实例;数据变化后更新;具体写法以官方文档为准。

易错点:容器高度为 0;重复初始化;未销毁;版本不匹配;把 canvas 调试代码直接当 vue-echarts 用法;把权限过滤问题误判为图表插件问题。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

1. canvas 基本使用 —— 绘制矩形 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>canvas 基本使用 - 绘制矩形</title>
  <style>
    /* 这里只给边框,绝对不能用 width/height 设置画布大小 */
    canvas { border: 1px solid #000; }
  </style>
</head>
<body>
  <!-- 画布的宽高必须写成"属性",不写默认 300 × 150 -->
  <canvas id="cvs" width="600" height="400"></canvas>

  <script>
    // 1. 获取 canvas 元素(DOM 对象)
    const canvas = document.querySelector('#cvs');
    // 2. 获取"笔"——2D 上下文,之后所有绘制都靠它
    const ctx = canvas.getContext('2d');

    // 3. 第一个矩形:X 100, Y 100, 宽 50, 高 250
    ctx.fillStyle = '#f00';          // 先设颜色,再绘制,有先后顺序
    ctx.fillRect(100, 100, 50, 250);

    // 4. 再画三个,凑成柱状图的样子
    ctx.fillStyle = 'rgba(0, 0, 255, 0.6)';
    ctx.fillRect(160, 50, 50, 300);
    ctx.fillStyle = 'green';
    ctx.fillRect(220, 200, 50, 150);
    ctx.fillStyle = '#1a9';
    ctx.fillRect(280, 10, 50, 340);

    // 5. 画文字:先设字体,再 fillText
    ctx.font = '20px 微软雅黑';
    ctx.fillStyle = '#333';
    ctx.fillText('数据可视化', 100, 200);
  </script>
</body>
</html>

关键行与易错点

  • canvas 是 H5 新增的双闭合标签,默认宽高 300 × 150;标签内部写文字不会显示,任何内容都必须用 JS 绘制。
  • 宽高必须用属性 width="600" height="400" 设置;用 CSS 样式(行内/内部/外部)设置会把画布拉伸,坐标全部错乱。写了 px 不写都行,单位默认就是 px。
  • getContext('2d') 返回的是 CanvasRenderingContext2D 实例(引用类型),fillStyle、font 是它的属性,fillRect、fillText 是原型上的方法。
  • 坐标原点 (0, 0) 在左上角,Y 轴向下递增;fillRect(x, y, w, h) 四个参数缺一不可。
  • fillStyle 必须在 fillRect 之前设置,支持英文色名、十六进制、rgb()/rgba()。
  • 浏览器把 canvas 当成一张图片(右键可"图片另存为"),但里面画出来的东西是像素,不是 DOM 元素,绑不了点击事件,只能给 canvas 标签本身绑。

2. canvas 绘制弧、线段与鼠标涂鸦 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>canvas 绘制弧与线段</title>
  <style>
    canvas { border: 1px solid #000; }
  </style>
</head>
<body>
  <canvas id="cvs" width="600" height="400"></canvas>

  <script>
    const canvas = document.querySelector('#cvs');
    const ctx = canvas.getContext('2d');

    // 半圆:圆心(100,100),半径 50,起始弧度 0,结束弧度 Math.PI(180°)
    ctx.beginPath();
    ctx.arc(100, 100, 50, 0, Math.PI, false); // false = 顺时针
    ctx.stroke();

    // 100 个同心圆(饼图、托盘的原理)
    for (let i = 0; i < 100; i++) {
      ctx.beginPath();
      ctx.arc(300, 200, i * 2, 0, Math.PI * 2, false); // 2π 就是一个整圆
      ctx.lineWidth = 1;
      ctx.strokeStyle = 'red';
      ctx.stroke();
    }

    // 折线:一个起点 + 多个其他点
    ctx.beginPath();
    ctx.moveTo(100, 300);
    ctx.lineTo(200, 350);
    ctx.lineTo(300, 300);
    ctx.lineTo(400, 380);
    ctx.lineWidth = 4;
    ctx.strokeStyle = '#08f';
    ctx.stroke();

    // 鼠标涂鸦,鼠标抬起时清空画布
    let drawing = false;
    canvas.onmousedown = function (e) {
      drawing = true;
      ctx.beginPath();
      ctx.moveTo(e.offsetX, e.offsetY);            // 起点只有一个
      ctx.strokeStyle = `rgb(${Math.random() * 255 | 0},${Math.random() * 255 | 0},${Math.random() * 255 | 0})`;
      ctx.lineWidth = 10;
    };
    canvas.onmousemove = function (e) {
      if (!drawing) return;
      ctx.lineTo(e.offsetX, e.offsetY);            // 其他点可以有多个
      ctx.stroke();
    };
    canvas.onmouseup = function () {
      drawing = false;
      ctx.clearRect(0, 0, 600, 400);               // 清除区域:x, y, w, h
    };
  </script>
</body>
</html>

关键行与易错点

  • arc(x, y, r, 起始弧度, 结束弧度, 是否逆时针) 六个参数:前两个是圆心,第三个半径,最后一个是布尔值,true 逆时针、false 顺时针。
  • JS 里的角度单位是弧度不是度:2π = 360°,π = 180°,1 弧度 ≈ 57.4°。
  • 画弧/线前必须 beginPath() 开启新路径,画完 stroke() 描边(或 fill() 填充);不调用 beginPath() 会让上一次的路径和样式残留、串联在一起。
  • moveTo 只能有一个起点,lineTo 可以有多个其他点,连起来就是折线。
  • 线宽 lineWidth、线条颜色 strokeStyle、填充颜色 fillStyle 都是属性,要在绘制前赋值。
  • 鼠标事件里取坐标用 e.offsetX / e.offsetY(相对 canvas 左上角);mousemove 里必须判断 drawing 状态,否则鼠标一动就乱画。
  • mouseup 时要把状态复位,否则会一直画;clearRect(x, y, w, h) 只清指定区域,想清全屏就传 0, 0, 画布宽, 画布高。
  • 这类"手写涂鸦"用 canvas 不卡,用原生 DOM(div 堆)既卡又做不出同样效果。

3. SVG 基本使用 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 基本使用</title>
  <style>
    /* 和 canvas 不同,SVG 可以直接用样式设置大小 */
    svg { width: 600px; height: 400px; border: 1px solid #000; }
  </style>
</head>
<body>
  <svg xmlns="http://www.w3.org/2000/svg">
    <!-- 线段:x1 y1 是起点,x2 y2 是终点 -->
    <line x1="100" y1="100" x2="200" y2="200" stroke="red" stroke-width="2"/>

    <!-- 多边形:points 就是点集 -->
    <polygon points="100,100 170,100 120,300" fill="yellowgreen"/>

    <!-- 矩形 -->
    <rect x="300" y="100" width="50" height="250" fill="red"/>

    <!-- 圆:cx cy 是圆心,r 是半径 -->
    <circle cx="200" cy="250" r="50" fill="orange" stroke="black"/>

    <!-- 椭圆:rx 水平半径,ry 垂直半径 -->
    <ellipse cx="400" cy="250" rx="50" ry="20" fill="#08f"/>

    <!-- 路径:M 起点,L 其他点,Z 闭合(阿里图标库的图标几乎都是这种写法) -->
    <path d="M450,50 L500,150 L550,50 Z" fill="green"/>
  </svg>
</body>
</html>

关键行与易错点

  • SVG 也是 H5 新增的双闭合标签 / 语义化标签,但它是个容器,里面的图形全靠子标签(line、rect、circle、polygon、path…)画出来,不用写 JS。
  • 默认宽高同样是 300 × 150;但与 canvas 相反,SVG 可以用 CSS 样式设置宽高,而且缩放不失真(矢量图),这正是阿里图标库用它的原因。
  • line 的 x1/y1/x2/y2、rect 的 x/y/width/height、circle 的 cx/cy/r、ellipse 的 rx/ry 都是属性,不是样式。
  • 颜色:fill 是填充色,stroke 是描边色,stroke-width 是线宽。不设 stroke 时线段默认看不见(白色/无描边),这是最常踩的坑。
  • 图形是真实 DOM 节点,可以绑定点击事件、可以用 CSS 改颜色改大小——这点和 canvas 里画出来的像素完全不同。
  • path 的 d 里:M 是起点,L 是其他点,Z 把终点和起点闭合;项目里从阿里图标库直接复制这段 SVG 代码粘进模板即可,不必下载到本地再引 icon 类。

常见错误 ​

  1. 现象:vue-echarts 图表不显示或高度为 0。→ 原因:图表容器没有明确宽高,或父级高度未撑开。→ 修法:给容器设置明确宽高,开启自适应,并在数据更新后正确触发图表更新。
  2. 现象:切换账号后菜单权限过滤结果错乱。→ 原因:递归过滤时直接修改了共享源数据/引用。→ 修法:过滤前先深拷贝,基于副本生成新结果,保证每次登录过滤互不影响。
  3. 现象:canvas 矩形尺寸用 CSS 设置后图形被拉伸、坐标错位。→ 原因:只改了显示尺寸,没有改画布像素尺寸。→ 修法:用 width、height 属性设置画布尺寸,样式只负责显示布局。
  4. 现象:连续绘制矩形、圆、线段时颜色或路径互相污染。→ 原因:未在每次绘制前重置路径和样式。→ 修法:每次绘制前 beginPath(),按需设置 fillStyle、strokeStyle、lineWidth,需要闭合时 closePath()。
  5. 现象:给 canvas 里画出的矩形绑定点击事件无效。→ 原因:绘制内容不是 DOM 元素,事件只能绑在 canvas 上。→ 修法:事件绑到 canvas,用坐标做命中检测;需要元素级交互时改用 SVG/DOM。
  6. 现象:复制阿里图标 SVG 后不显示或颜色不对。→ 原因:缺少 viewBox/宽高,或 fill、stroke 被写死。→ 修法:保留 viewBox,按需设置宽高和 fill/stroke,必要时用 currentColor。
  7. 现象:数据大屏在不同屏幕错位。→ 原因:布局和图表尺寸大量写死 px。→ 修法:使用 vw/vh 或 transform: scale() 方案做整体适配。
  8. 现象:canvas 绘制弧的方向与预期相反。→ 原因:起止弧度或逆时针参数理解反。→ 修法:确认弧度制与布尔值含义,必要时交换起止角或调整方向参数。

练习 ​

  1. 使用 vue-echarts 实现一个柱状图,要求容器自适应,并在数据更新后图表同步刷新。
  2. 用原生 canvas 绘制一组柱状图,包含坐标位置、颜色、文字和线段,并说明如何避免多次绘制互相污染。
  3. 用 canvas 实现一个简易签名板:鼠标按下开始、移动绘制、抬起结束,并提供清空画布功能。
  4. 从阿里图标库复制一个 SVG 图标到页面中,完成大小调整、颜色调整,并说明保留 viewBox 的原因。
  5. 模拟菜单权限过滤:准备一份源菜单数据,分别用两个账号过滤,验证切换账号后源数据不被污染。

原视频对照 ​

#视频时长
1解决菜单权限问题206:51
2数据可视化的简介20:12
3canvas基本使用之绘制矩形34:35
4canvas绘制弧18:17
5canvas绘制线段11:15
6svg基本使用18:00

小结 ​

  1. vue-echarts 是上层封装,排查问题时要同时看容器、配置项和底层渲染。
  2. canvas 绘制内容不是 DOM,交互要靠坐标计算或外层元素代理。
  3. canvas 的宽高优先用属性控制,不要只用 CSS 控制显示尺寸。
  4. SVG 更适合图标和需要元素级交互的场景,复制图标时要关注 viewBox、fill、stroke。
  5. 权限过滤必须保证无副作用,深拷贝是避免账号间数据污染的关键手段。
  6. 数据大屏适配不要写死 px,优先考虑 vw/vh 或整体缩放方案。
  7. 先掌握 canvas/SVG 基础,再使用图表插件,定位问题会更快。
  8. 调试可视化问题时,先查容器尺寸,再查数据结构,最后查绘制/配置顺序。