Smooth KineticJS animation, controlled speed - javascript

I am creating a simple plane animation in KineticJS for the fun of it.
Currently the animation runs a little jerky I would love to have some easing or tweening although I don't know how to begin.
Can anyone lend me a hand with the math?
<div id="container"></div>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.5.0-beta.js"></script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 870,
height: 392
});
var layer = new Kinetic.Layer();
var xPos = 0;
var yPos = 126;
var growthFactorX = 6;
var growthFactorY = 2.6;
var growthFactorP = 3;
var planeRotation = 30;
// dashed line
var trail = new Kinetic.Line({
points: [{x: xPos,y: yPos}],
stroke: 'white',
strokeWidth: 2,
lineJoin: 'round',
dashArray: [6, 5]
});
var imageObj = new Image();
imageObj.src = '/assets/img/plane.png';
var plane = new Kinetic.Image({
x: xPos,
y: yPos - 15,
width: 54,
height: 30
});
imageObj.onload = function() {
plane.setImage(imageObj);
layer.add(plane);
stage.add(layer);
};
plane.rotateDeg( planeRotation );
layer.add(trail);
stage.add(layer);
var anim = new Kinetic.Animation(function(frame) {
if( xPos < 500 ) {
xPos = growthFactorX + xPos; // adds 3 to xPos on each loop
if( xPos > 400 ) {
yPos = yPos - growthFactorY;
if( plane.getRotationDeg() > 0 )
plane.rotateDeg( (-growthFactorP) ) ;
}
var curPoints = trail.getPoints();
var newPoints = [{x: xPos, y: yPos}];
trail.setPoints(curPoints.concat(newPoints));
plane.setX(xPos + 10);
plane.setY(yPos - 35);
}
else {
anim.stop();
}
}, layer);
anim.start();
</script>

I have created a fiddle for you,
and have changed this factors, al thought it looks smooth to me, please let me know if any specification
var xPos = 0;
var yPos = 126;
var growthFactorX = 5;
var growthFactorY = 2;
var growthFactorP = 1;
var planeRotation = 30;
The fiddle link
I hope this will do :)

Related

drawing lines on circle segments in paperjs

I'm trying to make the line point to the center of the circle -or the circular shape- and in the code below they obviously do not. They are initialized in the proper position but they end at the wrong spot. Should be fairly easy but I couldn't crack it. How do I achieve this?
var path = new Path.RegularPolygon({
center: [100, 100],
radius: 50,
sides: 10
});
path.style = {
fillColor: 'red',
strokeColor: null
}
path.selected = true;
for(var i = 0; i < path.segments.length; i++){
spike = new Path();
spike.add(new Point(path.segments[i].point.x, path.segments[i].point.y));
spike.add(new Point(path.segments[i].point.x + 10, path.segments[i].point.y + 10));
spike.strokeColor = 'black';
spike.strokeWidth = 2.5;
}
this is what comes out of it:
Don't know any paper.js, but as far as math goes, here's an attempt:
var ctr = {x: 100.0, y: 100.0};
var rad = 50.0;
var spikeLen = 10;
for(var i = 0; i < path.segments.length; i++){
spike = new Path();
var p = {
x: path.segments[i].point.x,
y: path.segments[i].point.y
};
spike.add(new Point(p.x, p.y));
spike.add(new Point(p.x - spikeLen*(ctr.x-p.x)/rad, p.y - spikeLen*(ctr.y-p.y)/rad);
spike.strokeColor = 'black';
spike.strokeWidth = 2.5;
}
Set another path say path1 of the same shape with radius of 40 (50 - 10 = 40. Since you want the spike of 10) The draw the spike from path to path1 for each of the points
The final code is as follows
var path = new Path.RegularPolygon({
center: [100, 100],
radius: 50,
sides: 10
});
path.style = {
fillColor: 'red',
strokeColor: null
}
path.selected = true;
/* Add path1 */
var path1 = new Path.RegularPolygon({
center: [100, 100],
radius: 40, // 50 -10 =40
sides: 10
});
path1.style = {
strokeColor: 'red'
}
for(var i = 0; i < path.segments.length; i++){
spike = new Path();
spike.add(new Point(path.segments[i].point.x, path.segments[i].point.y));
/* end point is on path1 */
spike.add(new Point(path1.segments[i].point.x , path1.segments[i].point.y));
spike.strokeColor = 'black';
spike.strokeWidth = 2.5;
}

How to make the background color of a page change at a certain time of the day in Javascript?

Ok, guys I'm back with another question. . .
So, this time I've created a cool html webpage that contains snowflakes falling in the background that I created with Javascript.
What I am wanting to is have the background color of the page change at certain times of the day.
For example: from 4am - 11pm, it'd be a lightblue color, from 11pm-6pm it'd be a little darker blue, from 6pm-9pm, it'd be a really dark blue, and finally from 9pm-4am, it'd be black.
Here is the code, if it helps any:
window.onload = function(){
//create canvas
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//set canvas fullscreen
var W = window.innerWidth;
var H = window.innerHeight;
canvas.height = H;
canvas.width = W;
//generate snowflakes and atts
var mf = 100; //max flakes
var flakes = [];
//loop through empty flakes and apply atts
for(var i = 0; i < mf; i++){
flakes.push({
x: Math.random()*W, //set width of flake to random nr between 0 and 1 * width of screen
y: Math.random()*H, //set height of flake to random nr between 0 and 1 * height of screen
r: Math.random()*5+2, //set radius between 2 and 5
d: Math.random() + 1
})
}
//draw flakes
function drawFlakes(){
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = "White";
ctx.beginPath();
for(var i = 0; i < mf; i++){
var f = flakes[i];
ctx.moveTo(f.x, f.y);
ctx.arc(f.x, f.y, f.r, 0, Math.PI*2, true);
}
ctx.fill();
moveFlakes();
}
var angle = 0;
//move flakes
function moveFlakes(){
angle += 0.01;
for(var i = 0; i < mf; i++){
var f = flakes[i];
f.y += Math.pow(f.d, 2) + 1;
f.x += Math.cos(angle)*2;
if(f.y > H){
flakes[i] = {x: Math.random()*W, y: 0, r: f.r, d: f.d};
}
}
}
setInterval(drawFlakes, 25);
}
body {
background-color: lightSeaGreen;
z-index: -9999;
}
<!DOCTYPE html>
<html>
<head>
<script src="JsSnow.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body id="myBody">
<canvas id="myCanvas"></canvas>
</body>
</html>
I've tried many things using the getHours(), but none have worked!!!
I have changed your function to get the current Hours in the day (0-24) and set the background accordingly. Hopefully this helps you find your answer.
window.onload = function(){
var hour = (new Date()).getHours(); // get the current hours (0-24)
var bg = document.getElementById('myBody'); // grab the bg obj
if (hour > 10){ // if its past 10am
bg.style.backgroundColor = 'red'; // set the bg color
} else if (hour > 14){ // if its past 2pm
bg.style.backgroundColor = 'blue';
}
//create canvas
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
//set canvas fullscreen
var W = window.innerWidth;
var H = window.innerHeight;
canvas.height = H;
canvas.width = W;
//generate snowflakes and atts
var mf = 100; //max flakes
var flakes = [];
//loop through empty flakes and apply atts
for(var i = 0; i < mf; i++){
flakes.push({
x: Math.random()*W, //set width of flake to random nr between 0 and 1 * width of screen
y: Math.random()*H, //set height of flake to random nr between 0 and 1 * height of screen
r: Math.random()*5+2, //set radius between 2 and 5
d: Math.random() + 1
})
}
//draw flakes
function drawFlakes(){
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = "White";
ctx.beginPath();
for(var i = 0; i < mf; i++){
var f = flakes[i];
ctx.moveTo(f.x, f.y);
ctx.arc(f.x, f.y, f.r, 0, Math.PI*2, true);
}
ctx.fill();
moveFlakes();
}
var angle = 0;
//move flakes
function moveFlakes(){
angle += 0.01;
for(var i = 0; i < mf; i++){
var f = flakes[i];
f.y += Math.pow(f.d, 2) + 1;
f.x += Math.cos(angle)*2;
if(f.y > H){
flakes[i] = {x: Math.random()*W, y: 0, r: f.r, d: f.d};
}
}
}
setInterval(drawFlakes, 25);
}
body {
background-color: lightSeaGreen;
z-index: -9999;
}
<!DOCTYPE html>
<html>
<head>
<script src="JsSnow.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body id="myBody">
<canvas id="myCanvas"></canvas>
</body>
</html>
something like this should work:
var time = new Date().getHours()
var opt = [
'green', 'green', 'green', 'green', 'green', 'green', 'green', 'green', 'green', 'green', 'green', 'green', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red', 'red'
]
document.querySelector('body').style.background = opt[time-1]
Adding this block to javascript should do the work.Gets the hour of the day and assigns background color accordingly.
var date = new Date();
var hours= date.getHours();
if(hours > 4 && hours < 11){
document.body.style.backgroundColor = "#7EC0EE";
}else if (hours > 11 && hours < 17){
document.body.style.backgroundColor = "#7e9cee";
}else if(hours > 17 && hours < 21){
document.body.style.backgroundColor = "#0d41d0";
}else{
document.body.style.backgroundColor = "#030815";
}
Just have a separate function that runs every minute and change background color as needed
setInterval(()=>{
//get color from time of day
document.querySelector('body').style.background = color;
}, 60000);

Mouse Wheel Zooming

so i'm working on a canvas that you can only drag a image from side to side and use the mouse wheel to re size the image by zooming in and out on it here is the code i have so far please feel free to ask any more details. I'm trying to find a way that's compact to do this and require minimum code.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
<script src="kinetic-v5.1.0.min.js" type="text/javascript"></script>
</head>
<body>
<div id="container"></div>
<script type="text/javascript">
function drawImage(imageObj) {
var stage = new Kinetic.Stage({
container: "container",
width: 1800,
height: 800
});
var layer = new Kinetic.Layer();
// image
var image1 = new Kinetic.Image({
image: imageObj,
x: stage.getWidth() / 2 - 896 / 1,
y: stage.getHeight() / 2 - 255 / 2,
width: 200,
height: 157,
draggable: true,
dragBoundFunc: function (pos) {
if (pos.x < this.minX) { }
this.minX = pos.x;
return {
x: pos.x,
y: this.getAbsolutePosition().y
}
}
});
// add cursor styling
image1.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
image1.on('mouseout', function() {
document.body.style.cursor = 'default';
});
layer.add(image1);
stage.add(layer);
}
var imageObj = new Image();
imageObj.onload = function() {
drawImage(this);
};
imageObj.src = 'image1.png';
</script>
</body>
</html>
One way would be to use a zoom helper. For example:
var zoomHelper = {
stage: null,
scale: 1,
zoomFactor: 1.1,
origin: {
x: 0,
y: 0
},
zoom: function(event) {
event.preventDefault();
var delta;
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
if (event.originalEvent.detail > 0) {
//scroll down
delta = 0.2;
} else {
//scroll up
delta = 0;
}
} else {
if (event.originalEvent.wheelDelta < 0) {
//scroll down
delta = 0.2;
} else {
//scroll up
delta = 0;
}
}
var evt = event.originalEvent,
mx = evt.clientX - zoomHelper.stage.getX(),
my = evt.clientY - zoomHelper.stage.getY(),
zoom = (zoomHelper.zoomFactor - delta),
newscale = zoomHelper.scale * zoom;
zoomHelper.origin.x = mx / zoomHelper.scale + zoomHelper.origin
.x - mx / newscale;
zoomHelper.origin.y = my / zoomHelper.scale + zoomHelper.origin
.y - my / newscale;
zoomHelper.stage.setOffset({
x: zoomHelper.origin.x,
y: zoomHelper.origin.y
});
zoomHelper.stage.setScale({
x: newscale,
y: newscale
});
zoomHelper.stage.draw();
zoomHelper.scale *= zoom;
}
};
Here is a demo with code you provided in as an example slightly changed.
Try using this full javascript library.

how to resize rectangle in kinetic js,canvas 5

Rect is draggable,resizable even u can add or set text on it.But in fiddle textarea to take input from user is not appearing but on my workspace its working fine but if u see in fiddle problem is still there because of "simpleText" if you uncomment it, box will resize every time as per expectations but because of simpleText it resizes only 1st time and after that breaks logic.
here is my fiddle http://jsfiddle.net/abhish20/Y2m2z/56/
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 500,
x: 10,
y:18
});
var layer = new Kinetic.Layer();
stage.add(layer);
var group = new Kinetic.Group({
draggable : true,
});
var relativeX=0;
var relativeY=0;
var box = new Kinetic.Rect({
x : relativeX,
y : relativeY,
offset : [ 50, 25 ],
width : 100,
height : 50,
fill : 'yellow',
stroke : 'black',
strokeWidth : 1,
name:"comment"
});
group.add(box);
layer.add(group);
layer.draw();
var simpleText = new Kinetic.Text({
x : relativeX,
y : relativeY,
text : '',
fontSize : 15,
fontFamily : 'Calibri',
width:box.getWidth(),
height:box.getHeight(),
padding: 4,
fill : 'black',
id:"textBox"
});
group.add(simpleText);
layer.draw();
var circle1 = new Kinetic.Circle({
x: relativeX+50,
y:relativeY+25,
x : 50,
y : 25,
radius: 4,
fill: 'red',
stroke: 'black',
strokeWidth: 1,
draggable: true,
visible:false
});
group.add(circle1);
layer.draw();
circle1.on("dragmove", function () {
var pos = this.getPosition();
var x = pos.x;
var y = pos.y;
var rectX = box.getX();
var rectY = box.getY();
var x1= x - rectX;
var y1= y - rectY;
box.setSize(x1+50,y1+25);
layer.draw();
var textX=simpleText.getX();
var textY=simpleText.getY();
var x2= x - textX;
var y2= y - textY;
simpleText.setSize(x2,y2);
var circle1X=circle1.getX();
var circle1Y=circle1.getY();
var x3=x-circle1X;
var y3=y-circle1Y;
circle1.setSize(x3,y3);
layer.draw();
});
box.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
box.on('mouseout', function() {
document.body.style.cursor = 'default';
});
circle1.on('mouseover', function() {
document.body.style.cursor = 'se-resize';
});
circle1.on('mouseout', function() {
document.body.style.cursor = 'default';
});
group.on('click', function(evt) {
var shape =circle1.getVisible();
if( shape==false)
{
circle1.show();
layer.draw();
$('html').on('keydown',function(e){
if(e.keyCode === 46){
group.destroy();
layer.draw();
}
});
}else{
circle1.hide();
layer.draw();
}
circle1.setVisible(false);
});
group.on('dblclick', function() {
if (hasInput)
return;
addInput();
});
var canvas = document.getElementById('canDemo');
ctx = canvas.getContext('2d'),
font = '14px sans-serif',
hasInput = false;
function addInput() {
var input = document.createElement('textarea');
var x=box.getX();
var y=box.getY();
input.id="comment_area";
input.type = 'textarea';
input.style.position = "absolute";
input.style.left = x+220+ 'px';
input.style.top = y+171+ 'px';
input.style.height=300;
input.style.zIndex="3";
input.onblur= handleEnter;
document.body.appendChild(input);
input.focus();
if(simpleText.getText().length!=0)
{
$("#comment_area").val(simpleText.getText());
}
hasInput = true;
}
function handleEnter(e) {
var keyCode = e.keyCode;
simpleText.setText( $("#comment_area").val());
drawText(this.value, parseInt(this.style.left, 10), parseInt(this.style.top, 10));
document.body.removeChild(this);
hasInput = false;
}
function drawText(txt, x, y) {
ctx.textBaseline = 'top';
ctx.textAlign = 'left';
ctx.font = font;
ctx.fillText(txt, x - 4, y - 4);
layer.draw();
}
$('#comment_area').keypress(function (e){
if(e.keyCode === 13){
e.preventDefault();
this.value = this.value.substring(0, this.selectionStart)+"\n";
}
});
my concern is i am grouping all elements together to behave like single component so it causing a problem but i want working code in group form only.
please suggest
here is my fiddle http://jsfiddle.net/abhish20/Y2m2z/56/
There is a problem with your code.
circle1.setSize(x3, y3);
if x3 or y3 are === 0, then the circle vanishes.
Comment out that line, then the code works.
You can test your code to find issues like this by inserting... console.log(x3,y3) or whatever...

Kinetic.js: Rotating image on touch

I have this fiddle:
http://jsfiddle.net/WDjpx/2/
The image is not rotating correctly.
The code that i used was:
var stage = new Kinetic.Stage({
container: 'd',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
var isDragging = false;
var refRotation = null;
var rect = new Kinetic.Rect({
x: 150,
y: 150,
width: 100,
height: 100,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
offset: [50, 50],
dragOnTop: true,
draggable: true,
dragBoundFunc: function (pos) {
var xd = 150 - pos.x ;
var yd = 150 - pos.y ;
var theta = Math.atan2(yd, xd);
var deg = theta * 180 / Math.PI;
if (!isDragging) {
isDragging = true;
refRotation = deg;
} else {
var rotate = deg - refRotation;
rect.setRotationDeg(deg);
}
return {
x: this.getAbsolutePosition().x,
y: this.getAbsolutePosition().y
}
}
});
layer.add(rect);
stage.add(layer);
Anyone know what is wrong with my Math???
--- EDIT ---
New feddle with what i wanted:
http://jsfiddle.net/zk9cn/
Don't know about Math.atan2, but it seems calculation of x and y is not right to me. I would deduct position from center, not center from position. http://jsfiddle.net/bighostkim/qZDcg/
var x = 150 - pos.x;
var y = 150 - pos.y;
var radian = Math.PI + Math.atan(y/x);
this.setRotation(radian);
Other thing, I also see your variables are not in use; isDragging, refRotate, and rotate.
----- Edit ----
If you want to rotate rectangle by picking up the corner, you can use the following code.
When you pick up the corner, degree calculated by center positon is already 45. That's why you cannot pick up the corner properly. By adjusting 45 makes it seem right, but when you pick up the straight line, it will go wrong again. It seems your requirement has a flaw in it unless it's intentional. http://jsfiddle.net/bighostkim/7Q5Hd/
var pos = stage.getMousePosition();
var xd = 150 - pos.x ;
var yd = 150 - pos.y ;
var theta = Math.atan2(yd, xd);
var degree = theta / (Math.PI / 180) - 45;
this.setRotationDeg(degree);

Categories