Javascript make an image bounce around screen - javascript

I have made code for a bouncing ball (using the arc() method on a canvas). I am wondering how to make an image bounce around the screen. Here is my previous code (note that the launchBall() function is going to be the function that runs the bouncing image):
<!DOCTYPE HTML>
<html>
<body onload="startBall()" oncontextmenu="return false;" style="cursor: none; overflow: hidden;">
<center>
<div id="div" style="width: 1600px; height: 700px; border: 2px solid #000000; background-color: grey;">
<br>
<img draggable="false"id="image" style="position: absolute;" width="50" height="50"src="http://www.clker.com/cliparts/b/a/b/0/1207156679935151925noxin_crosshairs.svg.hi.png"/>
</div>
<center>
<p>Score: <a>0</a></p>
</center>
<script>
var dx = 3;
var dy = 3;
var x = 100;
var y = 100;
var radius = 20;
var interval;
function startBall(){
interval = setInterval(launchBall, 20);
}
function launchBall(){
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, 1275, 695);
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
document.getElementById
if(x<20 || x>1255) dx=-dx;
if(y<20 || y>675) dy=-dy;
x = x + dx;
y = y + dy;
}
document.getElementById("div").onmousemove = function(e) {
document.getElementById("image").style.top = e.pageY -25 + "px";
document.getElementById("image").style.left = e.pageX -25 +"px";
}
</script>
</body>
</html>

Related

Gecko - CSS layout border radius - Javascript conversion

I'm trying to get the exact formula in order to compute CSS border-radius property in a canvas. I've already tried and have an example in javascript (see below), but with no success.
Its seems that the browser is still adding some adaptations in order to ajust the borders. And i'm unable to identify them. So i've checked the sources of the Gecko layout engine, but i'm not sure where i can find this formula (in the sources).
It may be in layout/painting/nsCSSRenderingBorders.cpp, but there's still a lot of code and it's C++ (i've no skills into that language)
See Gecko repository : https://github.com/mozilla/gecko-dev
So, if anyone could help me in order to achieve this adaptation, or give me the blocks of code which are computing border-radius "arcs, orientation ?" (in gecko) i'll be able to do that.
Javascript/HTML snippet (current, close from good adaptation)
(RED SHAPE = Canvas shape, GREEN SHAPE = HTML shape)
I'm using this function to draw the shape : ctx.constructor.prototype.fillRoundedRect
And this function in order to get close from the browser adaptation : correctRadius
As you will see, im getting this result when TopLEFT, TopRight and BottomLEFT sliders are at max value. The browser (green) is rendering it perfectly, and mine is bad (red).
See snippet below
// Ctx
var ctx = document.getElementById("rounded-rect").getContext("2d");
function correctRadius(r, w, h) {
if (r.tl + r.tr > w) {
r.tl -= (r.tl + r.tr - w) / 2;
r.tr = w - r.tl;
}
if (r.bl + r.br > w) {
r.br -= (r.br + r.bl - w) / 2;
r.bl = w - r.br;
}
if (r.tl + r.bl > h) {
r.tl -= (r.tl + r.bl - h) / 2;
r.bl = h - r.tl;
}
if (r.tr + r.br > h) {
r.tr -= (r.tr + r.br - h) / 2;
r.br = h - r.tr;
}
}
//Round rect func
ctx.constructor.prototype.fillRoundedRect =
function (xx, yy, ww, hh, rad, fill, stroke) {
correctRadius(rad, ww, hh);
if (typeof(rad) === "undefined") rad = 5;
this.beginPath();
this.moveTo(xx, yy);
this.arcTo(xx + ww, yy, xx + ww, yy + hh, rad.tr);
this.arcTo(xx + ww, yy + hh, xx, yy + hh, rad.br);
this.arcTo(xx, yy + hh, xx, yy, rad.bl);
this.arcTo(xx, yy, xx + ww, yy, rad.tl);
if (stroke) this.stroke(); // Default to no stroke
if (fill || typeof(fill) === "undefined") this.fill(); // Default to fill
};
ctx.fillStyle = "red";
ctx.strokeStyle = "#ddf";
var copy = document.getElementById('copy');
var tl = document.getElementById('tl');
var tr = document.getElementById('tr');
var bl = document.getElementById('bl');
var br = document.getElementById('br');
var off = document.getElementById('off');
function test() {
ctx.clearRect(0, 0, 600, 500);
/* 1.Top left */
/* 2. Top right */
/* 3. Bottom right */
/* 4. Bottom left */
var borders = [tl.value, tr.value, br.value, bl.value].join('px ') + 'px';
copy.style.borderRadius = borders;
var copyRad = borders.replace(/px/g, '').split(' ').map(function (a) {
return parseInt(a)
});
var rad = {
tl: copyRad[0],
tr: copyRad[1],
br: copyRad[2],
bl: copyRad[3]
};
var o = +off.value;
ctx.fillRoundedRect(15 + o, 15 + o, 100, 100, rad);
}
tl.oninput = test;
tr.oninput = test;
bl.oninput = test;
br.oninput = test;
off.oninput = test;
test();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html, body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div style="display:inline-block; position: absolute;
left:120px;top:120px; width: 100px; height: 100px; background:green;
border-radius: 10px 5px 10px 20px;" id="copy">
</div>
<canvas style="display: inline-block; position: absolute; zindex:0; left:0; top:0;" id="rounded-rect" width="600" height="500">
</canvas>
<div style="top: 300px; position:absolute; z-index: 1;">
<label>
Top left
<input type="range" min="1" max="100" value="0" class="slider" id="tl"></label><br/>
<label>
Top right
<input type="range" min="1" max="100" value="0" class="slider" id="tr"></label><br/>
<label>
Bottom left
<input type="range" min="1" max="100" value="0" class="slider" id="bl"></label><br/>
<label>
Bottom right
<input type="range" min="1" max="100" value="0" class="slider" id="br"></label><br/>
<label>
Offset
<input type="range" min="1" max="200" value="0" class="slider" id="off"></label><br/>
</div>
</body>
</html>
The issue is with your correctRadius function. As you can see you are re-calculating value more than once which is incorrect.
Let's take an example with TopLeft, TopRight and BottomLeft set at max values (100px):
1) You will consider the first condition and you will update your values like this:
TopLeft = 50px | TopRight = 50px (these are correct values)
2) Now you will consider the third condition as you have TL+TB (100px + 50px) > h (100px) and you will update the values like this:
TopLeft = 25px | BottomLeft 75px (these are wrong values and the correct ones should be 50px for both)
So you don't have to calculate values separately, you should consider all of them and do only one calculation for each side depending on initial values.
The idea is to consider the max value of the difference between two adjacent side. Let's consider the same example above and make 3 different values like this:
TL = 100px | TR = 90px | BL = 100px | BR = 0px
TL is adjacent to TR and BL:
Considering TR we will have 190px > 100px and thus TL = 45px
Considering BL we will have 200px > 100px and this TL = 50px
So we should consider the max value which is 50px. We do the same for the other sides.
Here is the full code:
// Ctx
var ctx = document.getElementById("rounded-rect").getContext("2d");
function correctRadius(r, w, h) {
var tl=r.tl;
var tr=r.tr;
var br=r.br;
var bl=r.bl;
r.tl -= Math.max(Math.max((tl + tr - w)/2,0),
Math.max((tl + bl - h)/2,0));
r.tr -= Math.max(Math.max((tr + tl - w)/2,0),
Math.max((tr + br - h)/2,0));
r.br -= Math.max(Math.max((br + bl - w)/2,0),
Math.max((br + tr - h)/2,0));
r.bl -= Math.max(Math.max((bl + br - w)/2,0),
Math.max((bl + tl - h)/2,0));
}
//Round rect func
ctx.constructor.prototype.fillRoundedRect =
function (xx, yy, ww, hh, rad, fill, stroke) {
correctRadius(rad, ww, hh);
if (typeof(rad) === "undefined") rad = 5;
this.beginPath();
this.moveTo(xx, yy);
this.arcTo(xx + ww, yy, xx + ww, yy + hh, rad.tr);
this.arcTo(xx + ww, yy + hh, xx, yy + hh, rad.br);
this.arcTo(xx, yy + hh, xx, yy, rad.bl);
this.arcTo(xx, yy, xx + ww, yy, rad.tl);
if (stroke) this.stroke(); // Default to no stroke
if (fill || typeof(fill) === "undefined") this.fill(); // Default to fill
};
ctx.fillStyle = "red";
ctx.strokeStyle = "#ddf";
var copy = document.getElementById('copy');
var tl = document.getElementById('tl');
var tr = document.getElementById('tr');
var bl = document.getElementById('bl');
var br = document.getElementById('br');
var off = document.getElementById('off');
function test() {
ctx.clearRect(0, 0, 600, 500);
/* 1.Top left */
/* 2. Top right */
/* 3. Bottom right */
/* 4. Bottom left */
var borders = [tl.value, tr.value, br.value, bl.value].join('px ') + 'px';
copy.style.borderRadius = borders;
var copyRad = borders.replace(/px/g, '').split(' ').map(function (a) {
return parseInt(a)
});
var rad = {
tl: copyRad[0],
tr: copyRad[1],
br: copyRad[2],
bl: copyRad[3]
};
var o = +off.value;
ctx.fillRoundedRect(15 + o, 15 + o, 100, 100, rad);
}
tl.oninput = test;
tr.oninput = test;
bl.oninput = test;
br.oninput = test;
off.oninput = test;
test();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html, body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div style="display:inline-block; position: absolute;
left:120px;top:120px; width: 100px; height: 100px; background:green;
border-radius: 10px 5px 10px 20px;" id="copy">
</div>
<canvas style="display: inline-block; position: absolute; zindex:0; left:0; top:0;" id="rounded-rect" width="600" height="500">
</canvas>
<div style="top: 300px; position:absolute; z-index: 1;">
<label>
Top left
<input type="range" min="1" max="100" value="0" class="slider" id="tl"></label><br/>
<label>
Top right
<input type="range" min="1" max="100" value="0" class="slider" id="tr"></label><br/>
<label>
Bottom left
<input type="range" min="1" max="100" value="0" class="slider" id="bl"></label><br/>
<label>
Bottom right
<input type="range" min="1" max="100" value="0" class="slider" id="br"></label><br/>
<label>
Offset
<input type="range" min="1" max="200" value="0" class="slider" id="off"></label><br/>
</div>
</body>
</html>

Draw More Arc Canvas

Hello People I'd Like to Know How to Draw More Arc Inside My Canvas, What I Need to Draw This circles:
So I Write This Responsive Code to Make my Canvas is Responsive:
var myCanvas = document.getElementById('myCanvas');
var ctx = myCanvas.getContext('2d');
var centerX = myCanvas.width / 2;
var centerY = myCanvas.height / 2;
var borderWidth = 20;
var borderColor = '#2DC36A';
var radius = (myCanvas.width / 2) - (borderWidth / 2);
// days arc canvas background
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
ctx.lineWidth = borderWidth;
ctx.strokeStyle = borderColor;
ctx.stroke();
ctx.closePath();
// Make Canvas Responsive
function makeResponsive() {
var containerWidth = $('.progress-nested').width();
$('.progress-nested').height(containerWidth);
var canvasElements = ['#myCanvas'];
$('#myCanvas').width(containerWidth).height(containerWidth);
}
makeResponsive(); // Make Canvas Responsive in Document ready
$(window).resize(function () {
makeResponsive(); // Make Canvas Responsive in Window Resize
});
#progress {
width: 100%;
padding: 5px;
}
.progress-nested{
position:relative;
border-radius:50%;
}
canvas {
display:block;
position:absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div id="progress">
<div class="container">
<div class="row">
<div class="col-xs-3 col-md-2 col-md-offset-2">
<div class="progress-nested">
<canvas id="myCanvas" width="250" height="250"></canvas>
</div>
</div>
</div>
</div>
</div>
Note: Please Run Code Snippet In Full Page

Trying to draw shapes which are selected from toolbar at the mouse position-HTML5 CANVAS

Hey guys i'm trying to create an interactive app whereby users can select the shape they want and then click anywhere on the canvas and the shape appears at that position. I've been able to do it for one shape only so far. Here's the code:
<!DOCTYPE html>
<html>
<head>
<script>
function initiateCanvasRectangle()
{
var ctx = document.getElementById('myCanvas').getContext('2d');
ctx.canvas.addEventListener('mousemove', function(event) {
var mouseX = event.clientX - ctx.canvas.offsetLeft;
var mouseY = event.clientY - ctx.canvas.offsetTop;
});
ctx.canvas.addEventListener('click', function(event) {
var mouseX = event.clientX - ctx.canvas.offsetLeft;
var mouseY = event.clientY - ctx.canvas.offsetTop;
ctx.fillRect(mouseX,mouseY,100,50);
});
}
function initiateCanvasCircle()
{
var ctx = document.getElementById('myCanvas').getContext('2d');
ctx.canvas.addEventListener('mousemove', function(event) {
var mouseX = event.clientX - ctx.canvas.offsetLeft;
var mouseY = event.clientY - ctx.canvas.offsetTop;
});
ctx.canvas.addEventListener('click', function(event) {
var mouseX = event.clientX - ctx.canvas.offsetLeft;
var mouseY = event.clientY - ctx.canvas.offsetTop;
ctx.beginPath();
ctx.arc(mouseX, mouseY, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'green';
ctx.fill();
});
}
function rect(){ //so that the function is triggered only when the user selects the shape
window.addEventListener('click', function(event) {
initiateCanvasRectangle();
});
}
function drawRect()
{
rect();
}
function circle(){ //as from here the code is not working
window.addEventListener('click', function(event) {
initiateCanvasCircle();
});
}
function drawCircle()
{
circle();
}
</script>
<style>
BUTTON.rect {
padding: 8px 8px 8px 32px;
font-family: Arial, Verdana;
background-color: white;
border:2px solid black;
}
#tbl {
border-collapse:collapse;
}
</style>
</head>
<body>
<div align="left">
<table border="1" id="tbl" width="1100" height="100">
<div align="right">
<tr><td><button class="circle" onclick="drawCircle(); return true;" style="padding:20px 40px 20px 40px;">Circle</button>
</td>
<td>
<button class="rect" onclick="drawRect(); return true;" style="padding:20px 40px 20px 40px;"></button>
</td></tr>
</div>
</table>
<p>
<canvas id="myCanvas" width="1100" height="400" style="border:solid 1px black;"></canvas>
</div>
</body>
</html>
When i click on the button for the rectangle it works fine but i can't seem to draw the circle when i click on its button. Is there any mistake in my codes?
What i created so far is only for trying purposes so please disregard the look of the page.
Any help will be much appreciated. Thanks.
You never define radius variable used in this line:
ctx.arc(mouseX, mouseY, radius, 0, 2 * Math.PI, false);
Set it to some value like 50, and it will work.
Demo: http://plnkr.co/edit/8eUT0hRXA40K53Dy0xDl?p=preview

Why fill() property overwittern in canvas?

I am learner html5 canvas
When I try to draw 2 circle (a circle within a circle).
When I draw a circle and fill it, it works.
when I draw second circle and fill it. it turns into first circle with second fill style.
What I try to create is a orange circle in a grey circle.
I tries many time to solve this but by each way it get problem..
Please check my code and let me know if i am wrong or what to do to fix this problem.
I have following code
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"> </script>
<style>
body{
}
#mycanvas{
border:1px solid #000;
margin:0px auto;
display:block;
}
#mycanvas1{
border:1px solid #000;
margin:0px auto;
display:block;
}
</style>
<body>
<canvas id="mycanvas" width="200" height="200">
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas id="mycanvas1" width="200" height="200">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script type="text/javascript">
var c = document.getElementById("mycanvas");
var b = document.getElementById("mycanvas1");
var d = document.getElementById("mycanvas1");
var ctx = c.getContext("2d");
var ctx1 = b.getContext("2d");
var ctx2 = d.getContext("2d");
ctx.fillStyle = "#bddfb3";
ctx.fillRect(0,0,200,200);
ctx.moveTo(0,0);
ctx.lineTo(200,200);
ctx.stroke();
ctx1.fillStyle = "#f1b147";
ctx1.arc(100,100,80,0,360);
ctx1.fill();
ctx2.fillStyle = "#222";
ctx2.arc(100,100,50,45,180);
ctx2.fill();
ctx1.fillStyle="#fff";
ctx1.font="72px Arial";
ctx1.fillText("i",90,125);
</script>
</body>
</html>
This is a easy way to draw a orange circle inside a grey circle on canvas.
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
// orange circle
ctx.beginPath();
// centerX, centerY, radius, start angle, end angle, counterclockwise
ctx.arc(100, 100, 50, 0, 2 * Math.PI, false);
ctx.fillStyle = 'orange';
ctx.fill();
// grey circle
ctx.lineWidth = 25;
ctx.strokeStyle = 'grey';
ctx.stroke();
<canvas id="canvas" width="500" height="250"></canvas>

Jquery image hover, click and grayscale effect with tab and caption

i want my image get black white (grayscale) after i hover they will change to the color. it is already sucses, but i want if i click image they will change color, and show content in the div i already add .click .dblclick and .toogke function but always change image to the black and white here are the code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Tabbed Navigation</title>
<style type="text/css">
.item {
width: auto;
margin: 0 0 0 0;
float: left;
}
.item.first {
clear: left;
margin-left: 0;
}
.item img {
opacity:0;
}
.wrapper{
float:left; /* important */
position:relative; /* important(so we can absolutely position the description div */
margin-right: 20px
}
.description{
position:absolute; /* absolute position (so we can position it where we want)*/
bottom:50px; /* position will be on bottom */
width:100%;
/* styling bellow */
background-color:black;
font-family: 'tahoma';
font-size:15px;
color:white;
opacity:0.6; /* transparency */
filter:alpha(opacity=60); /* IE transparency */
z-index: 9999;
}
p.description_content{
padding:5px;
margin:0px;
}
.item img a:active {
background-image: url(images/icondock.jpg);
}
</style>
<script src="jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
// $(".item img").css({"display":"none");
// On window load. This waits until images have loaded which is essential
$(window).load(function(){
// Fade in images so there isn't a color "pop" document load and then on window load
$(".item img").animate({opacity:1},500);
// clone image
$('.item img').each(function(){
var el = $(this);
el.css({"position":"absolute"}).wrap("<div class='img_wrapper' style='display: inline-block'>").clone().addClass('img_grayscale').css({"position":"absolute","z-index":"998","opacity":"0"}).insertBefore(el).queue(function(){
var el = $(this);
el.parent().css({"width":this.width,"height":this.height});
el.dequeue();
});
this.src = grayscale(this.src);
});
// Fade image
$('.item img').mouseover(function(){
$(this).parent().find('img:first').stop().animate({opacity:1}, 500);
})
$('.img_grayscale').mouseout(function(){
$(this).stop().animate({opacity:0}, 500);
});
});
// Grayscale w canvas method
function grayscale(src){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var imgObj = new Image();
imgObj.src = src;
canvas.width = imgObj.width;
canvas.height = imgObj.height;
ctx.drawImage(imgObj, 0, 0);
var imgPixels = ctx.getImageData(0, 0, canvas.width, canvas.height);
for(var y = 0; y < imgPixels.height; y++){
for(var x = 0; x < imgPixels.width; x++){
var i = (y * 4) * imgPixels.width + x * 4;
var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}
ctx.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
return canvas.toDataURL();
}
</script>
</head>
<body>
<div class='wrapper'>
<div class="item">
<img src="images/icondock.jpg" />
</div>
<div class="description">
<p class="description_content">The pack, the basic The pack, the basic More » </p>
</div>
</div>
<div class='wrapper'>
<div class="item">
<img src="images/koifish.jpg" />
</div>
<div class="description">
<p class="description_content">The pack, the basic The pack, the basic More » </p>
</div>
</div>
<div class='wrapper'>
<div class="item">
<img src="images/sakura.jpg" />
</div>
<div class="description">
<p class="description_content">The pack, the basic The pack, the basic More » </p>
</div>
</div>
</body>
</html>
if it is so hard you can use 2 images grayscale and color
javascript:
$(function(){
var canv = document.createElement('canvas'),
ctx = canv.getContext('2d');
canv.style.cssText = "position:absolute;left:-10000px;";
document.body.appendChild( canv );
function getGrayScale(src, el ){
$("<img src=\""+src+"\" />").appendTo("body").bind("load", function ( ) {
var w = canv.width = this.offsetWidth,
h = canv.height = this.offsetHeight;
ctx.drawImage( this, 0, 0);
var imgPixels = ctx.getImageData(0, 0, w, h);
for(var y = 0; y < imgPixels.height; y++){
for(var x = 0; x < imgPixels.width; x++){
var i = (y * 4) * imgPixels.width + x * 4;
var avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}
ctx.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
$("<img class = \"img_grayscale\" src=\""+ canv.toDataURL() +"\" alt=\"\" />")
.insertBefore(el)
$(this).remove();
})
}
$(".item img").each(function(){
getGrayScale(this.src, $(this));
})
$(".item").delegate( ".img_grayscale", "mouseenter", function ( ) {
$(this).stop().animate({opacity:0}, 500)
}).delegate( ".img_grayscale","mouseout", function(){
$(this).stop().animate({opacity:1}, 500);
}).delegate( ".img_grayscale","click", function(){
$(this).remove();
});
});
add css:
.img_grayscale{ position:absolute;top:0;left:0;}
remove css:
.item img {opacity:0;}
i cant figure out what's wrong but this seems work as you expect

Categories