How to hyperlink an image in JavaScript - javascript

I would like to set hyperlink on an image with this JSON: {url: 'img/enf.png', x: 1200, y: 530, offset: -0.1} in a parallax effect, so if you click on this image, you go to "news.html".
Code I currently have:
<html>
<head>
<style>
body{
margin:0;
overflow-x: hidden;
}
#pozadi{
background-image: url(img/pozadi.png);
overflow: hidden;
background-size: cover;
background-position: top;
background-repeat: no-repeat;
position: relative;
min-height: 500px;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<div id="pozadi">
<div id="container"></div>
</div>
<script src="tweenmax.js"></script>
<script src="snapsvg.js"></script>
<script>
if (screen.width > 1200){
var assets = [
{url: 'img/vybuch.png', x: 0, y: 60, offset: -0.25},
{url: 'img/psi.png', x: 200, y: 80, offset: -0.2},
{url: 'img/kour.png', x: 120, y: 280, offset: -0.15},
{url: 'img/enf.png', x: 1200, y: 530, offset: -0.1},
{url: 'img/csf.png', x: -40, y: 530, offset: -0.1},
{url: 'img/nadpis.png', x: 350, y: 530, offset: 0.01},
{url: 'img/sbt.png', x: 610, y: 665, offset: 0.01},
],
layers = [],
w = screen.width,
h = screen.height,
loaded = 0,
container = document.getElementById('container'),
s = new Snap(w, h);
container.appendChild(s.node);
g = s.g();
c = s.g();
c.attr({transform: 'scale(1)'});
g.append(c);
for (var i = 0; i < assets.length; i++) {
var img = new Image();
img.src = assets[i].url;
img.onload = handle_load;
/*Start my code*/
if (i==3) { //3 is your 'img/enf.png', or check the string in img.src
img.onclick = function(e){
window.location.href = 'www.debil.cz';
}
}
/*End my code*/
var _img = s.image(assets[i].url, assets[i].x, assets[i].y);
c.append(_img);
layers.push(_img);
}
function handle_load(e) {
loaded += 1;
if (loaded == assets.length) {
handle_loaded();
}
}
function handle_loaded() {
container.addEventListener('mousemove', handle_mousemove);
container.addEventListener('mouseout', handle_mouseout);
container.addEventListener('mouseover', handle_mouseover);
}
function handle_mousemove(e) {
var dx = e.offsetX - (w / 2);
var dy = e.offsetY - (h / 2);
for (var i = 0; i < layers.length; i += 1) {
var l = layers[i];
var _x = dx * assets[i].offset;
var _y = dy * assets[i].offset;
TweenMax.to(l.node, 0.1, {x: _x, y: _y});
}
}
function handle_mouseout(e) {
for (var i = 0; i < layers.length; i += 1) {
var l = layers[i];
TweenMax.to(l.node, 0.2, {x: 0, y: 0, ease: Quad.easeOut});
}
TweenMax.to(s.node, 0.2, {scale: 0.9, rotationY: 0, rotationX: 0, ease: Quad.easeOut});
TweenMax.to(c.node, 1, {rotationY: 0, rotationX: 0});
}
function handle_mouseover(e) {
TweenMax.to(s.node, 0.2, {scale: 1, ease: Back.easeOut});
}
function angleToPoints(angle) {
var segment = Math.floor(angle / Math.PI * 2) + 2;
var diagonal = (1/2 * segment + 1/4) * Math.PI;
var op = Math.cos(Math.abs(diagonal - angle)) * Math.sqrt(2);
var x = op * Math.cos(angle);
var y = op * Math.sin(angle);
return {
x1: x < 0 ? 1 : 0,
y1: y < 0 ? 1 : 0,
x2: x >= 0 ? x : x + 1,
y2: y >= 0 ? y : y + 1
};
}
}else if (screen.width > 600){
var assets = [
{url: 'img/vybuch_tablet.png', x: -450, y: 80, offset: -0.25},
{url: 'img/psi_tablet.png', x: -280, y: 140, offset: -0.2},
{url: 'img/kour_tablet.png', x: -220, y: 350, offset: -0.15},
{url: 'img/enf_tablet.png', x: 470, y: 830, offset: -0.1},
{url: 'img/csf_tablet.png', x: 85, y: 830, offset: -0.1},
{url: 'img/nadpis_tablet.png', x: 5, y: 610, offset: 0.01},
{url: 'img/sbt_tablet.png', x: 150, y: 740, offset: 0.01},
],
layers = [],
w = screen.width,
h = screen.height,
loaded = 0,
container = document.getElementById('container'),
s = new Snap(w, h);
container.appendChild(s.node);
g = s.g();
c = s.g();
c.attr({transform: 'scale(1)'});
g.append(c);
for (var i = 0; i < assets.length; i++) {
var img = new Image();
img.src = assets[i].url;
img.onload = handle_load;
var _img = s.image(assets[i].url, assets[i].x, assets[i].y);
c.append(_img);
layers.push(_img);
}
function handle_load(e) {
loaded += 1;
if (loaded == assets.length) {
handle_loaded();
}
}
function handle_loaded() {
container.addEventListener('mousemove', handle_mousemove);
container.addEventListener('mouseout', handle_mouseout);
container.addEventListener('mouseover', handle_mouseover);
}
function handle_mousemove(e) {
var dx = e.offsetX - (w / 2);
var dy = e.offsetY - (h / 2);
for (var i = 0; i < layers.length; i += 1) {
var l = layers[i];
var _x = dx * assets[i].offset;
var _y = dy * assets[i].offset;
TweenMax.to(l.node, 0.1, {x: _x, y: _y});
}
}
function handle_mouseout(e) {
for (var i = 0; i < layers.length; i += 1) {
var l = layers[i];
TweenMax.to(l.node, 0.2, {x: 0, y: 0, ease: Quad.easeOut});
}
TweenMax.to(s.node, 0.2, {scale: 0.9, rotationY: 0, rotationX: 0, ease: Quad.easeOut});
TweenMax.to(c.node, 1, {rotationY: 0, rotationX: 0});
}
function handle_mouseover(e) {
TweenMax.to(s.node, 0.2, {scale: 1, ease: Back.easeOut});
}
function angleToPoints(angle) {
var segment = Math.floor(angle / Math.PI * 2) + 2;
var diagonal = (1/2 * segment + 1/4) * Math.PI;
var op = Math.cos(Math.abs(diagonal - angle)) * Math.sqrt(2);
var x = op * Math.cos(angle);
var y = op * Math.sin(angle);
return {
x1: x < 0 ? 1 : 0,
y1: y < 0 ? 1 : 0,
x2: x >= 0 ? x : x + 1,
y2: y >= 0 ? y : y + 1
};
}
}else{
var assets = [
{url: 'img/vybuch_phone.png', x: 0, y: 0, offset: -0.25},
{url: 'img/psi_phone.png', x: -400, y: 0, offset: -0.2},
{url: 'img/kour_phone.png', x: -300, y: 100, offset: -0.15},
{url: 'img/enf_phone.png', x: 200, y: 540, offset: -0.1},
{url: 'img/csf_phone.png', x: 20, y: 540, offset: -0.1},
{url: 'img/nadpis_phone.png', x: 30, y: 430, offset: 0.01},
{url: 'img/sbt_phone.png', x: 65, y: 495, offset: 0.01},
],
layers = [],
w = screen.width,
h = screen.height,
loaded = 0,
container = document.getElementById('container'),
s = new Snap(w, h);
container.appendChild(s.node);
g = s.g();
c = s.g();
c.attr({transform: 'scale(1)'});
g.append(c);
for (var i = 0; i < assets.length; i++) {
var img = new Image();
img.src = assets[i].url;
img.onload = handle_load;
var _img = s.image(assets[i].url, assets[i].x, assets[i].y);
c.append(_img);
layers.push(_img);
}
function handle_load(e) {
loaded += 1;
if (loaded == assets.length) {
handle_loaded();
}
}
function handle_loaded() {
container.addEventListener('mousemove', handle_mousemove);
container.addEventListener('mouseout', handle_mouseout);
container.addEventListener('mouseover', handle_mouseover);
}
function handle_mousemove(e) {
var dx = e.offsetX - (w / 2);
var dy = e.offsetY - (h / 2);
for (var i = 0; i < layers.length; i += 1) {
var l = layers[i];
var _x = dx * assets[i].offset;
var _y = dy * assets[i].offset;
TweenMax.to(l.node, 0.1, {x: _x, y: _y});
}
}
function handle_mouseout(e) {
for (var i = 0; i < layers.length; i += 1) {
var l = layers[i];
TweenMax.to(l.node, 0.2, {x: 0, y: 0, ease: Quad.easeOut});
}
TweenMax.to(s.node, 0.2, {scale: 0.9, rotationY: 0, rotationX: 0, ease: Quad.easeOut});
TweenMax.to(c.node, 1, {rotationY: 0, rotationX: 0});
}
function handle_mouseover(e) {
TweenMax.to(s.node, 0.2, {scale: 1, ease: Back.easeOut});
}
function angleToPoints(angle) {
var segment = Math.floor(angle / Math.PI * 2) + 2;
var diagonal = (1/2 * segment + 1/4) * Math.PI;
var op = Math.cos(Math.abs(diagonal - angle)) * Math.sqrt(2);
var x = op * Math.cos(angle);
var y = op * Math.sin(angle);
return {
x1: x < 0 ? 1 : 0,
y1: y < 0 ? 1 : 0,
x2: x >= 0 ? x : x + 1,
y2: y >= 0 ? y : y + 1
};
}
}
</script>
</body>
</html>
I have tried to do it with an a tag using href attribute in my html, but it totally breaks the parallax effect.
I am not the expert in javascript, I just changed the code I found and it works perfectly, but in my project, I definitelly need to set a link on the image. Do you have any idea how to do it please?

Try something like this (into the first for):
for (var i = 0; i < assets.length; i++) {
var img = new Image();
img.src = assets[i].url;
img.onload = handle_load;
/*Start my code*/
if (i==3) { //3 is your 'img/enf.png', or check the string in img.src
img.onclick = function(e){
window.location.href = 'the link of your news.html';
}
}
/*End my code*/
var _img = s.image(assets[i].url, assets[i].x, assets[i].y);
c.append(_img);
layers.push(_img);
}
EDIT
You are right, we wrong.
First of all, what your code generate is an SVG, and the SNAP library click event is this: http://snapsvg.io/docs/#Element.click
For this reason, the code above must be modified in this way:
for (var i = 0; i < assets.length; i++) {
var img = new Image();
img.src = assets[i].url;
img.onload = handle_load;
var _img = s.image(assets[i].url, assets[i].x, assets[i].y);
/*Start my code*/
if (i==3) {
_img.click(function(){
//window.location.href = 'www.debil.cz';
alert('yeah');
});
}
/*End my code*/
c.append(_img);
layers.push(_img);
}
BUT
You must remember that: the parallax effect work on layers, and the click event can't fired if an "invisible" element is below (as a blank region of a PNG).
Here a working example but with click on the item in the foreground !!
https://jsfiddle.net/StepBaro/hachn1sL/3/
Here another working example with click on the third element, and the event fired only on very top (because the first is above).
https://jsfiddle.net/StepBaro/hachn1sL/4/
Your assets array has as the last item inserted the highest element.

This isn't tested, but based on the information you provided this may help.
for (var i = 0; i < assets.length; i++) {
var img = new Image();
img.src = assets[i].url;
img.onload = handle_load;
//use an if statement to grab correct asset
//change page on click
if (img.src === "img/vybuch.png") {
img.onclick = function(e) {
document.location = "http://www.google.com/";
}
}
var _img = s.image(assets[i].url, assets[i].x, assets[i].y);
c.append(_img);
layers.push(_img);
}
Example:
var assets = [
{url: 'http://www.livefirelabs.com/images/learn-unix-demo-course.jpg', x: 0, y: 60, offset: -0.25},
]
for (var i = 0; i < assets.length; i++) {
var img = new Image();
img.src = assets[i].url;
img.onload = handle_load;
//use an if statement to grab correct asset
//change page on click
if (img.src === "http://www.livefirelabs.com/images/learn-unix-demo-course.jpg") {
img.onclick = function(e) {
document.location = "https://jsfiddle.net/";
}
}
document.body.appendChild(img);
}
function handle_load() {
//do nothing
}

Related

Why does speed of Ball is lower in the corners of the canvas?

Sorry for my english it is not my native language. I hope you understand me.
I made a ball that moves in a specific path around the canvas i define. Everything is going fine and my ball moves correctly, but i notice that when the ball reaches a corner it's speed is lower than it is when it moves straight. Does anyone Knows why this happens?
Here is my code.
Thanks in advance!
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var pathArray = [];
pathArray.push({
x: 150,
y: 100
});
pathArray.push({
x: 1375,
y: 100
});
pathArray.push({
x: 1375,
y: 230
});
pathArray.push({
x: 150,
y: 230
});
pathArray.push({
x: 150,
y: 320
});
pathArray.push({
x: 1375,
y: 320
});
pathArray.push({
x: 1375,
y: 450
});
pathArray.push({
x: 150,
y: 450
});
var polypoints = makePolyPoints(pathArray);
var width = 15;
var height = 30;
var speed = 1 / 2;
var position = 0;
animate();
function animate() {
setTimeout(function() {
requestAnimFrame(animate);
position += speed;
if (position > polypoints.length - 1) {
return;
}
var pt = polypoints[position];
if (pt) {
ctx.save();
ctx.beginPath();
ctx.translate(pt.x, pt.y);
ctx.arc(-width / 2, -height / 2, 12, 0, 2 * Math.PI);
ctx.fillStyle = "#B22222";
ctx.fill();
ctx.restore();
}
}, 1000 / 60);
}
function makePolyPoints(pathArray) {
var points = [];
for (var i = 1; i < pathArray.length; i++) {
var startPt = pathArray[i - 1];
var endPt = pathArray[i];
var dx = endPt.x - startPt.x;
var dy = endPt.y - startPt.y;
for (var n = 0; n <= 200; n++) {
var x = startPt.x + dx * n / 200;
var y = startPt.y + dy * n / 200;
points.push({
x: x,
y: y
});
}
}
return (points);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="1515" height="950" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
It's because when your makePolyPoints() function splits the path into points, it always creates 200 points per line, not taking the actual distance into account.
What you wanna do is calculate the distance using pythagoras, and then set the number of points accordingly. I included a speedFactor into the function parameters, so you can fine tune.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var pathArray = [];
pathArray.push({
x: 150,
y: 100
});
pathArray.push({
x: 1375,
y: 100
});
pathArray.push({
x: 1375,
y: 230
});
pathArray.push({
x: 150,
y: 230
});
pathArray.push({
x: 150,
y: 320
});
pathArray.push({
x: 1375,
y: 320
});
pathArray.push({
x: 1375,
y: 450
});
pathArray.push({
x: 150,
y: 450
});
var polypoints = makePolyPoints(pathArray, 5);
var width = 15;
var height = 30;
var speed = 1 / 2;
var position = 0;
animate();
function animate() {
setTimeout(function() {
requestAnimFrame(animate);
position += speed;
if (position > polypoints.length - 1) {
return;
}
var pt = polypoints[position];
if (pt) {
ctx.save();
ctx.beginPath();
ctx.translate(pt.x, pt.y);
ctx.arc(-width / 2, -height / 2, 12, 0, 2 * Math.PI);
ctx.fillStyle = "#B22222";
ctx.fill();
ctx.restore();
}
}, 1000 / 60);
}
function makePolyPoints(pathArray, speedFactor) {
var points = [];
for (var i = 1; i < pathArray.length; i++) {
var startPt = pathArray[i - 1];
var endPt = pathArray[i];
var dx = endPt.x - startPt.x;
var dy = endPt.y - startPt.y;
var distance = Math.sqrt(dx*dx+dy*dy)
var steps = distance/speedFactor
for (var n = 0; n <= steps; n++) {
var x = startPt.x + dx * n / steps;
var y = startPt.y + dy * n / steps;
points.push({
x: x,
y: y
});
}
}
return (points);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="1515" height="950" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>

Change falling hearts background animation to use multiple, random images

My question is for this plugin: https://codepen.io/bferioli/pen/qEGaPp
I'm trying to use several pictures in this canvas but I can't find how to. Basically, what I want is to display randomly a selection of images (10 or more) instead of only the heart.
I think I have to edit this part of that CodePen snippet:
heartHeight: 60,
heartWidth: 64,
hearts: [],
heartImage: 'http://i58.tinypic.com/ntnw5.png',
maxHearts: 8,
minScale: 0.4,
draw: function() {
this.setCanvasSize();
this.ctx.clearRect(0, 0, this.w, this.h);
for (var i = 0; i < this.hearts.length; i++) {
var heart = this.hearts[i];
heart.image = new Image();
heart.image.style.height = heart.height;
heart.image.src = this.heartImage;
this.ctx.globalAlpha = heart.opacity;
this.ctx.drawImage (heart.image, heart.x, heart.y, heart.width,
heart.height);
}
HERE IS MY CODE visible here: https://codepen.io/Le-future/pen/eKaarK
var imagesArray = ["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAABlBMVEX/4AL9+dVNpYF7AAAATElEQVR4nO3BQREAAAwCIO1fein28YB0XQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAvXXdlRQHDJgU7pgAAAABJRU5ErkJggg==", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAA1BMVEUpczS1QJ41AAAASElEQVR4nO3BgQAAAADDoPlTX+AIVQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwDcaiAAFXD1ujAAAAAElFTkSuQmCC", "https://www.apyart.com/2226-thickbox_default/bleu-ciel-500ml.jpg"];
var HeartsBackground = {
heartHeight: 60,
heartWidth: 64,
hearts: [],
heartImage: 'http://i58.tinypic.com/ntnw5.png',
maxHearts: 8,
minScale: 0.4,
draw: function() {
this.setCanvasSize();
this.ctx.clearRect(0, 0, this.w, this.h);
for (var i = 0; i < this.hearts.length; i++) {
var num = Math.floor(Math.random() * 3); // 0...3
var heart = this.hearts[i];
heart.image = new Image();
heart.image.style.height = heart.height;
heart.image.src = imagesArray[num];
this.ctx.globalAlpha = heart.opacity;
this.ctx.drawImage (heart.image, heart.x, heart.y, heart.width, heart.height);
}
this.move();
},
move: function() {
for(var b = 0; b < this.hearts.length; b++) {
var heart = this.hearts[b];
heart.y += heart.ys;
if(heart.y > this.h) {
heart.x = Math.random() * this.w;
heart.y = -1 * this.heartHeight;
}
}
},
setCanvasSize: function() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.w = this.canvas.width;
this.h = this.canvas.height;
},
initialize: function() {
this.canvas = $('#canvas')[0];
if(!this.canvas.getContext)
return;
this.setCanvasSize();
this.ctx = this.canvas.getContext('2d');
for(var a = 0; a < this.maxHearts; a++) {
var scale = (Math.random() * (1 - this.minScale)) + this.minScale;
this.hearts.push({
x: Math.random() * this.w,
y: Math.random() * this.h,
ys: Math.random() + 1,
height: scale * this.heartHeight,
width: scale * this.heartWidth,
opacity: scale,
image: imagesArray[Math.floor(Math.random()*imagesArray.length)]
});
}
setInterval($.proxy(this.draw, this), 30);
}
};
$(document).ready(function(){
HeartsBackground.initialize();
});
My answer is to add an array outside of the heartsBackground loop. it will be used to store the image of each of the 8 objects.
var heartsOutside = ["","","","","","","",""]
I then check to see if the outside array contains data and load if exists
if(heartsOutside[i] != ""){num = heartsOutside[i]}
Then store the data to the outside array for the next loop
heartsOutside[i] = num;
I also added a step to clear the heart image upon reaching the bottom of the fall in the move function
heartsOutside[b] = ""
var imagesArray = ["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAABlBMVEX/4AL9+dVNpYF7AAAATElEQVR4nO3BQREAAAwCIO1fein28YB0XQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAvXXdlRQHDJgU7pgAAAABJRU5ErkJggg==", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAA1BMVEUpczS1QJ41AAAASElEQVR4nO3BgQAAAADDoPlTX+AIVQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwDcaiAAFXD1ujAAAAAElFTkSuQmCC", "https://www.apyart.com/2226-thickbox_default/bleu-ciel-500ml.jpg"];
var heartsOutside = ["","","","","","","",""]
var HeartsBackground = {
heartHeight: 60,
heartWidth: 64,
hearts: [],
heartImage: 'http://i58.tinypic.com/ntnw5.png',
maxHearts: 8,
minScale: 0.4,
draw: function() {
this.setCanvasSize();
this.ctx.clearRect(0, 0, this.w, this.h);
for (var i = 0; i < this.hearts.length; i++) {
//else{
var num = Math.floor(Math.random() * 3); // 0...4
if(heartsOutside[i] != ""){num = heartsOutside[i]}
var heart = this.hearts[i];
heartsOutside[i] = num;
heart.image = new Image();
heart.image.style.height = heart.height;
heart.image.src = imagesArray[num];
this.ctx.globalAlpha = heart.opacity;
this.ctx.drawImage (heart.image, heart.x, heart.y, heart.width, heart.height);
}
this.move();
},
move: function() {
for(var b = 0; b < this.hearts.length; b++) {
var heart = this.hearts[b];
heart.y += heart.ys;
if(heart.y > this.h) {
heart.x = Math.random() * this.w;
heart.y = -1 * this.heartHeight;
heartsOutside[b] = ""
}
}
},
setCanvasSize: function() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.w = this.canvas.width;
this.h = this.canvas.height;
},
initialize: function() {
this.canvas = $('#canvas')[0];
if(!this.canvas.getContext)
return;
this.setCanvasSize();
this.ctx = this.canvas.getContext('2d');
for(var a = 0; a < this.maxHearts; a++) {
var scale = (Math.random() * (1 - this.minScale)) + this.minScale;
this.hearts.push({
x: Math.random() * this.w,
y: Math.random() * this.h,
ys: Math.random() + 1,
height: scale * this.heartHeight,
width: scale * this.heartWidth,
opacity: scale,
image: imagesArray[Math.floor(Math.random()*imagesArray.length)]
});
}
setInterval($.proxy(this.draw, this), 30);
}
};
$(document).ready(function(){
HeartsBackground.initialize();
});
body {
background: #B7004E;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas"></canvas>

How to manage multiple ball animations?

I have made a program that is supposed to make several balls move along a path. So far, I have only been able to make one ball successfully traverse the course because whenever I add another ball (from the array of balls) it begins to flicker and spasmodically disappears. I would appreciate any assistance in solving this problem.
JS bin
<!DOCTYPE html>
<html>
<head>
<style>
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<canvas id="Circuit" width="500" height="320"></canvas>
<script>
var dad = [];
var canvas = document.getElementById("Circuit");
var ctx = canvas.getContext("2d");
var bool = false;
var dx1 = 2;
var dx2 = -2;
var dy1 = 0;
var dy2 = 2;
var memes = [{
x: 0,
y: 100,
}, {
x: 0,
y: 100,
}, {
x: 0,
y: 100,
}, {
x: 0,
y: 100,
}];
function drawCircle(index) {
ctx.beginPath();
ctx.arc(memes[index].x, memes[index].y, 10, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw(index) {
if (index == 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
if (memes[index].x < 490 && memes[index].y < 291 && !bool) {
drawCircle(index);
memes[index].x += dx1;
memes[index].y += dy1;
}
else if (memes[index].x == 490) {
drawCircle(index);
memes[index].x += 1;
}
else if (memes[index].x > 490 && memes[index].y < 291) {
drawCircle(index);
memes[index].y += dy2;
}
else if (memes[index].y == 291) {
drawCircle(index);
memes[index].y += 1;
}
else if (memes[index].y > 291 && memes[index].x > 2) {
drawCircle(index);
bool = true;
memes[index].x -= 2;
}
else if (memes[index].x == 2 && memes[index].y > 291) {
drawCircle(index);
memes[index].x -= 1;
}
else if (memes[index].x < 2) {
drawCircle(index);
memes[index].y -= dy2;
if (memes[index].y < 100) {
clearInterval(dad[index]);
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}
ctx.strokeStyle = "red";
ctx.strokeRect(2, 101, 490, 190);
ctx.strokeStyle = "blue";
ctx.strokeRect(2, 82, 40, 40);
}
setTimeout(function() {
setTimeout(function() {
dad[1] = setInterval(function() {
draw(1);
}, 20);
}, 1000);
dad[0] = setInterval(function() {
draw(0);
}, 20);
}, 1000);
</script>
</body>
</html>
The flicker happens when the second ball tries to render the frame. You have two sprites (animating things) clearing and drawing the frame. You also have multiple timers and when animating you usually want a nextFrame function that handles movement of the sprites and drawing the frame.
The sprites array is a list of things that need to be moved and drawn. I added some properties to the meme sprites so you can see that their state needs to be internal like with the "bool" value. Without that you end up effecting the other balls. You'll need to figure out how to remove sprites when they're no longer in play.
var dad = [];
var canvas = document.getElementById("Circuit");
var ctx = canvas.getContext("2d");
var bool = false;
var dx1 = 2;
var dx2 = -2;
var dy1 = 0;
var dy2 = 2;
var memes = [{
x: 0,
y: 100,
color: "#0095DD",
draw: drawMeme,
move: moveMeme,
vx: 1.2,
vy: 1.5,
}, {
x: 0,
y: 100,
vx: 1.5,
vy: 1,
color: "#DD9500",
draw: drawMeme,
move: moveMeme
}, {
x: 0,
y: 100,
vx: 2,
vy: 1,
color: "#FF0000",
draw: drawMeme,
move: moveMeme
}, {
x: 0,
y: 100,
vx: 3,
vy: 2,
color: "#009999",
draw: drawMeme,
move: moveMeme
}];
function drawMeme(meme) {
ctx.beginPath();
ctx.arc(meme.x, meme.y, 10, 0, Math.PI * 2);
ctx.fillStyle = meme.color;
ctx.fill();
ctx.closePath();
}
var sprites = [];
function nextFrame () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var len = sprites.length;
for (var i = 0; i < len; i++) {
var sprite = sprites[i];
sprite.move(sprite);
sprite.draw(sprite);
}
ctx.strokeStyle = "red";
ctx.strokeRect(2, 101, 490, 190);
ctx.strokeStyle = "blue";
ctx.strokeRect(2, 82, 40, 40);
requestAnimationFrame(nextFrame);
}
function moveMeme(meme) {
if (meme.x < 490 && meme.y < 291 && !meme.bool) {
meme.x += dx1 * meme.vx;
meme.y += dy1 * meme.vy;
}
else if (meme.x == 490) {
meme.x += 1 * meme.vx;
}
else if (meme.x > 490 && meme.y < 291) {
meme.y += dy2 * meme.vy;
}
else if (meme.y == 291) {
meme.y += 1 * meme.vy;
}
else if (meme.y > 291 && meme.x > 2) {
meme.bool = true;
meme.x -= 2 * meme.vx;
}
else if (meme.x == 2 && meme.y > 291) {
meme.x -= 1 * meme.vx;
}
else if (meme.x < 2) {
meme.y -= dy2 * meme.vy;
if (meme.y < 100) {
// stop drawing this sprite
meme.draw = function(){};
meme.delete = 1; // for a cleanup function
}
}
}
nextFrame();
function startMeme(index) {
var meme = memes[index];
sprites.push(meme);
}
setTimeout(function() {
setTimeout(function() {
startMeme(1);
}, 1000);
startMeme(0);
startMeme(2);
startMeme(3);
}, 1000);
<canvas id="Circuit" width="500" height="320"></canvas>

How to keep text on image in kineticjs

I am trying to keep text on image through kineticjs. But initially I am able to keep the text on image after dragging the image text is going under the image. Can anyone help me on this. Here is my fiddle,
JSFiddle
$(document).ready(function()
{
var startAngle = 0;
var minImgSize = 10;
function update(activeAnchor)
{
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var rotateAnchor = group.get('.rotateAnchor')[0];
var image = group.get('Image')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
var imageWidth = image.getWidth();
var imageHeight = image.getHeight();
// update anchor positions
switch (activeAnchor.getName()) {
case 'rotateAnchor':
break;
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
topRight.setX(anchorX);
bottomLeft.setY(anchorY);
break;
case 'bottomLeft':
topLeft.setX(anchorX);
bottomRight.setY(anchorY);
break;
}
if (topRight.getX() < topLeft.getX() + minImgSize)
{
topRight.setX(topLeft.getX() + minImgSize);
}
if (bottomRight.getX() < topLeft.getX() + minImgSize)
{
bottomRight.setX(topLeft.getX() + minImgSize);
}
if (bottomRight.getY() < topLeft.getY() + minImgSize)
{
bottomRight.setY(topLeft.getY() + minImgSize);
}
if (bottomLeft.getY() < topLeft.getY() + minImgSize)
{
bottomLeft.setY(topLeft.getY() + minImgSize);
}
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
image.setPosition({x : topLeft.getPosition().x, y:(topLeft.getPosition().y)});
image.setWidth(width);
image.setHeight(height);
rotateAnchor.setX(width / 2 + topLeft.getX());
rotateAnchor.setY(height / 2 + topLeft.getY());
}
function addAnchor(group, x, y, name, dragBound)
{
var stage = group.getStage();
var layer = group.getLayer();
var groupPos = group.getPosition();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 6,
name: name,
draggable: true,
dragOnTop: false
});
if (dragBound == 'rotate')
{
startAngle = angle(groupPos.x, groupPos.y, x + groupPos.x, y + groupPos.y);
anchor.setAttrs({
dragBoundFunc: function (pos) {
return getRotatingAnchorBounds(pos, group);
}
});
}
anchor.on('dragmove', function() {
update(this);
layer.draw();
});
anchor.on('mousedown touchstart', function() {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function() {
group.setDraggable(true);
layer.draw();
});
// add hover styling
anchor.on('mouseover', function() {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
layer.draw();
});
anchor.on('mouseout', function() {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
function loadImages(sources, callback)
{
var images = {};
var loadedImages = 0;
var numImages = 0;
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
function radians (degrees) {return degrees * (Math.PI/180)}
function degrees (radians) {return radians * (180/Math.PI)}
function angle (cx, cy, px, py) {var x = cx - px; var y = cy - py; return Math.atan2 (-y, -x)}
function distance (p1x, p1y, p2x, p2y) {return Math.sqrt (Math.pow ((p2x - p1x), 2) + Math.pow ((p2y - p1y), 2))}
function getRotatingAnchorBounds(pos, group)
{
var groupPos = group.getPosition();
var rotation = degrees (angle (groupPos.x, groupPos.y, pos.x, pos.y) - startAngle);
var dis = distance (groupPos.x, groupPos.y, pos.x, pos.y);
console.log('x: ' + pos.x + '; y: ' + pos.y + '; rotation: ' + rotation + '; distance:' + dis);
group.setRotationDeg (rotation);
return pos;
}
function initStage(images)
{
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 400
});
var darthVaderGroup = new Kinetic.Group({
x: 270,
y: 100,
draggable: true,
fill: 'black'
});
var layer = new Kinetic.Layer();
var sw = stage.getWidth();
var sh = stage.getHeight();
var text = new Kinetic.Text({
x: 100,
y: 100,
text: "Gowtham",
fontSize: 32,
fontFamily: "Arial",
fill: "black",
stroke: "white",
strokeWidth: 1,
draggable: true,
dragBoundFunc: function (pos) {
var w = this.getWidth();
var h = this.getHeight();
if (pos.x < 0) {
pos.x = 0;
}
if (pos.x + w > sw) {
pos.x = sw - w;
}
if (pos.y < 0) {
pos.y = 0;
}
if (pos.y + h > sh) {
pos.y = sh - h;
}
return {
x: pos.x,
y: pos.y
}
}
});
layer.add(darthVaderGroup);
stage.add(layer);
layer.add(text);
layer.draw();
var darthVaderImg = new Kinetic.Image({
x: 0,
y: 0,
image: images.darthVader,
width: 200,
height: 138,
name: 'image'
});
darthVaderGroup.add(darthVaderImg);
addAnchor(darthVaderGroup, 0, 0, 'topLeft', 'none');
addAnchor(darthVaderGroup, darthVaderImg.getWidth(), 0, 'topRight', 'none');
addAnchor(darthVaderGroup, darthVaderImg.getWidth(), darthVaderImg.getHeight(), 'bottomRight', 'none');
addAnchor(darthVaderGroup, 0, darthVaderImg.getHeight(), 'bottomLeft', 'none');
addAnchor(darthVaderGroup, darthVaderImg.getWidth() / 2, darthVaderImg.getHeight() / 2, 'rotateAnchor','rotate');
darthVaderGroup.on('dragstart', function() {
this.moveToTop();
});
stage.draw();
}
var sources = {
darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'
};
loadImages(sources, initStage);
});
canvas
{
border: 1px solid #aaa;
-moz-box-shadow: 3px 3px 8px #222;
-webkit-box-shadow: 3px 3px 8px #222;
box-shadow: 3px 3px 8px #222;
}
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/kineticjs/5.2.0/kinetic.min.js"></script>
<div id="container"></div>
<button id="addImage">Add
</button>

Changing speed for each shape on canvas

How change the speed of each shape?
I tried to play with pct but I guess this is wrong way:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
// shape stuff
var shapes = [];
var points;
// shape#1
points = pointsToSingleArray([{
x: 20,
y: 20
}, {
x: 50,
y: 100
}, {
x: 75,
y: 20
}, {
x: 100,
y: 100
}]);
shapes.push({
width: 20,
height: 10,
waypoints: points,
color: "red"
});
// shape#2
points = pointsToSingleArray([{
x: 0,
y: 0
}, {
x: 180,
y: 0
}, {
x: 180,
y: 180
}, {
x: 0,
y: 180
}, {
x: 0,
y: 0
}, {
x: 100,
y: 80
}]);
shapes.push({
width: 20,
height: 20,
waypoints: points,
color: "blue"
});
// animation stuff
var index = 0;
var fps = 60;
// start animating
animate();
function pointsToSingleArray(points) {
// array to hold all points on this polyline
var allPoints = [];
// analyze all lines formed by this points array
for (var a = 1; a < points.length; a++) { // loop through each array in points[]
// vars for interpolating steps along a line
var dx = points[a].x - points[a - 1].x;
var dy = points[a].y - points[a - 1].y;
var startX = points[a - 1].x;
var startY = points[a - 1].y;
// calc 100 steps along this particular line segment
for (var i = 1; i <= 100; i++) {
var pct = Math.min(1, i * .01);
var nextX = startX + dx * pct;
var nextY = startY + dy * pct;
allPoints.push({
x: nextX,
y: nextY
});
}
}
return (allPoints);
}
function animate() {
setTimeout(function () {
// this flag becomes true if we made any moves
// If true, we later request another animation frame
var weMoved = false;
// clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw all shapes
for (var i = 0; i < shapes.length; i++) {
// get reference to next shape
var shape = shapes[i];
// check if we still have waypoint steps for this shape
if (index < shape.waypoints.length) {
// we're not done, so set the weMoved flag
weMoved = true;
// draw this shape at its next XY
drawShape(shape, index);
} else {
// we're done animating this shape
// draw it in its final position
drawShape(shape, shape.waypoints.length - 1);
}
}
// goto next index XY in the waypoints array
// Note: incrementing by 2 doubles animation speed
index += 2;
// if weMoved this frame, request another animation loop
if (weMoved) {
requestAnimFrame(animate)
};
}, 1000 / fps);
}
function drawShape(shape, waypointIndex) {
var x = shape.waypoints[waypointIndex].x;
var y = shape.waypoints[waypointIndex].y;
ctx.fillStyle = shape.color;
ctx.fillRect(x, y, shape.width, shape.height);
}
Maybe somebody know examples with changing speed, or how to make the code better.
http://jsfiddle.net/4DxLL/ - changing speed
var index = [0, 0];
shapes.push({
width: 20,
height: 10,
waypoints: points,
color: "red",
speed: 10,
});
index[i] += shape.speed;

Categories