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();
    }
  })
}

效果:
在这里插入图片描述

完整代码:

<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>
  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Canvas绘制曲线可以使用曲线和弧线两种方式。曲线是由一系列的点连接而成,每个点都有相同的曲率。而弧线则是圆周上的一部分。在Canvas中,可以使用moveTo(x, y)和lineTo(x, y)方法来绘制曲线。例如,可以使用以下代码在Canvas绘制一个曲线图形: ```html <canvas width="600" height="300" id="cvs"></canvas> <script> var oCanvas = document.getElementById('cvs'); var ctx = oCanvas.getContext('2d'); ctx.moveTo(10, 100); for(var i = 10; i < 600; i++){ var x = i; var y = 10 * Math.cos(x/10) + 100; ctx.lineTo(x, y); } ctx.strokeStyle = "orangered"; ctx.stroke(); </script> ``` 这段代码使用了Math.cos()函数来计算每个点的y坐标,然后使用lineTo()方法将点连接起来,最后使用stroke()方法绘制出曲线。\[1\] 除了使用曲线,还可以使用贝塞尔曲线来绘制曲线。贝塞尔曲线是根据四个位置任意的点坐标绘制出的一条光滑曲线。在Canvas中,可以使用bezierCurveTo(dx1, dy1, dx2, dy2, x, y)方法来绘制贝塞尔曲线。例如,可以使用以下代码在Canvas绘制一个贝塞尔曲线: ```html <canvas width="600" height="300" id="cvs"></canvas> <script> var oCanvas = document.getElementById('cvs'); var ctx = oCanvas.getContext('2d'); ctx.beginPath(); ctx.moveTo(50, 150); ctx.bezierCurveTo(100, 50, 200, 200, 250, 100); ctx.strokeStyle = "#FF0000"; ctx.lineWidth = 5; ctx.stroke(); </script> ``` 这段代码使用了bezierCurveTo()方法来绘制贝塞尔曲线,其中的参数分别表示控制点和终点的坐标。\[2\] 综上所述,Canvas可以使用曲线和贝塞尔曲线两种方式来绘制曲线图形。 #### 引用[.reference_title] - *1* *3* [canvas基础入门系列教程(5)-绘制曲线图形](https://blog.csdn.net/keledon/article/details/87114689)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [详述Canvas(四)/绘制曲线](https://blog.csdn.net/rentian1/article/details/78681655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值