Writing a simple script to have two buttons. One button animates a "painting" feature where rectangles follow the cursor around the canvas. The other button would display a rectangle that follows the canvas but doesn't leave a trail like the other. I have the buttons linked to do different functions. Right now the follow button doesn't work, it does clear the canvas but it still allows you to paint. It seems that the paint function is still running after I hit the follow button. Any help is appreciated.
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Canvas</title>
</head>
<body>
<input type="button" value="Paint" onclick="isPaint()">
<input type="button" value="Follow" onclick="isFollow()">
<canvas id="myCanvas" width="500" height="500"></canvas>
<script>
function isPaint(){
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
//change draw color
ctx.fillStyle = "#FF0000";
ctx.clearRect(0,0,500,500);
canvas.addEventListener("mousemove", function(event) {
ctx.fillRect(event.x,event.y,10,10);
})
}
function isFollow(){
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
//change draw color
ctx.fillStyle = "#FF0000";
ctx.clearRect(0,0,500,500);
}
</script>
</body>
</html>
Work for me : http://jsfiddle.net/XF7m4/1/
Using document.getElementById("paint").onclick= function (){
PS :And think to remove the mousemouse listener ;)
To achieve what you are trying to do you will need to enhance your code a little more.
The main idea is to bind the mousemove event only once and clear the canvas if it is to behave like a follow.
Try using the following code:
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Canvas</title>
</head>
<body>
<input type="button" value="Paint" onclick="CanvasPainter.paint()" />
<input type="button" value="Follow" onclick="CanvasPainter.follow()" />
<canvas id="myCanvas" width="500" height="500"></canvas>
<script type="text/javascript">
(function () {
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
//change draw color
ctx.fillStyle = "#FF0000";
var CanvasPainter = {
isPaint: false,
isFollow: false,
paint: function () {
this.isPaint = true;
this.isFollow = false;
return;
},
follow: function () {
this.isPaint = false;
this.isFollow = true;
return;
}
};
window.CanvasPainter = CanvasPainter;
canvas.addEventListener("mousemove", function (event) {
if (CanvasPainter.isPaint || CanvasPainter.isFollow) {
if (CanvasPainter.isFollow) {
// Clear canvas on every mousemove if it is a follow
ctx.clearRect(0, 0, 500, 500);
}
ctx.fillRect(event.x, event.y, 10, 10);
}
return;
});
return;
})();
</script>
</body>
</html>
Hope this helps!
Your isPaint() function is adding an event listener for "mousemove" to the canvas, but it isn't getting removed in the isFollow() function. If you remove your listener in the isFollow() function this should fix your problem.
Related
I have two problems: how can I draw rectangles with mouse o html canvas, and why isn't my timer showing up.
I have tried every code in here but nothing seems to work. Thank you!
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Canvas Resize</title>
<style>
canvas {
border: 1px solid black;
}
body {
margin: 0px;
}
</style>
</head>
<body>
<canvas></canvas>
<p id="timer"></p>
<script src="canvas.js"></script>
</body>
</html>
JAVASCRIPT
var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var c = canvas.getContext('2d');
//TIMER
var timer = document.getElementById('timer');
var counter = 0;
function setup(){
timer = createP('timer');
setInterval(timeIt, 1);
}
function timeIt (){
timer.html(counter);
counter+=134;
}
Here's the fiddle
https://jsfiddle.net/rita24/0vLwj3go/2/
Thank you!
For the canvas part, you can just add the event listener to keep track on the mouseup, mousemove and mousedown event.
canvas.addEventListener("mousedown", function (e) {
drawing = true;
lastPos = getMousePos(canvas, e);
}, false);
canvas.addEventListener("mouseup", function (e) {
drawing = false;
}, false);
canvas.addEventListener("mousemove", function (e) {
mousePos = getMousePos(canvas, e);
}, false);
// Get the position of the mouse relative to the canvas
function getMousePos(canvasDom, mouseEvent) {
var rect = canvasDom.getBoundingClientRect();
return {
x: mouseEvent.clientX - rect.left,
y: mouseEvent.clientY - rect.top
};
}
This will help you create the rectangle on canvas.
ctx.rect(mousePos.x,mousePos.y,lastPos.x-mousePos.x,lastPos.y-mousePos.y);
ctx.stroke();
You can check this out on how to work with mouse drawing on the canvas: http://bencentra.com/code/2014/12/05/html5-canvas-touch-events.html
For the timer part, you haven't called the setup() function and you are using jQuery html() function to setup the text inside the p element. Use .innerHTML to change the text inside the p element.
Here is the updated link for your JSfiddle: https://jsfiddle.net/0vLwj3go/7/
Hope this can help!
Elvis' answer is great, but since I had already started mine this morning, I'll post it anyway.
For one thing, you aren't calling setup() anywhere, so the timer never gets set and the timer <p> never gets any content. Here's my jsfiddle, which is very similar to Elvis', but shows the timer without scrolling, and includes an example of how to animate the drawing of rectangles.
I am getting the following Error
Error: Uncaught TypeError: Cannot read property 'innerHTML' of null
at script.js:1
I have tried everything I could think of but nothing works.
var canvas = document.getElementById("can").innerHTML;
var ctx = canvas.getContext("2d");
ctx.fillStyle = ("green");
ctx.fillRect(0, 0, 300, 200);
<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
</head>
<body>
<script src="script.js"></script>
<!-- Canvas -->
<canvas id="can" width="300" height="200" style="border:4px solid red;">
</canvas
</body>
</html>
Okay there are two serious errors.
You're trying to get the element before the DOM is fully loaded. Therefore the canvas note is not reachable. See addEventListener
and DOMContentLoaded.
Remove .innerHTML. getContext appends on the node not on the content.
document.addEventListener('DOMContentLoaded', function() {
var canvas = document.getElementById("can");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 300, 200);
});
<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
</head>
<body>
<script src="script.js"></script>
<!-- Canvas -->
<canvas id="can" width="300" height="200" style="border:4px solid red;">
</canvas>
</body>
</html>
1. Script error when using canvas
Use var canvas = document.getElementById("can");
Not var canvas = document.getElementById("can").innerHTML();
See W3C - Canvas
2. Add an event listener when the document is ready, then execute your script
See W3C - DOM Event Listener example
function doSomething() {
var canvas = document.getElementById("can");
var ctx = canvas.getContext('2d');
/*
another scripts...
*/
}
window.addEventListener('onload', doSomething, false);
There are two things.
First, you don't need .innerHTML as other answers stated.
Second, you either have to run you script at the window load event like so:
window.addEventListener('load', function () {
var canvas = document.getElementById("can");
var ctx = canvas.getContext("2d");
ctx.fillStyle = ("green");
ctx.fillRect(0, 0, 300, 200);
});
Or you should load the javascript after the canvas tag.
My project is JSF+PRIMEFACES+JPA and i want to draw rectangles in a jsf web page (XHTML) .
that draw need to be showen after i click on a button based on a list of rectangle that already existe in the managed bean .
its possible to do that just with JSF and primefaces ? or i need to introduce javascript or something else ?
Update 1 :
i fount that richfaces have paint2d option . It'is possible to use just this functionnality from richfaces in my project ?
I think that you want this:
<!doctype html>
<html>
<head>
<title>Example</title>
<meta charset='utf-8' />
</head>
<body>
<input type="button" value="Click Me" onclick="changeColor()" />
<canvas id='example'>Somewhat</canvas>
<script>
var changeColor = function(){
var colors = ['red' ,'green','blue','yellow','brown','azure','gold'];
var example = document.getElementById("example"),
context = example.getContext('2d');
example.height = 480;
example.width = 640;
context.beginPath();
context.rect(188, 50, 200, 100);
context.fillStyle = colors[parseInt(Math.random()*colors.length)];
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
}
</script>
</body>
</html>
Since the 5.1.8 elite release (or the 5.2-SNAPSHOT), Primefaces has the diagram component. It can create images you have above, so maybe that is something you cab use
I know that in js one must use canvas. Here simpliest example:
You can write javascript handler to capture click event and then invoke code that image a rectangle
<!doctype html>
<html>
<head>
<title>pathExample</title>
<meta charset='utf-8' />
</head>
<body>
<canvas id='example'>Обновите браузер</canvas>
<script>
var example = document.getElementById("example"),
context = example.getContext('2d');
example.height = 480;
example.width = 640;
context.beginPath();
context.rect(188, 50, 200, 100);
context.fillStyle = 'red';
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
</script>
</body>
</html>
My question is why does drawScreen have to be located where it is and cannot be moved outside of the method. It is like a method inside a method. I think that this is where I am still weak on JavaScript because there seems times when method, like this one, should be able to be moved outside of where it is as long as it can be called from some point inside of the script.
Question: Why does the drawScreen() method have to be located where it is in the code?
Code Here:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Chapter 1 Example 6 Canvas Sub Dom Example </title>
<script src="modernizr.js"></script>
<script type="text/javascript">
window.addEventListener("load", eventWindowLoaded, false);
var Debugger = function () { };
Debugger.log = function (message) {
try {
console.log(message);
} catch (exception) {
return;
}
}
function eventWindowLoaded () {
canvasApp();
}
function canvasSupport () {
return Modernizr.canvas;
}
function canvasApp () {
if (!canvasSupport()) {
return;
}
var theCanvas = document.getElementById("canvasOne");
var context = theCanvas.getContext("2d");
Debugger.log("Drawing Canvas");
**function drawScreen() {
//background
context.fillStyle = "#ffffaa";
context.fillRect(0, 0, 500, 300);
//text
context.fillStyle = "#000000";
context.font = "20px Sans-Serif";
context.textBaseline = "top";
context.fillText ("Hello World!", 195, 80 );
//image
var helloWorldImage = new Image();
helloWorldImage.onload = function () {
context.drawImage(helloWorldImage, 155, 110);
}
helloWorldImage.src = "helloworld.gif";
//box
context.strokeStyle = "#000000";
context.strokeRect(5, 5, 490, 290);
}**
drawScreen();
}
</script>
</head>
<body>
<div style="position: absolute; top: 50px; left: 50px;">
<canvas id="canvasOne" width="500" height="300">
<div>A yellow background with an image and text on top
<ol>
<li>The text says "Hello World"</li>
<li>The image is of the planet earth.</li>
</ol>
</div>
</canvas>
</div>
</body>
</html>
JavaScript has lexical scope, so it inherits the scope of outer functions (scope is dependant on where functions are located in source code).
In order to move it out, you'd need to either pass it the data it needs (context) or make it available via some other means.
How can I bind an event to a shape drawn on a canvas? I presumed this would work but I get an error.
<html>
<head>
<script type="application/javascript">
function draw() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(200,0,0)";
var rec = ctx.fillRect (0, 0, 55, 50);
rec.onclick = function(){
alert('something');
}
}
</script>
</head>
<body onLoad="draw()">
<canvas id="canvas" width="300" height="300"></canvas>
</body>
</html>
Put the event handlers on the canvas element, and then use the mouse position to decide which conceptual part of the canvas the event is occurring on.
I haven't played with canvas all that much, but I wouldn't be surprised if there were already some libraries that help you manage event delegation to such imaginary elements.
Using Kineticsjs, you can handle shape events in a canvas as follows:
<script>
shape.on('mousedown mouseover' function(evt) {
// do something
});
</script>
Sounds like you should be using svg instead since it allows you to add event listeners on shapes. I'd recommend checking out raphaeljs.com for a start.