简体   繁体   English

ChartJS 在 Vue 中不起作用

[英]ChartJS not working in Vue

I am making a little productivity app/game to make my self feel better about all the time I waste.我正在制作一个小的生产力应用程序/游戏,让我对我浪费的所有时间感觉更好。 I am using vue and chartjs and the don't seem to play nice with each other.我正在使用 vue 和 chartjs,但它们似乎不太适合彼此。

When I include my <canvas> element in <div id="app"> , the one vue is initiated on chartjs fails to render anything.当我在<div id="app">包含我的<canvas>元素时,在 chartjs 上启动的一个 vue 无法呈现任何内容。 There are no errors or anything.没有错误或任何东西。 However, when I move <canvas> outside of <div id="app"> it works perfectly.但是,当我将<canvas>移到<canvas> <div id="app">它运行良好。 Doesn't anyone have any insight in this?没有人对此有任何见解吗?

HTML HTML

<body>

  <div id="app">
    <div id="header">
      <h1>GAME OF LIFE!</h1>
    </div>
    <div class="character_container">
      <div class="health_bar">
        <div class="life"></div>
      </div>
      <div class="character">
        <img id="sprite" src="imgs/melee/1.png" width="100" height="100px">
        <div class="stats">
          <p>ed</p>
          <p>3</p>
          <p>3</p>
          <p>da</p>
          <p>adf</p>
          <p>adf</p>
        </div>
      </div>
    </div>
    <div id="dashboard">
      <h2>GAME DATA</h2>
      <input type="date" name="viewDate" v-model="viewDate">
    </div>
    <!-- Doesn't work when canvas inside #app -->
    <div class="canvas">
      <canvas></canvas>
    </div>
  </div>
  <!-- Works when the canvas is outside #app -->
  <!-- <div class="canvas">
    <canvas></canvas>
  </div> -->

  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.bundle.min.js"></script>
  <script src="vue.js"></script>
  <script src="app.js"></script>
</body>

Javascript Javascript

    const day = ( x => {
      let date = (t => new Date(t.getFullYear(), t.getMonth(), t.getDate(), 0, 0, 0))(new Date());
      return new Date(date.setDate(date.getDate() + x));
    });
    const padDate = (x => (x.toString().length <= 1? '0'+ x : x));
    const format = (x => formatDate(new Date(x)));
    const formatDate =  (fd => padDate(fd.getUTCMonth() + 1)+'/'+padDate(fd.getUTCDate())+'/'+fd.getUTCFullYear()+' 00:00');

    const serverUrl = 'http://localhost:3000/logs';
    const ctx = document.querySelector("canvas").getContext("2d");

    const chartConfig = {
      type: 'bar',
      data: {
        labels: [],
        datasets: [{
          type: 'bar',
          label: 'Productivity',
          backgroundColor: 'rgba(255, 0, 0, .5)',
          borderColor: 'rgba(255, 0, 0, .5)',
          data: [],
        }, {
          type: 'line',
          label: 'Code Written',
          backgroundColor: 'rgba(0, 255, 0, .5)',
          borderColor: 'rgba(0, 255, 0, .5)',
          fill: false,
          data: [],
        }, ]
      },
      options: {
                title: {
                    text:"Productivity Graph"
                },
        scales: {
          xAxes: [{
            type: "time",
            display: true,
            time: {
              format: 'MM/DD/YYYY HH:mm',
              round: 'day',
              unit: 'day'
            }
          }],
        },
      }
    };

    function fetchData() {
      return fetch(serverUrl).then(function (res){
        return res.json();
      })
    }

    function dateToISO(date) {
      var msec = Date.parse(date);
      return new Date(msec).toISOString().substring(0, 10);
    }



    function updateLog(logData){
      const headers = {
        headers: {
          'Access-Control-Allow-Origin':'*',
          'Content-Type': 'application/json'
        },
        method: "PUT",
        body:  JSON.stringify(logData)
      };
      return fetch('http://localhost:3000/logs',headers).then(function(res){
        return res.json();
      });
    }

    function runSprite(){
      // NOTE https://www.gameart2d.com/the-robot---free-sprites.html
      // NOTE Melee(Good) 8, Run(Normal) 8, DEAD(Bad) 10
      let path = 'imgs/';
      let i = app.sprite.index;
      switch (app.sprite.status) {
        case 'good':
          path += 'melee/';
          i = (i >= 26 ? 1 : ++i);
          break;
        case 'avg':
          path += 'run/';
          i = (i >= 8 ? 1 : ++i);
          break;
        case 'bad':
          path += 'dead/';
          i = (i >= 10 ? 1 : ++i);
          break;  
      }
      path += i;
      app.sprite.index = i;
      document.querySelector('#sprite').src = path + ".png";
    }

    setInterval(runSprite, 100);

    var app = new Vue({
      el: '#app',
      data: {
        viewDate:  new Date().toISOString().substring(0, 10),
        sprite: {
          status: 'good',
          index: 1
        },
        logs: [],
        log:{},
        chart: chartConfig,
        line: '',
        productivityMinutesGoal: 560,
        projectsMinutesGoal: 300,
        health_bar: 100,
        visible: true
      },
      methods : {
        updateChart: function(data, build = false){
          this.logs = data;
          const productivityAverages = this.logs
                                      .map(x => x.productivity)
                                      .reduce((a, b, index, self) => {
                                         const keys = Object.keys(a)
                                         let c = {} 
                                         keys.map((key) => {
                                          c[key] = a[key] + b[key]
                                          if (index + 1 === self.length) {
                                            c[key] = c[key] / self.length
                                          }
                                         })
                                         return c
                                      });

          const projectsAverages = this.logs
                                      .map(x => x.projects.data[0].grand_total)
                                      .reduce((a, b, index, self) => {
                                         const keys = Object.keys(a)
                                         let c = {} 
                                         keys.map((key) => {
                                          c[key] = a[key] + b[key]
                                          if (index + 1 === self.length) {
                                            c[key] = c[key] / self.length
                                          }
                                         })
                                         return c
                                      });

          // above 90% equals + to health_bar;
          // below 90% equals - to health_bar; 
          // below 50% should equal death;
          this.health_bar += ((projectsAverages.hours * 60 + projectsAverages.minutes) / this.projectsMinutesGoal ) - 90;
          this.health_bar += ((productivityAverages.software_development_hours * 60) / this.productivityMinutesGoal ) - 90;
          this.health_bar = Math.round(this.health_bar);
          document.querySelector('.health_bar .life').setAttribute('style','width:'+ (100 + this.health_bar)+'%;');
          const loggedData = this.logs
                            .map(x => {return {
                              date:x.date, 
                              projectTimeMinutes:((x.projects.data[0].grand_total.hours * 60) + x.projects.data[0].grand_total.minutes - (projectsAverages.hours * 60 + projectsAverages.minutes)), 
                              productivitySoftwareMinutes: (x.productivity.software_development_hours * 60 - (productivityAverages.software_development_hours * 60))}
                            })
                            .sort((a,b) => new Date(b.date) - new Date(a.date));

          loggedData.forEach(x => {
            this.chart.data.labels.push(format(x.date));
            this.chart.data.datasets[0].data.push(x.productivitySoftwareMinutes);
            this.chart.data.datasets[1].data.push(x.projectTimeMinutes);

          });
          // Handle Build default update
          if(build){
            this.line = new Chart(ctx, this.chart);
          }else{
            this.line.update();
          }
        }  

      },
      computed: {
        dateIsValid: function (){
          return this.friend.name.length == 0 || this.friend.feature.length == 0;
        }
      },
      created: function (){
        fetchData().then(function (data){
          app.updateChart(data, true);
        });
      }
    });

Here is a codepen with a component for your reference.这是一个带有组件的代码笔供您参考。 All this does is allow Vue to have some awareness of what you are doing.所有这些都是让 Vue 对你在做什么有一些了解。 Please let me know you have any other questions.请让我知道您有任何其他问题。

https://codepen.io/anon/pen/qxgPqB https://codepen.io/anon/pen/qxgPqB

Vue.component("me", {
  template: '<canvas id="canvas" width="800px" height="800px"></canvas>',
  methods: {
    draw: function(ctx) {
      var myChart = new Chart(ctx, {
        type: "bar",
        data: {
          labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
          datasets: [
            {
              label: "# of Votes",
              data: [12, 19, 3, 5, 2, 3],
              backgroundColor: [
                "rgba(255, 99, 132, 0.2)",
                "rgba(54, 162, 235, 0.2)",
                "rgba(255, 206, 86, 0.2)",
                "rgba(75, 192, 192, 0.2)",
                "rgba(153, 102, 255, 0.2)",
                "rgba(255, 159, 64, 0.2)"
              ],
              borderColor: [
                "rgba(255,99,132,1)",
                "rgba(54, 162, 235, 1)",
                "rgba(255, 206, 86, 1)",
                "rgba(75, 192, 192, 1)",
                "rgba(153, 102, 255, 1)",
                "rgba(255, 159, 64, 1)"
              ],
              borderWidth: 1
            }
          ]
        },
        options: {
          scales: {
            yAxes: [
              {
                ticks: {
                  beginAtZero: true
                }
              }
            ]
          }
        }
      });
    }
  },
  mounted: function() {
    var c = document.getElementById("canvas");
    var ctx = c.getContext("2d");
    ctx.translate(0.5, 0.5);
    ctx.imageSmoothingEnabled = false;
    this.draw(ctx);
  }
});

var app = new Vue({
  el: "#app",
  data: {}
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM