美文网首页APP & program
uniapp中使用canvas的时候如何动态修改画布的高度

uniapp中使用canvas的时候如何动态修改画布的高度

作者: 周星星的学习笔记 | 来源:发表于2022-06-14 22:22 被阅读0次

    今天在做一个功能应用的时候,需要动态地画线(示例图如下),因为各个节点是动态从服务端请求过来的,所以线的数量也是动态的,这个时候对于画布的高度就要能自适应,但是对于canvas本身要预先设置好高度,但是一开始的高度又不知道(因为数据还没请求过来),那怎么处理呢,想了一个办法,就是等数据请求过来之后,然后计算出画布应该设置的高度,最后再把canvas开放出显示。

    示例

    一、模板代码

    <!-- 线路区域 -->
        <view class="footmark-line-wrap" id="footmarkLineWrap">
          <!-- 线路画布 -->
          <canvas
            v-if="isShowCanvas"
            canvas-id="lineBg"
            class="canvas-wrap"
            :style="{ height: lineBgHeight + 'rpx' }"
          ></canvas>
          <!-- 线路画布 -->
    
          <!-- 节点 -->
          <line-node
            class="line-node"
            :style="{
              left: item.left + 'px',
              top: item.top + 'px'
            }"
            :id="getNodeIndex(index)"
            v-for="(item, index) in nodeList"
            :key="item.id"
            :node-info="item"
            :node-index="index"
            :current-pos="currentPos"
            :button-color="buttonColor"
            @detail="showNodeDetailModal"
          ></line-node>
          <!-- 节点 -->
        </view>
        <!-- 线路区域 -->
    

    二、数据变量

    data() {
        return {
          //画布对象
          canvasContext: null,
          //节点高度
          nodeSize: {
            width: 0,
            height: 0
          },
          //画布高度
          lineBgHeight: 0,
          //线路区域的宽度
          lineAreaWidth: 0,
          //路线节点列表
          nodeList: [],
          //是否显示画布
          isShowCanvas: false
        }
      },
    

    三、方法

    //画布背景高度
    setLineBgHeight() {
          //通过获取到的节点数据来估算出画布的高度
          let nodeNum = this.nodeList.length
          if (nodeNum <= 3) {
            this.lineBgHeight = 800
          } else {
            this.lineBgHeight = 260 * nodeNum
          }
    },
    //获取节点的宽
    async getLineAreaWidth() {
          return new Promise((resolve) => {
            let query = uni.createSelectorQuery().in(this)
            query.select('#footmarkLineWrap').boundingClientRect()
            query.exec((res) => {
              if (res && res[0]) {
                resolve(res[0].width)
              }
            })
          })
    },
    //获取节点索引
    getNodeIndex(index) {
          return 'lineNode' + index
     },
    //获取节点的宽高
    async getLineNodeSize(index) {
          return new Promise((resolve) => {
            let domid = '#' + this.getNodeIndex(index)
            let query = uni.createSelectorQuery().in(this)
            query.select(domid).boundingClientRect()
            query.exec((res) => {
              if (res && res[0]) {
                resolve({
                  width: res[0].width,
                  height: res[0].height
                })
              } else {
                resolve(false)
              }
            })
          })
    },
    //处理节点列表(每个节点动态计算出坐标)
    handleNodeList() {
          //初始节点坐标
          let xLeftPos = 0
          let xRightPos = this.lineAreaWidth - 103
          let yPos = 0
          let findPos = false
          this.nodeList = this.nodeList.map((item, index) => {
            if (item.user_done == 0 && !findPos) {
              this.currentPos = index
              findPos = true
            }
            //判断当前索引处于偶数还是基数
            let isEven = index % 2 == 0
            //节点信息
            let itemInfo = {
              ...item,
              left: isEven
                ? xLeftPos + this.$u.random(0, this.lineAreaWidth / 6)
                : xRightPos - this.$u.random(0, this.lineAreaWidth / 5),
              top: yPos
            }
            yPos += 130
            return itemInfo
          })
    },
    //绘制线路
    async drawLine() {
          if (this.nodeList.length) {
            //获取节点的大小
            let nodeSize = await this.getLineNodeSize(0)
            if (!nodeSize) {
              nodeSize = {
                width: 99,
                height: 105
              }
            }
            this.canvasContext = uni.createCanvasContext('lineBg')
            //开始绘制
            this.canvasContext.beginPath()
            this.canvasContext.setShadow(10, 10, 50, '#EF808B')
            this.canvasContext.setLineCap('round')
            this.canvasContext.setLineJoin('round')
            this.canvasContext.setStrokeStyle('#EF9D73')
            this.canvasContext.setLineWidth(12)
            //节点列表
            this.nodeList.map((item, index) => {
              let xPos = item.left + nodeSize.width / 2
              let yPos = item.top + nodeSize.height / 2
              if (index == 0) {
                this.canvasContext.moveTo(xPos, yPos)
              } else {
                //前一个节点
                let prePoint = this.nodeList[index - 1]
                //控制点
                let cxPos = (item.left + prePoint.left + nodeSize.width) / 2
                let cyPos = (item.top + prePoint.top + nodeSize.height) / 2
                //随机出曲线控制点方向
                let controldirection = this.$u.random(0, 1)
                if (controldirection) {
                  cyPos -= this.$u.random(30, 80)
                } else {
                  cyPos += this.$u.random(30, 80)
                }
                this.canvasContext.quadraticCurveTo(cxPos, cyPos, xPos, yPos)
              }
            })
            this.canvasContext.stroke()
            this.canvasContext.draw()
          }
    },
    

    四、业务处理

    async onLoad(args) {
        //获取节点数据列表
        await this.getNodeList()
        //设置画布高度
        this.setLineBgHeight()
        //高度设置完成之后开启显示canvas
        this.isShowCanvas = true
        //设置线路区域的宽度
        this.lineAreaWidth = await this.getLineAreaWidth()
        //处理节点
        this.handleNodeList()
        //绘制线路
        this.drawLine()
    },
    

    五、CSS样式

    .footmark-line-wrap {
        position: relative;
        .canvas-wrap {
          width: 100%;
        }
        .line-node {
          position: absolute;
        }
    }
    

    相关文章

      网友评论

        本文标题:uniapp中使用canvas的时候如何动态修改画布的高度

        本文链接:https://www.haomeiwen.com/subject/xghtvrtx.html