canvas根据坐标点绘制图形

有一需求,需要根据后台返回的坐标集在canvas中绘制图形。由于canvas使用不多,简单记录学习一下。整个需求实现主要分为三个部分

一.前端等比展示a4纸大小canvas画布
1. A4纸大小:210×297mm一般在ps中可以根据分辨率的不同转换成不同的px单位:
  1. 当分辨率是72像素/英寸时,A4纸像素长宽分别是842×595
  2. 当分辨率是120像素/英寸时,A4纸像素长宽分别是2105×1487
  3. 当分辨率是150像素/英寸时,A4纸像素长宽分别是1754×1240
  4. 当分辨率是300像素/英寸时,A4纸像素长宽分别是3508×2479
2.计算缩放比例
//calcRate方法,以宽为基准
calcRate(){
  let containerDom = this.$refs['canvas-container'] //获取DOM
  const containerWith = containerDom.clientWidth || containerDom.offsetWidth //获取DOM宽度
  // const rate = (containerWith / this.originWidth).toFixed() //会四舍五入,精度有影响
  const rate = Math.floor(containerWith / this.originWidth *100) / 100 //计算比例精确到两位小数
  this.rate = rate
}
3.计算画布大小
computed:{
    rateWidth(){
      return this.originWidth * this.rate //originWidth为原始宽度
    },
    rateHeight(){
      return this.originHeight * this.rate //originWidth为原始高度
    }
  }
4.canvas元素
<canvas ref="canvas" :width="rateWidth" :height="rateHeight"></canvas>
二.处理点集数据
后台返回数据处理
//[
//	[{x:xxx,y:xxx},{x:xxx,y:xxx},{x:xxx,y:xxx},{x:xxx,y:xxx}...],
//	[{x:xxx,y:xxx},{x:xxx,y:xxx},{x:xxx,y:xxx},{x:xxx,y:xxx}...],
//	[{x:xxx,y:xxx},{x:xxx,y:xxx},{x:xxx,y:xxx},{x:xxx,y:xxx}...]
//]
getDots(){
  Api.get_dots()
  .then(res=>{
    if(res.errCode ==0){
      let dots = res.data
      dots.forEach(item=>{
        item.forEach(it=>{
          it.x = it.x * this.rate //需要根据比例等比缩放大小保证位置正确
          it.y = it.y * this.rate //需要根据比例等比缩放大小保证位置正确
        })
      })
      this.dots = dots
      this.$nextTick(()=>{
        this.initCanvas()
      })
    }else{
      console.log(res.msg)
    }
  })
  .catch(err=>{
    console.log(err)
  })
}
三.绘制图形
// 初始化canvas对象,开始绘制。有两种绘图形式,一种是点多成线,另一种是连点成线。点足够多的话可以直接绘制小圆,这里采用的是连线法
initCanvas(){
  let canvasDom = this.$refs['canvas']
  let ctx = canvasDom.getContext("2d")
  this.dots.forEach(item=>{
    for(let i=0; i < item.length; i++){
      if(i == item.length-1) return  //注意循环结束条件
      ctx.beginPath();
      ctx.moveTo(item[i].x,item[i].y);
      ctx.lineWidth = 2
      ctx.lineTo(item[i+1].x,item[i+1].y)
      ctx.stroke();
    }
  })
}

效果:
canvas根据坐标点绘制图形_第1张图片

完整代码:

<template>
  <div class="canvas" ref="canvas-container">
    <canvas ref="canvas" :width="rateWidth" :height="rateHeight">
    </canvas>
  </div>
</template>

<script>
import * as Api from './indexApi'
//rate 换算比例(以宽为换算标准)
//originWidth 原始宽
//originHeight 原始高
//rateWidth 比例换算宽
//rateHeight 比例换算高
export default {
  data(){
    return{
      rate: 1,
      originWidth: 2480, //300分辨率
      originHeight: 3508, //300分辨率
      dots:[],
    }
  },
  computed:{
    rateWidth(){
      return this.originWidth * this.rate
    },
    rateHeight(){
      return this.originHeight * this.rate
    }
  },
  mounted(){
    this.getDots()
    this.calcRate()
  },
  methods:{
    getDots(){
      Api.get_dots()
      .then(res=>{
        if(res.errCode ==0){
          let dots = res.data
          dots.forEach(item=>{
            item.forEach(it=>{
              it.x = it.x * this.rate
              it.y = it.y * this.rate
            })
          })
          this.dots = dots
          this.$nextTick(()=>{
            this.initCanvas()
          })
        }else{
          console.log(res.msg)
        }
      })
      .catch(err=>{
        console.log(err)
      })
    },
    calcRate(){
      let containerDom = this.$refs['canvas-container']
      const containerWith = containerDom.clientWidth || containerDom.offsetWidth
      const rate = Math.floor(containerWith / this.originWidth *100) / 100
      this.rate = rate
    },
    initCanvas(){
      let canvasDom = this.$refs['canvas']
      let ctx = canvasDom.getContext("2d")
      this.dots.forEach(item=>{
        for(let i=0; i < item.length; i++){
          if(i == item.length-1) return 
          ctx.beginPath();
          ctx.moveTo(item[i].x,item[i].y);
          ctx.lineWidth = 2
          ctx.lineTo(item[i+1].x,item[i+1].y)
          ctx.stroke();
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.canvas{
  box-sizing: border-box;
  padding: 10px;
  width: 100%;
  display: flex;
  justify-content: center;
  canvas{
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  }
}
</style>

你可能感兴趣的:(vue,canvas,vue)