Reputation: 33
I'm having a div (#option1
) in the shape of a dot animating a graph using an array, Option1[]
, in which all the heights of the several 'dots' are included. I'm using a for loop to create space between two dots (left: '+=5px'
) and get the height for the next dot from the array, like so:
for (var i = 0; i < Option1.length; ++i) {
$('#option1').animate({left: '+=5px',top: Option1[i]}, 200);
}
As you can see, the div takes 200ms to move to it's next coordinates. This all works fine, but it is just a moving dot. I actually want to make it look like the dot is drawing a line, so I tried to use a canvas
and lineTo
methods, like so:
var xaxis=5;
var a = document.getElementById("myCanvas1");
var atx = a.getContext("2d");
atx.beginPath();
atx.moveTo(5, 900);
for (var i = 0; i < Option1.length; ++i) {
xaxis += 5;
$('#option1').animate({left: '+=5px',top: Option1[i]}, 200);
atx.lineTo(xaxis, Option1[i]);
atx.stroke();
}
As you can see the line starts at coordinates 5,900, then moves 5px to the right and to the height of the next value of the Option1[]
array.
The line comes out correctly. The problem is that the total line shows instantaneously, and then the dot starts moving over the already drawn line. To make it so that a line-section only appears after the dot has past the new coordinates, I've tried the setTimeout
function, setting the timeout at 200ms, just like the animate time:
$(document).ready(function() {
var Option1 = [100, 150, 150, 130, 50, 100, 75, 125, 50, 100];
var xaxis = 5;
var a = document.getElementById("myCanvas1");
var atx = a.getContext("2d");
atx.beginPath();
atx.moveTo(5, 400);
atx.strokeStyle="green";
for (var i = 0; i < Option1.length; ++i) {
xaxis += 5;
$('#option1').animate({
left: '+=5px',
top: Option1[i]
}, 400);
setTimeout(drawLines(), 400);
function drawLines() {
atx.lineTo(xaxis, Option1[i]);
atx.stroke();
};
};
});
html,
body {
width: 100%;
height: 100%;
background-color: black;
}
#maindiv {
position: absolute;
top: 5px;
left: 5px;
z-index: 5;
cursor: pointer;
Width: 500px;
Height: 400px;
background-color: black;
border-radius: 1%;
border-width: 0px;
border-color: blue;
border-style: solid;
font-family: Verdana, Arial, Sans-Serif;
color: white;
box-shadow: 0 0 20px white;
}
canvas {
position: absolute;
z-index: 5;
cursor: pointer;
Width: 100%;
Height: 100%;
background-color: none;
border-radius: 1%;
border-width: 1px;
border-color: blue;
border-style: solid;
font-family: Verdana, Arial, Sans-Serif;
color: white;
box-shadow: 0 0 20px white;
}
#option1 {
position: absolute;
top: 390px;
left: 5px;
z-index: 10;
Width: 5px;
Height: 5px;
background-color: green;
border-radius: 50%;
border-width: 0px;
border-color: blue;
border-style: solid;
font-family: Verdana, Arial, Sans-Serif;
color: white;
box-shadow: 0 0 20px white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<html>
<body>
<div id="maindiv">
<canvas id="myCanvas1" width="500" height="400"></canvas>
<div id="option1"></div>
</div>
</body>
</html>
(This last hidden snippet is complete with html and css btw, so it's working). No success. The total line is there instantaneously. I've also tried to write the setTimeout
in other ways using other posts on stackoverflow, but always the total line shows instantaneously.
Any help to get my line to be drawn live, would be much appreciated! Also solutions that use entirely different methods/functions are most welcome. Thanks!
Upvotes: 3
Views: 150
Reputation: 78630
Your first issue is that you are calling your drawLines
function immediately and then passing the result of that function (undefined) to setTimeout
.
Once you fix that, you will find you have an issue of having a closure in a loop. There are a number of ways to fix that, though I have chosen to create a new function and pass the needed variables in to it and then have the timeout created inside that function.
More info on closure inside a loop
With both of those issues fixed, you end up with this:
New function:
function drawLine(atx, xaxis, y, delay){
setTimeout(function(){
atx.lineTo(xaxis, y);
atx.stroke();
}, delay);
}
Called as such in place of your existing setTimeout
:
drawLine(atx, xaxis, Option1[i], 400 * i);
You'll notice I have 400 * i
for the timeout delay instead of just 400
as you had. If 400 is used, they will all draw at once after 400ms.
Here is a working snippet:
$(document).ready(function() {
var Option1 = [100, 150, 150, 130, 50, 100, 75, 125, 50, 100];
var xaxis = 5;
var a = document.getElementById("myCanvas1");
var atx = a.getContext("2d");
atx.beginPath();
atx.moveTo(5, 400);
atx.strokeStyle="green";
for (var i = 0; i < Option1.length; ++i) {
xaxis += 5;
$('#option1').animate({
left: '+=5px',
top: Option1[i]
}, 400);
drawLine(atx, xaxis, Option1[i], 400 * i);
};
});
function drawLine(atx, xaxis, y, delay){
setTimeout(function(){
atx.lineTo(xaxis, y);
atx.stroke();
}, delay);
}
html,
body {
width: 100%;
height: 100%;
background-color: black;
}
#maindiv {
position: absolute;
top: 5px;
left: 5px;
z-index: 5;
cursor: pointer;
Width: 500px;
Height: 400px;
background-color: black;
border-radius: 1%;
border-width: 0px;
border-color: blue;
border-style: solid;
font-family: Verdana, Arial, Sans-Serif;
color: white;
box-shadow: 0 0 20px white;
}
canvas {
position: absolute;
z-index: 5;
cursor: pointer;
Width: 100%;
Height: 100%;
background-color: none;
border-radius: 1%;
border-width: 1px;
border-color: blue;
border-style: solid;
font-family: Verdana, Arial, Sans-Serif;
color: white;
box-shadow: 0 0 20px white;
}
#option1 {
position: absolute;
top: 390px;
left: 5px;
z-index: 10;
Width: 5px;
Height: 5px;
background-color: green;
border-radius: 50%;
border-width: 0px;
border-color: blue;
border-style: solid;
font-family: Verdana, Arial, Sans-Serif;
color: white;
box-shadow: 0 0 20px white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<html>
<body>
<div id="maindiv">
<canvas id="myCanvas1" width="500" height="400"></canvas>
<div id="option1"></div>
</div>
</body>
</html>
Upvotes: 1