可视化指南之- canvas | 小册免费学

320 阅读4分钟

Canvas

 <body>
 <canvas width="512" height="512"></canvas> 
</body>

Canvas 元素上的 width 和 height 属性不等同于 Canvas 元素 的 CSS 样式的属性。这是因为,CSS 属性中的宽高影响 Canvas 在页面上呈现的大小,而 HTML 属性中的宽高则决定了 Canvas 的坐标系。为了区分它们,我们称 Canvas 的 HTML 属性宽高为画布宽高,CSS 样式宽高为样式宽高

简单来说就是 我们可以通过设置css来设置Canvas的展示宽高比, 同时通过Canvas的 width height属性来设置Canvas坐标系的宽高!

当我们 设置的Canvas的width大于Css的时候,表示 我们可以获取更多的像素坐标,虽然那些区域并不被展示出来。

Canvas的坐标系

默认左上角为原点。x轴向右,y轴向下。

与传统的笛卡尔坐标系不一致~ 需要注意

另外 如果在三维坐标下的话。Canvas对应的就是左右坐标系

Canvas绘制

 const canvas = document.querySelector('canvas'); // 获取页面的Canvas
 const context = canvas.getContext('2d');// 设置上下文参数为2d

context 对象上会有许多 API,它们大体上可以分为两类:一类是设置状态的 API,可以设置或改变当前的绘图状态,比如,改变要绘制图形的颜色、线宽、坐标变换等 等;另一类是绘制指令 API,用来绘制不同形状的几何图形。

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形需要一些额外的步骤。

  1. 首先,你需要创建路径起始点。
  2. 然后你使用画图命令去画出路径。
  3. 之后你把路径封闭。
  4. 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。

参数:

beginPath()
//新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。

closePath()
//闭合路径之后图形绘制命令又重新指向到上下文中。

stroke()
//通过线条来绘制图形轮廓。

fill()
//通过填充路径的内容区域生成实心的图形。

来简单画个正方形吧

  1. 获取 Canvas 对象,通过 getContext(‘2d’) 得到 2D 上下文;

  2. 设置绘图状态,比如填充颜色 fillStyle,平移变换 translate 等等;

  3. 调用 beginPath 指令开始绘制图形;

  4. 调用绘图指令,比如 rect,表示绘制矩形;

  5. 调用 fill 指令,将绘制内容真正输出到画布上。

  const canvas = document.querySelector('canvas')
      console.log(canvas)
      const context = canvas.getContext('2d')
      const canvas_are = {
        width:500,
        height:500
      }
      canvas.width = canvas_are.width
      canvas.height = canvas_are.height
      //绘制一个100*100的正方形吧
      let rectSize = [100,100]
      context.fillStyle = 'red' //设置背景颜色
      context.beginPath() // 开始绘制
      context.rect(0.5*canvas.width-rectSize[0]/2,0.5*canvas.height-rectSize[1]/2,...rectSize) //绘制具体步骤
      context.fill() //闭合路径

#平移画布/恢复平移
context.save(); // 暂存状态
// 平移
 context.translate(-0.5 * rectSize[0], -0.5 * rectSize[1]);
 ... 执行绘制
 context.restore(); // 恢复状态

Canvas绘制层级关系图

{
 "name":"中国",
 "children":
[
{
 "name":"浙江" , 
 "children":
  [
	  {"name" : "杭州"}
  ]
}
]
}
image-20210324191952654

需要绘制来表现JSON的层级关系

在这个过程中,我们应当先处理数据, 将数据内容与绘图指令建立映射关系,然后遍历数据,通过映射关系将代表数据内容的参数 传给绘图指令,最后将图形绘制到 Canvas 上。

我们可以借助d3 这个工具包 来帮我们将数据进行处理,包括层级分配定位等

分割为类似如下的数据:

image-20210325140852041

来看一下具体的代码吧

//引入d3工具包
<script src="https://d3js.org/d3-hierarchy.v1.min.js"></script>
(async function () {
  const data = await (await fetch(dataSource)).json();
  const regions = d3.hierarchy(data)
    .sum(d => 1)
    .sort((a, b) => b.value - a.value);

  const pack = d3.pack()
    .size([900, 900])
    .padding(5);

  const root = pack(regions);

  const canvas = document.querySelector('canvas');
  const context = canvas.getContext('2d');
  const TAU = 2 * Math.PI;

  function draw(ctx, node, {fillStyle = 'rgba(0, 0, 0, 0.2)', textColor = 'white'} = {}) {
    const children = node.children;
    const {x, y, r} = node;
    ctx.fillStyle = fillStyle;
    ctx.beginPath();
    ctx.arc(x, y, r, 0, TAU);
    ctx.fill();
    if(children) {
      for(let i = 0; i < children.length; i++) {
        console.log(children[i])
        draw(context, children[i]);
      }
      let centerName = node.data.name
      ctx.fillStyle = 'red'
      ctx.font = '0.8rem Arial';
      ctx.textAlign = 'center';
      ctx.fillText(centerName, x, y);
    } else {
      const name = node.data.name;
      ctx.fillStyle = textColor;
      ctx.font = '0.8rem Arial';
      ctx.textAlign = 'center';
      ctx.fillText(name, x, y);
    }
  }

  draw(context, root);
}());

Canvas优点

1.Canvas 是一个非常简单易用的图形系统。结合刚才的例子你也能感受到,Canvas 通过一组简单的绘图指令,就能够方便快捷地绘制出各种复杂的几何图形。

2.Canvas 渲染起来相当高效。即使是绘制大量轮廓非常复杂的几何图形,Canvas 也 只需要调用一组简单的绘图指令就能高性能地完成渲染。这个呀,其实和 Canvas 更偏向于 渲染层,能够提供底层的图形渲染 API 有关。那在实际实现可视化业务的时候,Canvas 出 色的渲染能力正是它的优势所在。

Canvas缺点

1.因为 Canvas 在 HTML 层面上是一个独立的画布元素,所以所有 的绘制内容都是在内部通过绘图指令来完成的,绘制出的图形对于浏览器来说,只是 Canvas 中的一个个像素点,我们很难直接抽取其中的图形对象进行操作。

补充 : 如何实现操纵Caanvas呢 可以通过计算点的坐标来确定位置,当确定鼠标移动到圆内后 渲染新的样式

codepen.io/gltjk/pen/G…

本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情