Related
I am trying to set this HTML code to a Chromebook background. Is this possible? I also don't want to have to use any extensions.
<style>*{
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html, body{
height: 100%;
margin: 0;
padding: 0;
background-color: #333;
overflow: hidden;
}
canvas{
background-color: #000;
}</style>
<div class="container">
<div class="row">
<canvas id="nokey" width="800" height="800">
</canvas>
</div>
</div>
<script>
var canvas = document.getElementById('nokey'),
can_w = parseInt(canvas.getAttribute('width')),
can_h = parseInt(canvas.getAttribute('height')),
ctx = canvas.getContext('2d');
// console.log(typeof can_w);
var ball = {
x: 0,
y: 0,
vx: 0,
vy: 0,
r: 0,
alpha: 1,
phase: 0
},
ball_color = {
r: 207,
g: 255,
b: 4
},
R = 2,
balls = [],
alpha_f = 0.03,
alpha_phase = 0,
// Line
link_line_width = 0.8,
dis_limit = 260,
add_mouse_point = true,
mouse_in = false,
mouse_ball = {
x: 0,
y: 0,
vx: 0,
vy: 0,
r: 0,
type: 'mouse'
};
// Random speed
function getRandomSpeed(pos){
var min = -1,
max = 1;
switch(pos){
case 'top':
return [randomNumFrom(min, max), randomNumFrom(0.1, max)];
break;
case 'right':
return [randomNumFrom(min, -0.1), randomNumFrom(min, max)];
break;
case 'bottom':
return [randomNumFrom(min, max), randomNumFrom(min, -0.1)];
break;
case 'left':
return [randomNumFrom(0.1, max), randomNumFrom(min, max)];
break;
default:
return;
break;
}
}
function randomArrayItem(arr){
return arr[Math.floor(Math.random() * arr.length)];
}
function randomNumFrom(min, max){
return Math.random()*(max - min) + min;
}
console.log(randomNumFrom(0, 10));
// Random Ball
function getRandomBall(){
var pos = randomArrayItem(['top', 'right', 'bottom', 'left']);
switch(pos){
case 'top':
return {
x: randomSidePos(can_w),
y: -R,
vx: getRandomSpeed('top')[0],
vy: getRandomSpeed('top')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
}
break;
case 'right':
return {
x: can_w + R,
y: randomSidePos(can_h),
vx: getRandomSpeed('right')[0],
vy: getRandomSpeed('right')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
}
break;
case 'bottom':
return {
x: randomSidePos(can_w),
y: can_h + R,
vx: getRandomSpeed('bottom')[0],
vy: getRandomSpeed('bottom')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
}
break;
case 'left':
return {
x: -R,
y: randomSidePos(can_h),
vx: getRandomSpeed('left')[0],
vy: getRandomSpeed('left')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
}
break;
}
}
function randomSidePos(length){
return Math.ceil(Math.random() * length);
}
// Draw Ball
function renderBalls(){
Array.prototype.forEach.call(balls, function(b){
if(!b.hasOwnProperty('type')){
ctx.fillStyle = 'rgba('+ball_color.r+','+ball_color.g+','+ball_color.b+','+b.alpha+')';
ctx.beginPath();
ctx.arc(b.x, b.y, R, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
});
}
// Update balls
function updateBalls(){
var new_balls = [];
Array.prototype.forEach.call(balls, function(b){
b.x += b.vx;
b.y += b.vy;
if(b.x > -(50) && b.x < (can_w+50) && b.y > -(50) && b.y < (can_h+50)){
new_balls.push(b);
}
// alpha change
b.phase += alpha_f;
b.alpha = Math.abs(Math.cos(b.phase));
// console.log(b.alpha);
});
balls = new_balls.slice(0);
}
// loop alpha
function loopAlphaInf(){
}
// Draw lines
function renderLines(){
var fraction, alpha;
for (var i = 0; i < balls.length; i++) {
for (var j = i + 1; j < balls.length; j++) {
fraction = getDisOf(balls[i], balls[j]) / dis_limit;
if(fraction < 1){
alpha = (1 - fraction).toString();
ctx.strokeStyle = 'rgba(150,150,150,'+alpha+')';
ctx.lineWidth = link_line_width;
ctx.beginPath();
ctx.moveTo(balls[i].x, balls[i].y);
ctx.lineTo(balls[j].x, balls[j].y);
ctx.stroke();
ctx.closePath();
}
}
}
}
// calculate distance between two points
function getDisOf(b1, b2){
var delta_x = Math.abs(b1.x - b2.x),
delta_y = Math.abs(b1.y - b2.y);
return Math.sqrt(delta_x*delta_x + delta_y*delta_y);
}
// add balls if there a little balls
function addBallIfy(){
if(balls.length < 20){
balls.push(getRandomBall());
}
}
// Render
function render(){
ctx.clearRect(0, 0, can_w, can_h);
renderBalls();
renderLines();
updateBalls();
addBallIfy();
window.requestAnimationFrame(render);
}
// Init Balls
function initBalls(num){
for(var i = 1; i <= num; i++){
balls.push({
x: randomSidePos(can_w),
y: randomSidePos(can_h),
vx: getRandomSpeed('top')[0],
vy: getRandomSpeed('top')[1],
r: R,
alpha: 1,
phase: randomNumFrom(0, 10)
});
}
}
// Init Canvas
function initCanvas(){
canvas.setAttribute('width', window.innerWidth);
canvas.setAttribute('height', window.innerHeight);
can_w = parseInt(canvas.getAttribute('width'));
can_h = parseInt(canvas.getAttribute('height'));
}
window.addEventListener('resize', function(e){
console.log('Window Resize...');
initCanvas();
});
function goMovie(){
initCanvas();
initBalls(20);
window.requestAnimationFrame(render);
}
goMovie();
// Mouse effect
canvas.addEventListener('mouseenter', function(){
console.log('mouseenter');
mouse_in = true;
balls.push(mouse_ball);
});
canvas.addEventListener('mouseleave', function(){
console.log('mouseleave');
mouse_in = false;
var new_balls = [];
Array.prototype.forEach.call(balls, function(b){
if(!b.hasOwnProperty('type')){
new_balls.push(b);
}
});
balls = new_balls.slice(0);
});
canvas.addEventListener('mousemove', function(e){
var e = e || window.event;
mouse_ball.x = e.pageX;
mouse_ball.y = e.pageY;
// console.log(mouse_ball);
});
</script>
Since you said, "Chromebook." There's no native support for it as you're asking; without extension.
According to Google's Chromebook Help, they state only .png & .jpg backgrounds.
If you haven't yet, download an image (.png or .jpg) from the web that
you’d like as your wallpaper.
Also, referencing the crosexperts website, it states:
there’s no native support for moving wallpapers, we had to create an
engine — and editor — to make this possible. But, amazingly, it is
possible.
Chrome OS doesn’t support Live Wallpapers in any way.
EDIT::
I have converted the various points to (x,y) just as I wanted. I changed the name from bolt to drop because I already have an established shape named drop. However, it will not draw on the canvas. I replaced the coordinates with a leaf shape I also drew and converted to (x,y) and it worked fine. I can't figure out what's so different about my bolt shape.
context.beginPath();
context.moveTo(drop.x,drop.y);
context.moveTo(drop.x+140,drop.y+28);
context.lineTo(drop.x+24,drop.y+28);
context.moveTo(drop.x+24,drop.y+28);
context.lineTo(drop.x-2,drop.y+25);
context.moveTo(drop.x-2,drop.y+25);
context.lineTo(drop.x+17,drop.y+25);
context.moveTo(drop.x+17,drop.y+25);
context.lineTo(drop.x-18,drop.y+53);
context.moveTo(drop.x-18,drop.y+53);
context.lineTo(drop.x-3,drop.y+54);
context.moveTo(drop.x-3,drop.y+54);
context.lineTo(drop.x-47,drop.y+77);
context.moveTo(drop.x-47,drop.y+77);
context.lineTo(drop.x-31,drop.y+59);
context.moveTo(drop.x-31,drop.y+59);
context.lineTo(drop.x-40,drop.y+59);
context.moveTo(drop.x-40,drop.y+59);
context.lineTo(drop.x-14,drop.y+33);
context.moveTo(drop.x-14,drop.y+33);
context.lineTo(drop.x-30,drop.y+32);
context.moveTo(drop.x-30,drop.y+32);
context.lineTo(drop.x+140,drop.y+28);
context.closePath();
context.fillStyle = 'yellow';
context.fill();
I'm not sure what I want to do is called. This is the code my professor provided for a cloud.
function drawCloud(cloud) {
context.beginPath();
context.moveTo(cloud.x, cloud.y);
context.bezierCurveTo(cloud.x-40, cloud.y+20, cloud.x-40, cloud.y+70, cloud.x+60, cloud.y+70);
context.bezierCurveTo(cloud.x+80, cloud.y+100, cloud.x+170, cloud.y+100, cloud.x+170, cloud.y+70);
context.bezierCurveTo(cloud.x+250, cloud.y+70, cloud.x+250, cloud.y+40, cloud.x+210, cloud.y+20);
context.bezierCurveTo(cloud.x+260, cloud.y-40, cloud.x+200, cloud.y+50, cloud.x+170, cloud.y-30);
context.bezierCurveTo(cloud.x+150, cloud.y-75, cloud.x+80, cloud.y-60, cloud.x+80, cloud.y-30);
context.bezierCurveTo(cloud.x+30, cloud.y-75, cloud.x-20, cloud.y-60, cloud.x, cloud.y);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.strokeStyle = cloud.color;
context.stroke();
}
I found the shape generator and made this shape
function drawBolt(bolt){
context.beginPath()
context.moveTo(140,28);
context.lineTo(164,28);
context.moveTo(164,28);
context.lineTo(138,53);
context.moveTo(138,53);
context.lineTo(157,53);
context.moveTo(157,53);
context.lineTo(122,81);
context.moveTo(122,81);
context.lineTo(137,82);
context.moveTo(137,82);
context.lineTo(93,105);
context.moveTo(93,105);
context.lineTo(109,87);
context.moveTo(109,87);
context.lineTo(100,87);
context.moveTo(100,87);
context.moveTo(126,61);
context.lineTo(110,60);
context.moveTo(110,60);
context.lineTo(140,28);
context.closePath();
context.fill();
};
She told me that I had to change those points to x,y and I imagine there is math involved? Is there an easy way of doing that?
So how she has (cloud.x-40) I suppose I need bolt.x(?)
Where is a good starting point?
var canvas;
var context;
var shapes = []
var timer;
var timerTwo;
var possibleShapes = ['drop','triangle','square','circle','cloud'];
function Shape(x, y, color) {
this.x = x;
this.y = y;
this.size = Math.random()*20+5;
this.dx = Math.random()*4-2;
this.dy = Math.random()*4-2;
this.color = color;
this.shape = possibleShapes[Math.floor(Math.random()*possibleShapes.length)];
}
function init() {
canvas = document.getElementById('canvas');
context = canvas.getContext("2d");
window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('orientationchange', resizeCanvas, false);
resizeCanvas();
canvas.onclick = function(event) {
handleClick(event.clientX, event.clientY);
};
timer = setInterval(resizeCanvas, 20);
timerTwo = setInterval(newShape, 200);
}
function newShape() {
var x = Math.random() * canvas.width;
var y = Math.random() * canvas.height;
var colors = ["red", "green", "blue", "orange", "purple", "yellow"];
var color = colors[Math.floor(Math.random()*colors.length)];
shapes.push(new Shape(x, y, color));
}
function drawCircle(circle) {
context.beginPath();
context.arc(circle.x, circle.y, circle.size, 0, degreesToRadians(360), true);
context.fillStyle = circle.color;
context.fill();
}
function drawSquare(square) {
context.beginPath();
context.fillStyle = square.color;
context.fillRect(square.x, square.y, square.size, square.size);
}
function drawTriangle(triangle) {
context.beginPath();
context.fillStyle = triangle.color;
context.moveTo(triangle.x+triangle.size,triangle.y);
context.lineTo(triangle.x,triangle.y);
context.lineTo(triangle.x,triangle.y+triangle.size);
context.closePath();
context.fill();
}
function drawCloud(cloud) {
context.beginPath();
context.moveTo(cloud.x, cloud.y);
context.bezierCurveTo(cloud.x-40, cloud.y+20, cloud.x-40, cloud.y+70, cloud.x+60, cloud.y+70);
context.bezierCurveTo(cloud.x+80, cloud.y+100, cloud.x+170, cloud.y+100, cloud.x+170, cloud.y+70);
context.bezierCurveTo(cloud.x+250, cloud.y+70, cloud.x+250, cloud.y+40, cloud.x+210, cloud.y+20);
context.bezierCurveTo(cloud.x+260, cloud.y-40, cloud.x+200, cloud.y+50, cloud.x+170, cloud.y-30);
context.bezierCurveTo(cloud.x+150, cloud.y-75, cloud.x+80, cloud.y-60, cloud.x+80, cloud.y-30);
context.bezierCurveTo(cloud.x+30, cloud.y-75, cloud.x-20, cloud.y-60, cloud.x, cloud.y);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.strokeStyle = cloud.color;
context.stroke();
}
function drawDrop(drop) {
context.beginPath();
context.lineJoin = 'miter';
context.moveTo(drop.x, drop.y);
context.arc(drop.x, drop.y+68, 34.5, 5.75, 3.66, false);
context.quadraticCurveTo(drop.x-3.5, drop.y+15, drop.x, drop.y);
context.closePath();
context.lineWidth = 2;
context.fillStyle = drop.color;
context.fill();
}
function drawText() {
context.fillStyle = 'white';
context.font = 'bold 2em sans-serif';
context.textAlign = 'right';
context.fillText('Art?', canvas.width-40, canvas.height-40);
}
function resizeCanvas() {
canvas.width = window.innerWidth-20;
canvas.height = window.innerHeight-20;
fillBackgroundColor();
for (var i=0; i<shapes.length; i++) {
if (shapes[i].shape == 'square') {
drawSquare(shapes[i]);
} else if (shapes[i].shape == 'circle') {
drawCircle(shapes[i]);
} else if (shapes[i].shape == 'triangle') {
drawTriangle(shapes[i]);
} else if (shapes[i].shape == 'drop') {
drawDrop(shapes[i]);
} else if (shapes[i].shape == 'cloud') {
drawCloud(shapes[i]);
}
if (shapes[i].x + shapes[i].dx > canvas.width || shapes[i].x + shapes[i].dx < 0)
shapes[i].dx = -shapes[i].dx;
if (shapes[i].y + shapes[i].dy > canvas.height || shapes[i].y + shapes[i].dy < 0)
shapes[i].dy = -shapes[i].dy;
shapes[i].x += shapes[i].dx;
shapes[i].y += shapes[i].dy;
}
drawText();
}
function fillBackgroundColor() {
//var colors = ["white", "yellow", "blue", "red"];
//var bgColor = colors[Math.floor(Math.random() * colors.length)];
context.fillStyle = 'black';
context.fillRect(0, 0, canvas.width, canvas.height);
}
function degreesToRadians(degrees) {
//converts from degrees to radians and returns
return (degrees * Math.PI)/180;
}
window.onload = init;
You can translate entire canvas instead of modifying your code.
let's suppose that bolt is an object with x and y as properties.
function drawBolt(bolt){
context.save();
context.translate(bolt.x, bolt.y);
context.beginPath()
context.moveTo(140,28);
context.lineTo(164,28);
context.moveTo(164,28);
context.lineTo(138,53);
context.moveTo(138,53);
context.lineTo(157,53);
context.moveTo(157,53);
context.lineTo(122,81);
context.moveTo(122,81);
context.lineTo(137,82);
context.moveTo(137,82);
context.lineTo(93,105);
context.moveTo(93,105);
context.lineTo(109,87);
context.moveTo(109,87);
context.lineTo(100,87);
context.moveTo(100,87);
context.moveTo(126,61);
context.lineTo(110,60);
context.moveTo(110,60);
context.lineTo(140,28);
context.closePath();
context.fill();
context.restore();
};
This is equivalent to drawing the bolt modifying all the points adding x and y to each of them.
So I have been looking around and trying tutorials but I can't seem to get any collision detection systems to work. If someone would be able to explain what I am doing wrong or any syntax errors that would be great.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bouncing Ball</title>
<style>
#mycanvas {
outline: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="mycanvas" width="1280" height="750"></canvas>
<script>
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var xx = 50;
var yy = 100;
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity+=acceleration;
yy += velocity;
if(yy > 597) {
var temp =0;
temp =velocity/4;
velocity=-temp;
yy = 597;
}
}
function collision(first, second){
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: xx,
y: yy,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(xx, yy, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 300,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX+=3;
}
}
if (keys[37]) {
if (velX > -speed) {
velX--;
}
}
if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
xx += velX;
yy += velY;
physics();
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.rect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fill();
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
console.log('collision');
}
setTimeout(update, 10);
}
update();
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
</script>
</body>
I can only append to what markE already says in his answer (we seem to be working on this simultaneously :) ).
I will first point out a more serious bug in the code:
You are using fill() without a beginPath() first. This will slow down the code loop rapidly. Replace fill() with a fillRect() instead.
Also, there is no need to use clearRect() when the next draw operation fills the entire canvas:
//ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fillRect(0, 0, canvas.width, canvas.height);
You're using global vars xx/yy. One main point of using objects is to avoid global vars. The render method uses the same so it appears to work, but the player's local properties are never updated. Remove global vars and only work with the object's x and y (I would recommend some refactoring so you can pass in the object to the physics() etc. instead of doing global referencing).
var xx = 50;var yy = 100;
To:
var player = {
x: 50, // numbers cannot be referenced, their value
y: 100, // is copied. Use these properties directly instead..
// ...
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height); // and here..
}
}
and
function physics() {
//...
player.y += velocity;
if (player.y > 597) {
//...
player.y = 597;
}
}
and in the loop:
player.x += velX;
player.y += velY;
Add preventDefault() in you key handlers to prevent the key moves to affect the brower's window scroll (not all users have a large screen so the left/right key will also affect the scrolling).
document.body.addEventListener("keydown", function(e) {
e.preventDefault();
...
And of course, use requestAnimationFrame to loop the animation.
I would also recommend using a function object that can be instantiated as you have methods in all of them. With a function object you can prototype the draw() method and share it across all the instances without the need of extra memory (and it's good for the internal optimizer as well). This if you plan to draw more than those three objects.
Updated code
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity += acceleration;
player.y += velocity;
if (player.y > 597) {
var temp = 0;
temp = velocity / 4;
velocity = -temp;
player.y = 597;
}
}
function collision(first, second) {
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: 50,
y: 100,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 300,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX += 3;
}
}
else if (keys[37]) {
if (velX > -speed) {
velX -= 3;
}
}
else if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
player.x += velX;
player.y += velY;
physics();
//ctx.clearRect(0, 0, canvas.width, canvas.height); // not really needed
ctx.fillStyle = "#EEE3B9";
ctx.fillRect(0, 0, canvas.width, canvas.height); // as this clears too...
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
console.log('collision');
}
requestAnimationFrame(update);
}
update();
document.body.addEventListener("keydown", function(e) {
e.preventDefault();
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
e.preventDefault();
keys[e.keyCode] = false;
});
#mycanvas {outline: 1px solid #000;}
<canvas id="mycanvas" width="1280" height="750"></canvas>
There's no problem with your collision function--it will correctly recognize the collision between any 2 un-rotated rectangles.
Visually, your black rect drops to the floor, bounces once or twice and then settles on the floor.
3 issues though...
I do see that your setTimeout is set to trigger every 10ms. That's a bit fast since the display will only refresh about every 1000/60=16.67ms--so your setTimeout should be at least 16.67. Also, You might consider using requestAnimationFrame instead of setTimeout because rAF synchronizes itself with the display and gives better performance.
One design glitch, even if the user constantly holds down the right-key to move the rect towards the bucket as fast as possible, the rect is never given enough "delta X" to hit the bucket.
You are testing collisions with player and bucket but you are not updating the player.x & player.y. Therefore your collision() is only testing the initial player position and not its current position.
// in update()
...
player.x=xx;
player.y=yy;
Demo of refactored code:
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var xx = 50;
var yy = 100;
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity+=acceleration;
yy += velocity;
if(yy > 597) {
var temp =0;
temp =velocity/4;
velocity=-temp;
yy = 597;
}
}
function collision(first, second){
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: xx,
y: yy,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(xx, yy, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 50,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX+=3;
}
}
if (keys[37]) {
if (velX > -speed) {
velX--;
}
}
if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
xx += velX;
yy += velY;
//
player.x=xx;
player.y=yy;
physics();
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.rect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fill();
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
alert('collision when player at:'+player.x+"/"+player.y);
}else{
setTimeout(update, 1000/60*3);
}
}
update();
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
<canvas id="mycanvas" width="1280" height="750"></canvas>
Copy and paste
<html>
<head>
<title> new </title>
<script>
var ctx1;
var ctx;
var balls = [
{x:50, y:50, r:20, m:1, vx:1, vy:1.5},
{x:200, y:80, r:30, m:1, vx:-1, vy:0.3},
];
function start()
{
ctx1 = document.getElementById("ctx");
ctx = ctx1.getContext("2d");
ctx.strokeStyle = "blue";
ctx.lineWidth = 2;
setInterval(draw, 10);
}
function draw()
{
ctx.clearRect(0, 0, ctx1.width, ctx1.height);
for (var a = 0; a < balls.length; a ++)
{
for (var b = 0; b < balls.length; b ++)
{
if (a != b)
{
var distToBalls = Math.sqrt(Math.pow(balls[a].x - balls[b].x, 2) + Math.pow(balls[a].y - balls[b].y, 2));
if (distToBalls <= balls[a].r + balls[b].r)
{
var newVel = getBallCollision(balls[a], balls[b]);
balls[a].vx = newVel.ball1.vx;
balls[a].vy = newVel.ball1.vy;
balls[b].vx = newVel.ball2.vx;
balls[b].vy = newVel.ball2.vy;
balls[a].x += balls[a].vx;
balls[a].y += balls[a].vy;
balls[b].x += balls[b].vx;
balls[b].y += balls[b].vy;
}
}
}
}
for (var a = 0; a < balls.length; a ++)
{
ctx.beginPath();
ctx.arc(balls[a].x, balls[a].y, balls[a].r, 0, Math.PI*2, true);
ctx.fill();
ctx.closePath();
if (balls[a].x <= balls[a].r) balls[a].vx *= -1;
if (balls[a].y <= balls[a].r) balls[a].vy *= -1;
if (balls[a].x >= ctx1.width - balls[a].r) balls[a].vx *= -1;
if (balls[a].y >= ctx1.height - balls[a].r) balls[a].vy *= -1;
balls[a].x += balls[a].vx;
balls[a].y += balls[a].vy;
}
}
function getBallCollision(b1, b2)
{
var dx = b1.x - b2.x;
var dy = b1.y - b2.y;
var dist = Math.sqrt(dx*dx + dy*dy);
if (Math.abs(dy) + Math.abs(dx) != 0 && dist <= b1.r + b2.r)
{
var colAng = Math.atan2(dy, dx);
var sp1 = Math.sqrt(b1.vx*b1.vx + b1.vy*b1.vy);
var sp2 = Math.sqrt(b2.vx*b2.vx + b2.vy*b2.vy);
var dir1 = Math.atan2(b1.vy, b1.vx);
var dir2 = Math.atan2(b2.vy, b2.vx);
var vx1 = sp1 * Math.cos(dir1 - colAng);
var vy1 = sp1 * Math.sin(dir1 - colAng);
var vx2 = sp2 * Math.cos(dir2 - colAng);
var vy2 = sp2 * Math.sin(dir2 - colAng);
var fvx1 = ((b1.m - b2.m) * vx1 + (2 * b2.m) * vx2) / (b1.m + b2.m);
var fvx2 = ((2 * b1.m) * vx1 + (b2.m - b1.m) * vx2) / (b1.m + b2.m);
var fvy1 = vy1;
var fvy2 = vy2;
b1.vx = Math.cos(colAng) * fvx1 + Math.cos(colAng + Math.PI/2) * fvy1;
b1.vy = Math.sin(colAng) * fvx1 + Math.sin(colAng + Math.PI/2) * fvy1;
b2.vx = Math.cos(colAng) * fvx2 + Math.cos(colAng + Math.PI/2) * fvy2;
b2.vy = Math.sin(colAng) * fvx2 + Math.sin(colAng + Math.PI/2) * fvy2;
return { ball1:b1, ball2:b2 };
}
else return false;
}
</script>
</head>
<body onLoad="start();">
<canvas id="ctx" width="500" height="300" style = "border : 2px solid #854125 ;"> </canvas>
</body>
</html>
I have a kineticjs canvas with image upload and text input, both functions are working fine but I can't get the image resize anchors to show... I need to get the image resize anchors to show "onClick" of the image.
any help is much appreciated :)
thanks in advance.
here is the js
var stage = new Kinetic.Stage({
container: 'container',
width: 375,
height: 200
});
var layer = new Kinetic.Layer();
//image loader
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var img = new Image();
img.onload = function(){
layer.add(new Kinetic.Image({
x: 100,
y: 50,
image: img,
width: 200,
height: 130,
draggable: true
}));
text.moveToTop();
stage.draw();
};
console.log(event);
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
// parameters
var resizerRadius = 3;
var rr = resizerRadius * resizerRadius;
// constant
var pi2 = Math.PI * 2;
function draw(img, withAnchors, withBorders) {
// clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw the image
var view = img.view;
ctx.drawImage(img, 0, 0, img.width, img.height, view.left, view.top, view.width, view.height);
// optionally draw the draggable anchors
if (withAnchors) {
drawDragAnchor(view.left, view.top);
drawDragAnchor(view.left + view.width, view.top);
drawDragAnchor(view.left + view.width, view.top + view.height);
drawDragAnchor(view.left, view.top + view.height);
}
// optionally draw the connecting anchor lines
if (withBorders) {
ctx.beginPath();
ctx.rect(view.left, view.top, view.width, view.height);
ctx.stroke();
}
drawText();
}
function drawDragAnchor(x, y) {
ctx.beginPath();
ctx.arc(x, y, resizerRadius, 0, pi2, false);
ctx.closePath();
ctx.fill();
}
function drawText(){
var x = 40,
y = 100;
ctx.font = "bold 20px sans-serif";
ctx.fillStyle = "black";
ctx.fillText($("#textBox").val(), x, y);
}
// -------------------------------------------
// - Hit Testing -
// -------------------------------------------
// return 0,1,2, or 3 if (x,y) hits the respective anchor
// of the given view.
// return -1 if no anchor hit.
function anchorHitTest(view, x, y) {
var dx, dy;
x -= view.left;
y -= view.top;
// top-left
dx = x;
dy = y;
if (dx * dx + dy * dy <= rr) return (0);
// top-right
dx = x - view.width;
dy = y;
if (dx * dx + dy * dy <= rr) return (1);
// bottom-right
dx = x - view.width;
dy = y - view.height;
if (dx * dx + dy * dy <= rr) return (2);
// bottom-left
dx = x;
dy = y - view.height;
if (dx * dx + dy * dy <= rr) return (3);
return (-1);
}
// return true if (x,y) lies within the view
function hitImage(view, x, y) {
x -= view.left;
y -= view.top;
return (x > 0 && x < view.width && y > 0 && y < view.height);
}
// -------------------------------------------
// - Mouse -
// -------------------------------------------
var mousePos = {
x: 0,
y: 0
};
var draggingImage = false;
var startX, startY;
var isDown = false;
var currentImg = null;
var draggingResizer;
function updateMousePos(e) {
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
updateMousePos = function (e) {
mousePos.x = parseInt(e.clientX - offsetX);
mousePos.y = parseInt(e.clientY - offsetY);
};
return updateMousePos(e);
}
function handleMouseDown(e) {
updateMousePos(e);
// here you could make a loop to see which image / anchor was clicked
draggingResizer = anchorHitTest(img.view, mousePos.x, mousePos.y);
draggingImage = draggingResizer < 0 && hitImage(img.view, mousePos.x, mousePos.y);
//
if (draggingResizer<0 && !draggingImage) return;
startX = mousePos.x;
startY = mousePos.y;
currentImg = img;
}
function handleMouseUp(e) {
if (!currentImg) return;
draggingResizer = -1;
draggingImage = false;
draw(currentImg, true, false);
currentImg = null;
}
function handleMouseOut(e) {
handleMouseUp(e);
}
function handleMouseMove(e) {
if (!currentImg) return;
updateMousePos(e);
var view = currentImg.view;
if (draggingResizer > -1) {
var oldView = {
left: view.left,
top: view.top,
width: view.width,
height: view.height
};
// resize the image
switch (draggingResizer) {
case 0:
cl('ttoo');
//top-left
view.left = mousePos.x;
view.top = mousePos.y;
view.width = oldView.left + oldView.width - mousePos.x;
view.height = oldView.top + oldView.height - mousePos.y;
break;
case 1:
//top-right
// view.left unchanged
view.top = mousePos.y;
view.width = mousePos.x - oldView.left;
view.height = oldView.top + oldView.height - mousePos.y;
break;
case 2:
//bottom-right
view.width = mousePos.x - oldView.left;
view.height = mousePos.y - oldView.top;
break;
case 3:
//bottom-left
view.left = mousePos.x;
view.width = oldView.left + oldView.width - mousePos.x;
view.height = mousePos.y - (oldView.top);
break;
}
if (view.width < 25) view.width = 25;
if (view.height < 25) view.height = 25;
// redraw the image with resizing anchors
draw(currentImg, true, true);
} else if (draggingImage) {
imageClick = false;
// move the image by the amount of the latest drag
var dx = mousePos.x - startX;
var dy = mousePos.y - startY;
view.left += dx;
view.top += dy;
// reset the startXY for next time
startX = mousePos.x;
startY = mousePos.y;
// redraw the image with border
draw(currentImg, false, true);
}
}
var text = new Kinetic.Text({
x: 20,
y: 30,
text: '',
fontSize: '30',
fontFamily: 'Calibri',
fill: 'black',
draggable: true
});
stage.add(layer);
layer.add(text);
document.getElementById("textBox").addEventListener("keyup", function () {
text.setText(this.value);
layer.draw();
}, true);
document.getElementById("textSize").addEventListener("change", function () {
var size = this.value;
text.fontSize(size);
layer.draw();
}, true);
document.getElementById("fontFamily").addEventListener("change", function () {
var font = this.value;
text.fontFamily(font);
layer.draw();
}, true);
document.getElementById("fontStyle").addEventListener("change", function () {
var style = this.value;
text.fontStyle(style);
layer.draw();
}, true);
document.getElementById("fill").addEventListener("change", function () {
var colour = this.value;
text.fill(colour);
layer.draw();
}, true);
$("#canvas").mousedown(function (e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function (e) {
handleMouseMove(e);
});
$("#canvas").mouseup(function (e) {
handleMouseUp(e);
});
$("#canvas").mouseout(function (e) {
handleMouseOut(e);
});
// utility
function cl() {
console.log.apply(console, arguments);
}
can provide jsFiddle if needed :)
You're trying to mix KineticJS with html canvas drawing commands.
That combination doesn't work because KineticJS does its magic by taking over the canvas--leaving no ability to call native canvas commands like context.beginPath.
// these 2 don't play together
... new Kinetic.Image ...
... ctx.beginPath ...
Anyway, Here's the answer to your question (in case you choose KineticJS for your project)
Kinetic.Image can be asked to execute a function when the image is clicked like this:
var image=new Kinetic.Image({
x: 100,
y: 50,
image: img,
width: 200,
height: 130,
draggable: true
}));
image.on("click",function(){
// The image was clicked
// Show your anchors now
});
layer.add(image);
[ Addition: Example of Kinetic.Image resizing ]
I don't like the overhead and complexity of maintaining anchors to resize Kinetic.Images.
Here's an example that lets you drag on the right side of the image to scale it proportionally:
http://jsfiddle.net/m1erickson/p8bpC/
You could modify this code to add cosmetic resizing grabbers (the grabbers are not necessary, but if you prefer the "anchor" look, you can add them).
You can refer to this question, the answers are guided and constructive, and contain a jsfiddle with the exact same behavior that you need.
Kinetic JS - how do you hide all the anchors for a given group ID
I'm having trouble keeping one object on my canvas. The initially drawn box rendered it in the correct position, but it disappears when I drag it:
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
eraseAllButton = document.getElementById('eraseAllButton'),
strokeStyleSelect = document.getElementById('strokeStyleSelect'),
guidewireCheckbox = document.getElementById('guidewireCheckbox'),
drawingSurfaceImageData,
mousedown = {},
rubberbandRect = {},
dragging = false,
guidewires = guidewireCheckbox.checked,
w = 90, h = 90;
count = 0;
boxesXCo = 0;
boxesYCo = 0;
i = 0;
// Functions..........................................................
function drawGrid(color, stepx, stepy) {
context.save()
context.strokeStyle = color;
context.lineWidth = 0.5;
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {
context.beginPath();
context.moveTo(i, 0);
context.lineTo(i, context.canvas.height);
context.stroke();
}
for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {
context.beginPath();
context.moveTo(0, i);
context.lineTo(context.canvas.width, i);
context.stroke();
}
context.restore();
}
function windowToCanvas(x, y) {
var bbox = canvas.getBoundingClientRect();
return { x: x - bbox.left * (canvas.width / bbox.width),
y: y - bbox.top * (canvas.height / bbox.height) };
}
// Save and restore drawing surface...................................
function saveDrawingSurface() {
drawingSurfaceImageData = context.getImageData(0, 0,
canvas.width,
canvas.height);
}
function restoreDrawingSurface() {
context.putImageData(drawingSurfaceImageData, 0, 0);
}
function drawRubberbandShape(loc) {
context.beginPath();
context.moveTo(mousedown.x, mousedown.y);
//context.lineTo(loc.x, loc.y);
context.stroke();
}
function updateRubberband(loc) {
//updateRubberbandRectangle(loc);
context.restore();
drawRubberbandShape(loc);
}
// Guidewires.........................................................
function drawHorizontalLine (y) {
context.beginPath();
context.moveTo(0,y+0.5);
context.lineTo(context.canvas.width,y+0.5);
context.stroke();
}
function drawVerticalLine (x) {
context.beginPath();
context.moveTo(x+0.5,0);
context.lineTo(x+0.5,context.canvas.height);
context.stroke();
}
function drawGuidewires(x, y) {
context.save();
context.strokeStyle = 'rgba(0,0,230,0.4)';
context.lineWidth = 0.5;
drawVerticalLine(x);
drawHorizontalLine(y);
context.restore();
}
// Canvas event handlers..............................................
canvas.onmousedown = function (e) {
var loc = windowToCanvas(e.clientX, e.clientY);
e.preventDefault(); // prevent cursor change
context.restore();
saveDrawingSurface();
mousedown.x = loc.x;
mousedown.y = loc.y;
dragging = true;
if (i ==0)
i++;
else if(((mousedown.x<=(boxesXCo+w)&&(mousedown.x>=boxesXCo))&&
((mousedown.y<=(boxesYCo+h)&&(mousedown.y>=boxesYCo)))))
i--;
};
canvas.onmousemove = function (e) {
var loc;
if (dragging) {
e.preventDefault(); // prevent selections
loc = windowToCanvas(e.clientX, e.clientY);
restoreDrawingSurface();
//updateRubberband(loc);
if(guidewires) {
drawGuidewires(loc.x, loc.y);
}
}
if(((mousedown.x<=(boxesXCo+w)&&(mousedown.x>=boxesXCo))&&
((mousedown.y<=(boxesYCo+h)&&(mousedown.y>=boxesYCo))))
&& (dragging)&&(i == 1 )){
context.restore();
restoreDrawingSurface();
context.fillStyle = strokeStyleSelect.value;
context.fillRect(e.clientX,e.clientY,w,h);
};
//Trying to implement moving shapes but need to store values of drawn objs
};
canvas.onmouseup = function (e) {
loc = windowToCanvas(e.clientX, e.clientY);
restoreDrawingSurface();
updateRubberband(loc);
dragging = false;
if(i == 0);
else {
saveDrawingSurface();
restoreDrawingSurface();
context.fillRect(e.clientX,e.clientY, w, h);
boxesXCo = e.clientX;
boxesYCo = e.clientY;
context.restore();
i++;}
/*else if(i == 1)
{
context.restore();
}*/
//context.fillRect(mousedown.x,mousedown.y,w,h,"FF0982");
};
// Controls event handlers.......................................
eraseAllButton.onclick = function (e) {
context.clearRect(0, 0, canvas.width, canvas.height);
drawGrid('lightgray', 10, 10);
saveDrawingSurface();
count =0;
context.restore();
};
strokeStyleSelect.onchange = function (e) {
context.strokeStyle = strokeStyleSelect.value;
context.fillStyle = strokeStyleSelect.value;
};
guidewireCheckbox.onchange = function (e) {
guidewires = guidewireCheckbox.checked;
};
// Initialization................................................
context.strokeStyle = strokeStyleSelect.value;
context.fillStyle = strokeStyleSelect.value;
drawGrid('lightgray', 10, 10);
//context.fillRect(mousedown.x,mousedown.y,(mousedown.x+50),(mousedown.x+50),"FF0982");
//context.drawRect(mousedown.x-50,mousedown.y-50,mousedown.x+50,mousedown.y+50);
thanx again
Rather than drawing to canvas on each mouse movement, use window.requestFrameAnimation to draw constantly.
At a guess, I'd assume either the browser rendering is interfering or the coordinates are out but I can't run your code to make sure.
I've written some pseudo code that shows what I do for rendering things. You'll need to implement this for yourself, it won't run out of the box, it's just intended as a guide.
var Box = function() {
};
Box.prototype = {
x: 0,
y: 0,
draw: function (canvas) {
// draw the item on the canvas
}
};
var box = new Box();
window.requestAnimationFrame(function() {
box.draw(canvas);
window.requestAnimationFrame();
});
canvas.onmousemove = function(e) {
if (dragging) {
box.x = e.clientX;
box.y = e.clientY;
}
}