I have the following code leveraging the ChartJS library.
/*assume the tags in the right place */
<canvas id="graph1" width="300" height="300"></canvas>
var ctx = $("#graph1").get(0).getContext("2d");
var myChart = new Chart(ctx).Line(graph1Generator("day"));
... everything works fine, but after adding the following event handler to clear and repaint the same chart with different data, a glitch occurs.
weekButton.addEventListener("click", function(){
ctx.clearRect (0, 0, 300, 300);
ctx.canvas.width = 300;
ctx.canvas.height = 300;
myChart = new Chart(ctx).Line(graph1Generator("week"));
This code does successfully redraw the chart with the new data, but when I hover over it, it does some very strange "flashbacks" to the old chart that it was supposed to clear. This makes me believe that it didn't clear the old one.
Here is an update to your fiddle. The primary change (other than fixing the function name typo) is to add
myChart.destroy();
before lines like
myChart = new Chart(ctx).Line(...);
The .destroy() method gets rid of the event handler registrations etc, so you shouldn't see those weird "ghost charts" when you mouse over the graphics.
Related
I have seen several solutions on this issue but have not found one yet that works for my situation.
I have a chart being made with chart.js which uses canvas to display. I have a function that is supposed to clear the canvas so that I can then redraw the chart with different x variables. The function works initially but as soon as I start to hover on my cleared canvas the old contents reappear. More specifically it seems to reappear if I am hovering over on of the previous data points.
Here is the function:
function empty(){
canvas = document.getElementById("loansChart");
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
}
EDIT
If a canvas contained items that had hover initiated function items, do those items still exist (just invisible) in the canvas?
You should use the chart.js functions for updating and clearing charts rather than the ones for the html canvas.
The docs are quite straightforward. https://www.chartjs.org/docs/latest/developers/updates.html
So I am building an AngularJs chart that utilizes an Angular Library to create the chart on a Canvas tag. However when I drag and drop a new data set onto the canvas to redraw it continues to hold the old data. What I am trying to accomplish is If (there is new data){ clear the canvas}. I know I have to use:
canvasReset.clearRect(0, 0, canvas.width, canvas.height);
somewhere but what I am really looking for is an event handler to use to assist me in determining if anything is on the canvas, and if so clearing it. However, I am not looking for mouseover mouse-click,etc. But something that is just generally looking to see if the canvas is being utilized.
The short answer, you can't. But you can catch mouseevnets, or you can wrap canvas ctx drawing functions,like
var fill = ctx.fill;
ctx.fill = function(){
fill.apply(this, arguments);
setDirty();
};
I was working on a couple of Chart.js charts and have found some strange behavior.
In this fiddle: http://jsfiddle.net/h42tv3xv/ people have been getting a variety of side effects when pressing the buttons "Day", "Week", or "Month".
What it should do:
Simply refresh the chart with potentially new information displayed(the pie and doughnut actually don't have anything new)
What it should not do:
As a side effect for some, it is growing the size of the <canvas> on each click. It does it for me. But it doesn't do it for a lot of other people accessing this fiddle. Here is a screen shot:
Why is it doing this for some people and not others? How can I remedy this problem? If you are curious, I initially asked a question about something else about these charts, but this could be somewhat related.
Any clue what could be causing this in my browser and other browsers/computers?
Edit, I realize the fiddle is large, so this is what I am doing essentially:
// Assign and Create all canvas contexts
var ctx = $("#graph1").get(0).getContext("2d");
var ctx2 = $("#graph2").get(0).getContext("2d");
var ctx3 = $("#graph3").get(0).getContext("2d");
// Instantiate new charts and pass in generated data
var myChart = new Chart(ctx).Line(graph1Generator("day"));
var myDoughnutChart = new Chart(ctx2).Doughnut(graph2Generator("day"));
var myPieChart = new Chart(ctx3).Pie(graph3Generator("day"));
then I am adding (for each button) an event listener that destroys each canvas, and creates a new one with new information. Here is an example of the "week" button:
weekButton.addEventListener("click", function(){
myChart.destroy();
myChart = new Chart(ctx).Line(graph2Generator("Week"));
myDoughnutChart.destroy();
myDoughnutChart = new Chart(ctx2).Doughnut(graph2Generator("week"));
myPieChart.destroy();
myPieChart = new Chart(ctx3).Pie(graph3Generator("week"));
});
Wrap the element inside a wrapper and set its max-width to be 80% or as desired.
Turn off responsiveness.
Check out this fiddle and let me know whether you are still getting bloated chart on clicking re-renders.
<div class="wrapper">
<canvas id="graph1" width="300" height="300"></canvas>
<canvas id="graph2" width="250" height="250"></canvas>
<canvas id="graph3" width="250" height="250"></canvas>
</div>
.wrapper {
max-width: 80%;
}
I had the same behaviour defining padding definition to my canvas. I removed padding and I have no resizing now.
I'm new to this - I just can't figure out why this isn't working. When I remove Display:none from HTML, the image works correctly so I know the path to the image is correct. But it's not drawing on the canvas. Thanks for your time.
HTML:
<canvas width="840" height="900" id="Canvas6">
Your browser does not support this feature.
</canvas>
<img src="image/logo.png" id="img1" width="825" height="272" style="display:none;">
<script type="text/javascript" src="js/main.js"></script>
Main.JS JAVASCRIPT:
var theCanvas = document.getElementById('Canvas6');
if (theCanvas && theCanvas.getContext) {
var ctx = theCanvas.getContext("2d");
if (ctx) {
//Create a variable to hold our image
var srcImg = document.getElementById("img1");
//Draw an image directly onto the canvas
ctx.drawImage(srcImg, 0,0);
//Draw a scaled down image
//drawImage(srcImg, dx, dy, dw, dh)
}
}
In html file, the first best thing you have done is used the 'script' tag right at the end of the html file.
This ensures that the "Critical Render Time" is minimized, and the display items in HTML are shown first. (Not a huge impact on this case, because here you are using the JS to draw/display, but this approach is really good when you use your js for other purposes like calculations etc., and you don't want to stop the other HTML items from displaying because of an ongoing calculation.)
Now that the canvas is ready, its time to throw the image on the canvas.
Try using the border property (style="border: 2px dotted black") to see the container area of the canvas.
Hmmm !! But the image doesn't show in canvas. WHY ??
Images(or any other files) take atleast some time to get processed. By the time they are getting processed to be loaded on the screen, your canvas is already getting displayed. Hence you see an empty canvas.
So, the solution is to make everything else wait, till the time image gets loaded.
How do we do that ? Just use the "Event Listener".
EventListener is the property of Window object. (window.addEventListener("load", some_func_to_run , false);). We generally use this, when we want our window/page/browser to wait for something, but hey , we can use it for our images as well.
var cvs = document.getElementById("canvas"); // Getting the control of the canvas
var ctx = cvs.getContext("2d"); //Getting the control of the useful HTML object getContext . This object brings in a lot of useful methods like drawImage, fillRect etc.
//create images
var bg = new Image(); // Creating image objects
bg.src = "images/bg.png"; //Setting the source file
//create images ends
//load images first
bg.addEventListener("load" , draw , false); //**IMPORTANT : Just remove this line and you will start facing this problem of empty canvas again
//loading images ends
function draw() {
ctx.drawImage(bg,0,0); // Putting the image and its coordinates on the canvas
}
draw(); // Calling the draw function to put the image on canvas
<html>
<body>
<canvas id="canvas" width="288" height="512" style="border: 2px dotted black"> </canvas>
<script src="flappyBird.js"></script>
</body>
</html>
So, it all about using Event Listener and asking everything to wait till the image gets loaded.
Hope this help. :)
If you try to place an image on a Canvas before it has loaded, it will not show. It is not like the img tag that will show the image whenever it loads. I surrounded your JS with an onload and it worked for me.
document.getElementById("img1").onload = function() { /* Your JS */ };
You have to wait for the image to load before you can draw it on the canvas, so set your drawing code to run on the window load event (by which time all images are loaded). Also, you don't need to include the markup for the image on the page, where you have to then prevent it from displaying with CSS. You can just create the image object and set the source attribute in the javascript. For example:
var img = document.createElement('img');
img.src = 'image/logo.png';
window.addEventListener('load', function(){
var theCanvas = document.getElementById('Canvas6');
if (theCanvas && theCanvas.getContext) {
var ctx = theCanvas.getContext("2d");
if (ctx) {
ctx.drawImage(img, 0,0);
}
}
});
11I'm using sketch.js from here: http://intridea.github.io/sketch.js/ and jquery 2.0.0
On my page, I have a list of images presented like so:
<img src="http://url.to/image"><br><span class="background">click for background</span>
and a canvas, set up like so:
<canvas id="simple_sketch" style="border: 2px solid black;"></canvas>
relevant JavaScript:
var winwidth = 800;
var winheight = 600;
$('#simple_sketch').attr('width', winwidth).attr('height', winheight);
$('#simple_sketch').sketch();
$('.background').on('click', function(event) {
event.preventDefault();
var imgurl = $(this).parent().attr('href');
console.log('imgurl: ' + imgurl);
var n = imgurl.split('/');
var size = n.length;
var file = '../webkort/' + n[size - 1];
var sigCanvas = document.getElementById('simple_sketch');
var context = sigCanvas.getContext('2d');
var imageObj = new Image();
imageObj.src = imgurl;
imageObj.onload = function() {
context.drawImage(this, 0, 0,sigCanvas.width,sigCanvas.height);
};
alert('background changed');
});
Backgrounds are changed just as I want them to, but whenever I click on the canvas, the backgound image is cleared. As per a suggestion on this thread: html5 canvas background image disappear on mousemove I commented out this.el.width = this.canvas.width(); on line 116 of sketch.js, but to no avail.
Any help appreciated!
EDIT: jsfiddle: http://jsfiddle.net/RXFX4/1/
EDIT: Couldn't figure out how to do this with sketch.js, so instead went with jqScribble (link posted in comments) which has the ability to do this as a built-in function instead.
Find this line on the library - sketch.js and delete/comment it out.
this.el.width = this.canvas.width();
Good luck
Assign the url on the image source after the onload event. If the image is already loaded, the event is probably firing before you are hooking it. Which means that your drawImage is never being called.
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(this, 0, 0,sigCanvas.width,sigCanvas.height);
};
imageObj.src = imgurl;
EDIT: I'm going to take a shot in the dark here, since I'm not familiar with sketchjs
I'm thinking that your problem is that you are completely re-render the canvas when you click your 'change background' link. Notice that if you draw, then click the change background, you lose your drawing.
However, notice that once you click again, the background disappears, and you get your original drawing back again. This tells me that sketchjs is keeping track of what has been drawn on it's own in-memory canvas, and then it drops it onto the target. The problem, then, is that when this in-memory canvas is drawn, it completely replaces the contents of the target canvas with it's own.
I notice in some of the sketchjs examples, if you want a background they actually assign the canvas a background style. In your example, you are drawing the background directly onto the canvas. The prior probably works because sketchjs knows to incorporate the background style when it draws. However, it does not know that when you drew your fresh background image, it should be using that.
Can you just change the background style on the canvas element, instead of drawing directly on the canvas?