我正在制作一个小小的生产力应用程序/游戏,让我在浪费时总是感觉更好。我正在使用vue和chartjs,而且看起来彼此并不好玩。
当我在<canvas>
中包含我的<div id="app">
元素时,在chartjs上启动的一个vue无法呈现任何内容。没有任何错误或任何错误。但是,当我将<canvas>
移到<div id="app">
之外时,它的效果非常好。没有人对此有任何见解吗?
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
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);
});
}
});
答案 0 :(得分:1)
这是一个包含组件的codepen供您参考。所有这一切都让Vue能够意识到你在做什么。请告诉我您还有其他任何问题。
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: {}
});