Canvas实现连线题的方案设计

        开发“连线题”并没什么难点,这里主要分享的是:实现过程中的一点点布局设计上的小心思。想要的效果大体长这样(如下图所示):

1

        乍一看似乎需要获取每个元素的位置信息、计算连线的端点坐标,似乎很繁琐,而且每次页面尺寸变化时,都得重新计算。其实,事情可以比想象中简单很多…

一、方案设计

        1.1 将连线题分为上中下三个区块,其中:

        1)上下区块均使用flex(justify-content: space-around)

        2)中间区块为canvas,在style属性中将width和height设置为100%

.row-1 { justify-content: space-around; }

.row-2 {

        height: 0; flex-grow: 1;

        canvas { width: 100%; height: 100%; }

}

.row-3 { justify-content: space-around; }

2

        1.2 这样设置以后,有几点好处

        1)计算直线端点(元素中点)坐标就会变得很轻松,只需要排序百分比与canvas的内容宽度相乘即可。

let x1 = (上方元素下标 * 2 + 1) / (上方元素总数 * 2) * canvas.width

let x2 = (下方元素下标 * 2 + 1) / (下方元素总数 * 2) * canvas.width

// 连线上方端点坐标: (x1, 0)

// 连线下方端点坐标: (x2, canvas.height)

        2)页面resize时无需重新计算,页面也不会乱。当然如果resize前后差异较大,可能连线粗细程度会不美观。

        经测,一般不重新绘制也问题不大;如果要求高的话,可以在resize时重新绘制一下。(下图是第一张图在网页resize后的效果,线条经过拉伸变细了)

3

        3)如果你连canvas的尺寸也懒得初始化,也是可以的,只不过效果会差些(线条有点模糊,粗细不美观),Chrome中canvas默认内容尺寸是300*100,效果如下图所示(截图可能视觉效果不明显):

4

二、代码实现

        线条绘制的相关代码如下:

        Html

<canvas ref="canvas" :width="cvsWidth" :height="cvsHeight"></canvas>

        Js

// 动态调整canvas的内容尺寸(必要时,可在每次resize时重复调用)

initCanvas() {

  if (!this.$refs.canvas) return

  let cvsInfo = this.$refs.canvas.getBoundingClientRect()

  this.cvsWidth = parseInt(cvsInfo.width)

  this.cvsHeight = parseInt(cvsInfo.height)

},

// 绘制连线

drawLine() {

  if (!this.$refs.canvas) return

  let count = this.dataList.length

  let ctx = this.$refs.canvas.getContext("2d");

  let cvsWidth = this.$refs.canvas.width

  let cvsHeight = this.$refs.canvas.height

  ctx.clearRect(0, 0, cvsWidth, cvsHeight);

  ctx.lineWidth = 4;

  ctx.lineCap = 'round';

  ctx.strokeStyle = '#FF9C0A'

  for (let k in this.answerDict) {

    let _i1 = parseInt(k)

    let _i2 = this.answerDict[k]

    let _i1_x = (_i1 * 2 + 1) / (count * 2) * cvsWidth

    let _i2_x = (_i2 * 2 + 1) / (count * 2) * cvsWidth

    ctx.beginPath()

    ctx.moveTo(_i1_x, 0);

    ctx.lineTo(_i2_x, cvsHeight);

    ctx.stroke()

  }

},

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容