What is the right offset for better drag effect?











up vote
0
down vote

favorite












I am trying to make my cloud draggable. It works but as can be seen in the example that i have, the cloud always clippes from the center to the mouse possition.



Here is my current set-up.






$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = true;
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>





The code that sets the location of the cloud when dragged is this:



// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}


This does not work correctly. I want it not to clip to the center.



Can any one help me with this ?



If its not completely clear what the question is or if you need any extra information please ask.










share|improve this question
























  • "i know not all code is used but that is not important." It is for those willing to help you as they have to go through the code. Please strip it down to the essential part (see Minimal, Complete, and Verifiable example). Furthermore, please use the HTML/CSS/JavaScript code snippet function to make it more accessible.
    – Nico Schertler
    Nov 19 at 17:09












  • @NicoSchertler Edited. removed unused code
    – JanWillem Huising
    Nov 19 at 17:13















up vote
0
down vote

favorite












I am trying to make my cloud draggable. It works but as can be seen in the example that i have, the cloud always clippes from the center to the mouse possition.



Here is my current set-up.






$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = true;
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>





The code that sets the location of the cloud when dragged is this:



// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}


This does not work correctly. I want it not to clip to the center.



Can any one help me with this ?



If its not completely clear what the question is or if you need any extra information please ask.










share|improve this question
























  • "i know not all code is used but that is not important." It is for those willing to help you as they have to go through the code. Please strip it down to the essential part (see Minimal, Complete, and Verifiable example). Furthermore, please use the HTML/CSS/JavaScript code snippet function to make it more accessible.
    – Nico Schertler
    Nov 19 at 17:09












  • @NicoSchertler Edited. removed unused code
    – JanWillem Huising
    Nov 19 at 17:13













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I am trying to make my cloud draggable. It works but as can be seen in the example that i have, the cloud always clippes from the center to the mouse possition.



Here is my current set-up.






$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = true;
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>





The code that sets the location of the cloud when dragged is this:



// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}


This does not work correctly. I want it not to clip to the center.



Can any one help me with this ?



If its not completely clear what the question is or if you need any extra information please ask.










share|improve this question















I am trying to make my cloud draggable. It works but as can be seen in the example that i have, the cloud always clippes from the center to the mouse possition.



Here is my current set-up.






$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = true;
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>





The code that sets the location of the cloud when dragged is this:



// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}


This does not work correctly. I want it not to clip to the center.



Can any one help me with this ?



If its not completely clear what the question is or if you need any extra information please ask.






$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = true;
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>





$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = true;
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
var offsetX = mousePosition.x - this.location.x;
var offsetY = mousePosition.y - this.location.y;

this.location = new Vector2d(this.location.x + offsetX - this.width/2, this.location.y + offsetY - this.height/2);
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>






javascript jquery html math draggable






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 19 at 17:13

























asked Nov 19 at 16:58









JanWillem Huising

17510




17510












  • "i know not all code is used but that is not important." It is for those willing to help you as they have to go through the code. Please strip it down to the essential part (see Minimal, Complete, and Verifiable example). Furthermore, please use the HTML/CSS/JavaScript code snippet function to make it more accessible.
    – Nico Schertler
    Nov 19 at 17:09












  • @NicoSchertler Edited. removed unused code
    – JanWillem Huising
    Nov 19 at 17:13


















  • "i know not all code is used but that is not important." It is for those willing to help you as they have to go through the code. Please strip it down to the essential part (see Minimal, Complete, and Verifiable example). Furthermore, please use the HTML/CSS/JavaScript code snippet function to make it more accessible.
    – Nico Schertler
    Nov 19 at 17:09












  • @NicoSchertler Edited. removed unused code
    – JanWillem Huising
    Nov 19 at 17:13
















"i know not all code is used but that is not important." It is for those willing to help you as they have to go through the code. Please strip it down to the essential part (see Minimal, Complete, and Verifiable example). Furthermore, please use the HTML/CSS/JavaScript code snippet function to make it more accessible.
– Nico Schertler
Nov 19 at 17:09






"i know not all code is used but that is not important." It is for those willing to help you as they have to go through the code. Please strip it down to the essential part (see Minimal, Complete, and Verifiable example). Furthermore, please use the HTML/CSS/JavaScript code snippet function to make it more accessible.
– Nico Schertler
Nov 19 at 17:09














@NicoSchertler Edited. removed unused code
– JanWillem Huising
Nov 19 at 17:13




@NicoSchertler Edited. removed unused code
– JanWillem Huising
Nov 19 at 17:13












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










You need to remember the click location within the cloud's local coordinate system:



if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}


Then, when you update, you calculate the new position based on the click location:



this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;





$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>








share|improve this answer





















  • Works great, Thank you.
    – JanWillem Huising
    Nov 19 at 17:50











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53379393%2fwhat-is-the-right-offset-for-better-drag-effect%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










You need to remember the click location within the cloud's local coordinate system:



if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}


Then, when you update, you calculate the new position based on the click location:



this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;





$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>








share|improve this answer





















  • Works great, Thank you.
    – JanWillem Huising
    Nov 19 at 17:50















up vote
1
down vote



accepted










You need to remember the click location within the cloud's local coordinate system:



if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}


Then, when you update, you calculate the new position based on the click location:



this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;





$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>








share|improve this answer





















  • Works great, Thank you.
    – JanWillem Huising
    Nov 19 at 17:50













up vote
1
down vote



accepted







up vote
1
down vote



accepted






You need to remember the click location within the cloud's local coordinate system:



if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}


Then, when you update, you calculate the new position based on the click location:



this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;





$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>








share|improve this answer












You need to remember the click location within the cloud's local coordinate system:



if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}


Then, when you update, you calculate the new position based on the click location:



this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;





$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>








$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>





$(document).ready(function () {

var canvas = document.getElementById("background-canvas");
canvas.width = $(window).width();
canvas.height = $(window).height();
canvas.style.zIndex = -1;
var ctx = canvas.getContext("2d");

var mousePosition = new Vector2d(0,0);

var background = new Background(ctx, canvas.width, canvas.height, new Color(224,247,250,0.8));
var cloud = new Cloud(background, 300, 100, new Vector2d(10,10), 20, 1000);
img=new Image();
img.src="https://i.imgur.com/hIVsoho.png";

background.addCloud(cloud);

for (var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
for (var j = 0; j < selectedCloud.maxNumberofPixels; j++){
var pixel = cloud.createPixel(); // TODO: cloud shall not define pixel.
//new Pixel(2, 4, getRandomLocationWithinParent(selectedCloud), new Vector2d(0,5), new Vector2d(0,0), new Color(0,0,128,1));
cloud.addPixel(pixel);
}
}
/*
* Input listeners
*/
document.addEventListener("mousemove", function (evt) {
mousePosition = getMousePos(canvas, evt);
}, false);
document.addEventListener("mousedown", function (evt){
console.log(mousePosition);
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition)) {
background.allClouds[i].isClicked = true;
background.allClouds[i].clickLocalPosition = new Vector2d(mousePosition.x, mousePosition.y);
background.allClouds[i].clickLocalPosition.sub(background.allClouds[i].location);
}
}, false)
document.addEventListener("mouseup", function (evt){
for(var i = 0; i < background.allClouds.length; i++)
if(background.allClouds[i].hover(mousePosition))
background.allClouds[i].isClicked = false;
}, false)


setInterval(updateBackground, 20);

function updateBackground() {
// paint background color.
ctx.fillStyle = background.color.getColorString();
ctx.fillRect(0,0,background.width, background.height);

// paint clouds
for(var i = 0; i < background.allClouds.length; i++){
var selectedCloud = background.allClouds[i];
//ctx.fillStyle = selectedCloud.color.getColorString();
//ctx.fillRect(0, 0, selectedCloud.width, selectedCloud.height); rectangle view of cloud.

// paint rain
var deadPixelContainer = ;
for (var j = 0; j < selectedCloud.allPixels.length; j++){
var selectedPixel = selectedCloud.allPixels[j];
ctx.fillStyle = selectedPixel.color.getColorString();
ctx.save();
ctx.translate(selectedPixel.location.x, selectedPixel.location.y);
ctx.fillRect(-selectedPixel.width / 2, -selectedPixel.height / 2, selectedPixel.width, selectedPixel.height);
ctx.restore();
if(!selectedPixel.alive){
deadPixelContainer.push(selectedPixel);
continue;
}
selectedPixel.update();
selectedPixel.checkEdges(background);

}
if(deadPixelContainer.length > 0){
selectedCloud.removePixels(deadPixelContainer);
}
ctx.save();
ctx.translate(selectedCloud.location.x, selectedCloud.location.y);
ctx.drawImage(img,0,0,img.width,img.height,-25, -10,350,100);
ctx.restore();
cloud.update(mousePosition);
}

}
// TODO: Create object for mouse
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return new Vector2d(evt.clientX - rect.left, evt.clientY - rect.top);
}

});


function Cloud(background, width, height, location, startNumberOfPixels, maxNumberofPixels){
this.width = width;
this.height = height;
this.location = location;
this.allPixels = ;
this.maxNumberofPixels = maxNumberofPixels;
this.color = new Color(255,255,255,0.5);
this.isClicked = false;
this.rainStrength = 5; // how often cloud spawns new pixels per update cycle.
this.addPixel = function(pixel){
if(this.allPixels.length <= startNumberOfPixels)
this.allPixels.push(pixel);
}
this.update = function(mousePosition){
// make cloud draggable
if(this.isClicked){
this.location.x = mousePosition.x - this.clickLocalPosition.x;
this.location.y = mousePosition.y - this.clickLocalPosition.y;
}
// add more pixels overtime.
if(this.allPixels.length <= this.maxNumberofPixels)
for(var i = 0; i < this.rainStrength; i++)
this.allPixels.push(this.createPixel());
}
this.hover = function(mousePosition){
if(mousePosition.x > this.location.x
&& mousePosition.x < this.location.x + this.width
&& mousePosition.y > this.location.y
&& mousePosition.y < this.location.y + this.height)
return true;
return false;
}
this.createPixel = function(){
return new Pixel(2, 4, this.getRandomLocation(), new Vector2d(0,7), new Vector2d(0,0.05), new Color(0,0,128,1));
}
this.removePixels = function(deadPixelContainer){
for(var i = 0; i < deadPixelContainer.length; i++){
try{
var pixelContainer = this.allPixels.slice();
pixelContainer.splice(this.allPixels.findIndex(v => v === deadPixelContainer[i]), 1).slice();
this.allPixels = pixelContainer.slice();
}catch(e){
console.log(e);
}
}
}
this.getRandomLocation = function(){
var minWidth = this.location.x;
var maxWidth = this.location.x + this.width;
var minHeight = this.location.y + this.height/2; // don't count upper part of cloud. Rain forms at the bottom.
var maxHeight = this.location.y + this.height;
var randomWidthLocation = Math.random() * (maxWidth - minWidth + 1)+minWidth;
var randomHeightLocation = Math.random() * (maxHeight - minHeight + 1) + minHeight;
return new Vector2d(randomWidthLocation, randomHeightLocation);
}
}

function Background(ctx, width, height, color){
this.width = width;
this.height = height;
this.color = color; //"#191919"
this.isPaused = false;
this.allPixels = ; // might need to be removed.
this.allClouds = ;
this.pixelCount = 150;
this.addCloud = function(cloud){
this.allClouds.push(cloud);
};
this.refreshCanvas = function(){
this.width = $(window).width();
this.height = $(window).height();
};
this.addPixelOn = function(pixelWidht, pixelHeight, location, velocity, acceleration, color) { // might need to be removed.
var pixel = new Pixel(pixelWidht, pixelHeight, location, velocity, acceleration, color);
this.allPixels.push(pixel);
};
this.addPixel = function(pixelWidht, pixelHeight, velocity, acceleration, color) { // might need to be removed.
var location = new Vector2d(Math.random() * this.width, Math.random() * this.height);
this.addPixelOn(pixelWidht, pixelHeight, location, velocity, acceleration, color);
};
}

function Pixel(widht, height, location, velocity, acceleration, color) {
this.height = height;
this.width = widht;
this.color = color; //"#00CC33"
this.location = location;
this.velocity = velocity;
this.acceleration = acceleration;
this.alive = true;
this.update = function () {
this.velocity.add(this.acceleration);
//this.velocity.limit(topspeed);
this.location.add(this.velocity);
};
this.checkEdges = function (background) {
if (this.location.y > background.height) {
this.alive = false;
}
};
this.setColor = function(color){
this.color = color;
};
this.setHeight = function(height){
this.height = height;
};
this.setWidth = function(width){
this.width = width;
}
}

function Color(r,g,b,o){
this.red = r;
this.green = g;
this.blue = b;
this.opacity = o;
this.getColorString = function(){
return "rgba("+this.red+","+this.green+","+this.blue+","+this.opacity+")";
}
}

function Vector2d(x, y) {
this.x = x;
this.y = y;
this.add = function (vector2d) {
this.x += vector2d.x;
this.y += vector2d.y;
};
this.sub = function (vector2d) {
this.x -= vector2d.x;
this.y -= vector2d.y;
};
this.mult = function (mult) {
this.x *= mult;
this.y *= mult;
};
this.div = function (div) {
this.x /= div;
this.y /= div;
};
this.mag = function () {
return Math.sqrt(this.x * this.x, this.y * this.y);
};
this.norm = function () {
var m = this.mag();
if (m !== 0) {
this.div(m);
}
}
}

#background-canvas {
position: fixed;
width: 100%;
height: 100%
background-color:red;
top:0;
left:0;
}

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<canvas id="background-canvas" />
</body>
</html>






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 19 at 17:33









Nico Schertler

25k42350




25k42350












  • Works great, Thank you.
    – JanWillem Huising
    Nov 19 at 17:50


















  • Works great, Thank you.
    – JanWillem Huising
    Nov 19 at 17:50
















Works great, Thank you.
– JanWillem Huising
Nov 19 at 17:50




Works great, Thank you.
– JanWillem Huising
Nov 19 at 17:50


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53379393%2fwhat-is-the-right-offset-for-better-drag-effect%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

TypeError: fit_transform() missing 1 required positional argument: 'X'