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

今天在做一个功能应用的时候,需要动态地画线(示例图如下),因为各个节点是动态从服务端请求过来的,所以线的数量也是动态的,这个时候对于画布的高度就要能自适应,但是对于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;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容