自定義vue組件chart-view

前言: 我正式接觸web前端時間很短,前先後後差很少3個月左右的時間。我是16年從事android開發的,在android裏也常常會玩一下自定義控件。針對於以前移動端的折線圖,我在利用了空閒時間,用vue也寫了一個組件chart-view前端

1、先看看chartview的效果圖

chartview.gif

2、來看看chartview.vue

代碼不是很長,在代碼裏註釋的很是詳細,若有不懂,歡迎留言。vue

<template>
  <div >
    <canvas ref="canvas" width="500" height="500" ></canvas>
  </div>
</template>

<script>
export default {
  //部件
  components: {},
  //靜態
  //這裏至關於自定義了3個屬性
  //lineCenterX: X軸在畫布上Y方向的座標點(這樣設計的功能是由於公司業務,看明白了能夠把他改掉)
  //textFont: 文字大小
  //value_50: 50μv在畫布上的長度
  props: ['lineCenterX', 'textFont','value_50'],
  //對象內部的屬性監聽,也叫深度監聽
  watch: {
    
  },
  //屬性的結果會被緩存,除非依賴的響應式屬性變化纔會從新計算。主要看成屬性來使用;
  computed: {},
  //方法表示一個具體的操做,主要書寫業務邏輯;
  methods: {
    initDataSon(valueList) {

      //將畫布設置滿屏
      this.$refs.canvas.width = window.innerWidth
      this.$refs.canvas.height = window.innerHeight
      var ctx = this.$refs.canvas.getContext('2d')

      //當前控件的總長寬
      var total_W = this.$refs.canvas.offsetWidth // 返回元素的總寬度
      var total_H = this.$refs.canvas.offsetHeight // 返回元素的總高度

      ctx.font = 'normal ' + this.textFont + 'px Verdana'
      ctx.fillStyle = '#000000'

      //在畫布上肯定好+-50μv座標,並渲染到畫布上
      ctx.fillText('-50μv', 14, this.lineCenterX + this.value_50)
      ctx.fillText('+50μv', 14, this.lineCenterX - this.value_50 + this.textFont)


      //橫座標 (先用紅線畫出X軸)
      ctx.moveTo(0, this.lineCenterX)
      ctx.lineTo(total_W, this.lineCenterX)
      ctx.strokeStyle = '#ff0000'
      ctx.lineWidth = 0.3
      ctx.stroke()

      //縱座標
      // ctx.moveTo(0, 0)
      // ctx.lineTo(0, total_H)

      //畫筆改爲黑色,準備畫折線圖
      ctx.beginPath()
      ctx.strokeStyle = '#000000'
      ctx.lineWidth = 0.6

      
      //填充數據是不斷須要更新數據且須要渲染界面,因此這裏用到了nextTick方法
      this.$nextTick(() => {

        //每段x軸每一個刻度值之間的距離(其實這裏的ever_x,是根據你當前座標軸要展現多長時間的數據算的,好比總共波長是200s,你當前
        //只想展現10s,因此真的項目確定是肯定的,最好是把valueList.length也當成一個屬性去傳遞,是個固定值)
        var ever_x = total_W / (valueList.length - 1)
        for (const key in valueList) {
          
          //將數據放大1000倍(這裏徹底是根據咱們項目走的,能夠忽略這點)
          let itemValue = valueList[key] * 1000
          //知道了每一個x軸座標點,那麼再計算出每一個y軸的座標點
          let trueItemValue = itemValue/50*this.value_50 if (key === 0) {
            //單獨處理下x=0的點
            ctx.moveTo(0, this.lineCenterX - trueItemValue)
          } else {
            //鏈接以後的全部點
            ctx.lineTo(ever_x * key, this.lineCenterX - trueItemValue)
          }
        }

        ctx.stroke()

      })


    },
  },
  //請求數據
  created() {},
  mounted() {},


  
}

</script>

<style scoped>

</style>
複製代碼


3、頁面裏的使用

<template>
  <div>
    <button class="buttonStyle" @click="test">{{ buttonText }}</button>
    <div class="fatherCss" ref="fatherCss">
      <canvas-item
        :lineCenterX="50"
        :value_50="50"
        :textFont="14"
        ref="mychild"
      ></canvas-item>
    </div>
  </div>
</template>


<script>
import ChartView from '@/components/ChartView.vue'
import axios from 'axios'

export default {
  data() {
    return {
      //開始時間
      start: 0,
      //滿屏展現的波,所佔的時間
      showTotalTime: 20,
      //整個數據源的波長時間
      dataTotalTime: 210,
      //波的總數據源list
      list: [],
      //如下用於處理按鈕點擊
      isScroll: false,
      buttonText: '點擊開始',
      timer: null,
    }
  },

  //部件
  components: {
    'canvas-item': ChartView,
  },
  //靜態
  props: {},
  //對象內部的屬性監聽,也叫深度監聽
  watch: {},
  //屬性的結果會被緩存,除非依賴的響應式屬性變化纔會從新計算。主要看成屬性來使用;
  computed: {},
  //方法表示一個具體的操做,主要書寫業務邏輯;
  methods: {
    initData() {
      //若是開始時間不得大於總時間
      if (this.start >= this.dataTotalTime) {
        return
      }

      //若是當前展現波的末尾時間大於總時間,那麼末尾時間就等於總時間
      var lastTime = this.start + this.showTotalTime if (lastTime >= this.dataTotalTime) {
        lastTime = this.dataTotalTime
      }

      var dataList = []

      //用開始時間和總時間算出數據源起始index,取整
      let start = Math.floor(
        (this.list.length * this.start) / this.dataTotalTime
      )

      //同理算出末尾index
      let end = Math.floor((this.list.length * lastTime) / this.dataTotalTime)

      //從總數據獲取當前所展現的數據
      dataList = Object.assign([], dataList, this.list.slice(start, end))
      this.$refs.mychild.initDataSon(dataList)

      //起始時間每次+20ms,由於下面開啓了間隔20ms運行一次,模擬波的運動
      this.start += 0.02
    },
    test() {
      if (this.isScroll) {
        //表明是滾動時候
        this.isScroll = false
        this.buttonText = '點擊開始'
        clearInterval(this.timer)
      } else {
        //未滾動時候
        this.isScroll = true
        this.buttonText = '點擊暫停'
        this.initData()
        this.timer = setInterval(() => {
          this.initData() //自定義函數
        }, 20)
      }
    },
  },
  //請求數據
  created() {
    axios.get('/js/data.json').then(
      (response) => {
        this.list = Object.assign([], this.list, response.data.list)
        this.initData()
      },
      (response) => {
        console.log('error')
      }
    )
  },
  mounted() {},

  beforeDestroy(){
    //生命週期銷燬時,清楚定時器timer
    clearInterval(this.timer)
    this.timer = null
  }
}
</script>

<style scoped>
.buttonStyle {
  display: block;
}

.fatherCss {
  position: absolute;
}
</style>


複製代碼


4、github地址

chart-viewjava

相關文章
相關標籤/搜索