canvas g6在项目中的心的体会

2,083 阅读4分钟

为什么我们在项目中用canvas?(why)

产品经历的需求:做个组织架构图。 需求大致如下:公司下边有部门,部门要和负责人同级,子部门下边也会有相应的负责人和部门;如图所示

有人问了:为什么不用dom去做

这是个好问题,其实之前我们就是用dom来做组织架构图的。

用dom也有他的弊端,比如一旦涉及到2000条以上的数据,对于组织架构这种复杂业务,如果我们用dom做,渲染的时间会很长,甚至直接导致浏览器崩溃。所以这个时候canvas登场了。

g6其实是基于canvas封装的库

个人使用canvas优势: 1.渲染速度快

劣势: 1.g6的文档写的不太好,很多文档只有api使用文档但是没有当前api具体例子,导致我们在用的时候要自己去尝试踩坑。 2.跟dom不一样,每个图形的位置需要自己手动计算,在用g6画卡片的时候会有这样的一种感觉:我是在做浏览器排列dom的核心算法。因为所有的图形并不会平白无故的就按顺序排列。所以也就要我们去算每个元素所在的位置,接下来我分享以下计算文案宽度所的收获的东西。

计算文字的宽度

为什么要计算文字宽度,不计算行不行? 上边提到到了canvas的劣势:它不会平白无故的就按顺序排列元素。也就是我们如果不指定文字的位置,那么你可以看到下边话横线的文字,都会在堆叠在一个地方,而且后边的文字会覆盖前边的文字;

所以我们必须要排列文字,而排列文字就要知道当前文字的起始坐标,而第二列文字和第一列文字的长度有关系(就跟我们用dom一样,如果这是两个span标签,第一个span标签如果文字增加,那么第二个span标签的位置也会相应的增加);

V-01

之前我认为,两个英文字母和一个汉字所占的像素是一样的,但事实如此吗?

我们来验证一下;

以下两个汉字的宽度:

四个字母的宽度:

结论:通过上边三张图我们可以知道,其实一个汉字不等于两个字母的宽度,甚至字母所占的像素都是不一样的。所以用正则将 汉字转换为字母,再通过字符串数量来计算文案的长度是不正确的。

V-02

那么既然两个字母的像素宽度不等与一个汉字的宽度,那么我有了第二中方案: 手动量出每个字母所占的像素。

export const WIDTH_ALPHABET_MAP = {
  // 小写
  a_WIDTH: 7.83,
  b_WIDTH: 8.22,
  c_WIDTH: 7.67,
  d_WIDTH: 8.22,
  e_WIDTH: 7.78,
  f_WIDTH: 5.23,
  g_WIDTH: 8.28,
  h_WIDTH: 7.8,
  i_WIDTH: 3.59,
  j_WIDTH: 3.75,
  k_WIDTH: 7.41,
  l_WIDTH: 3.3,
  m_WIDTH: 11.98,
  n_WIDTH: 7.83,
  o_WIDTH: 8.22,
  p_WIDTH: 8.22,
  q_WIDTH: 8.22,
  r_WIDTH: 5.13,
  s_WIDTH: 7.08,
  t_WIDTH: 4.98,
  u_WIDTH: 7.84,
  v_WIDTH: 6.75,
  w_WIDTH: 10.58,
  x_WIDTH: 7.14,
  y_WIDTH: 6.95,
  z_WIDTH: 6.83,
  // 大写
  A_WIDTH: 9.2,
  B_WIDTH: 9.48,
  C_WIDTH: 10.2,
  D_WIDTH: 9.89,
  E_WIDTH: 8.92,
  F_WIDTH: 8.08,
  G_WIDTH: 10.48,
  H_WIDTH: 10.09,
  I_WIDTH: 3.33,
  J_WIDTH: 7.25,
  K_WIDTH: 9.67,
  L_WIDTH: 8.23,
  M_WIDTH: 12.36,
  N_WIDTH: 10.08,
  O_WIDTH: 10.75,
  P_WIDTH: 9,
  Q_WIDTH: 10.75,
  R_WIDTH: 9.47,
  S_WIDTH: 8.86,
  T_WIDTH: 8.67,
  U_WIDTH: 10,
  V_WIDTH: 8.95,
  W_WIDTH: 13.03,
  X_WIDTH: 8.92,
  Y_WIDTH: 9.28,
  Z_WIDTH: 8.75,
};

但是接下来问题又出现了,上边只是字母所占的宽度,那么数字呢? 之后我又测量出了每个数字所占像素的宽度;

export const WIDTH_NUMBER_MAP = {
  0: 8.41,
  1: 5.63,
  2: 8.41,
  3: 8.41,
  4: 8.41,
  5: 8.41,
  6: 8.41,
  7: 7.67,
  8: 8.41,
  9: 8.41,
};

特殊字符呢?

难道要每个都量出来吗?显然我走错方向了。

V-03

查找了g6的API,发现没有计算文字宽度的方法;那么直接 cavans 中的API有没有呢? 在w3schools上我找到了这样的api;

  • measureText

www.w3schools.com/tags/canvas…

最后总结

  • 两个英文字母和一个汉字所占的像素通常是不一样的
  • 我个人在实验的过程中还发现,就算是相同的字体,fontWeight不一样,不同字符所占的像素情况也很多。比如,现在我们现在页面中只有一个span标签,只给这个span标签设置了font-size为14px,fontWeight分别设置为400和600后会发现,汉字所占像素没有变化,但英文字母前后所占像素也不一样,特殊字符前后所占像素也不一样;这次通过踩坑,个人对字体的理解更深了。
  • 我们要的到画布上文字的长度的时候,measureText是最简单有效的
  • 这次也对思维方式做了反思,我们在用一个新框架的时候,要对底层的了解要稍微全面才行。比如:g6是canvas的封装,在用g6之前我应该先看一遍canvas,做到心中有底才去看g6,要不然直接用g6会很虚。

参考文献

www.w3schools.com/tags/canvas…