Everytime someone clicks on parts of my website, I'd like to show a circle that becomes larger over time. I thought of doing it via a canvas. So far I managed to add circle to the position where the visitor clicked:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Canvas</title>
</head>
<body>
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #cccccc;">
</canvas>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script>
/* Canvas test. */
$(function() {
var c = $("#myCanvas");
// add element that changes over time,
$(c).click(function(e) {
var ctx = this.getContext("2d");
ctx.beginPath();
ctx.arc(e.pageX,e.pageY,40,0,2*Math.PI);
ctx.stroke();
});
});
</script>
</body>
</html>
Is it also possible to have those circles change their radius 1px per 100ms and disappear when their radius in larger than the canvas?
Is it also possible to do this without a canvas?
Solution :
You have to use requestAnimationFrame, to add element and change over time, push in array the point, and draw circle.
/* Canvas test. */
var circles = [];
var canvas = null;
var ctx = null;
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
circles.forEach(function(arg) {
var size = 100 - (new Date() - arg.time) / 10;
if (size <= 0)
return;
ctx.beginPath();
ctx.arc(arg.x, arg.y, size, 0, 2 * Math.PI);
ctx.stroke();
});
requestAnimFrame(loop);
}
$(function() {
canvas = $("#myCanvas")[0];
ctx = canvas.getContext("2d");
window.requestAnimFrame = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
requestAnimFrame(loop);
});
$(function() {
var c = $("#myCanvas");
// add element that changes over time,
$(c).click(function(e) {
circles.push({
time: +new Date(),
x: e.pageX,
y: e.pageY
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="500" height="500" style="border:1px solid #cccccc;"></canvas>
Is it also possible to have those circles change their radius 1px per 100ms and disappear when their radius in larger than the canvas? YES
You can start an animation loop(use raF) and change/stop the growth
Is it also possible to do this without a canvas? YES
Javasccript + SVG or javascript + css3 but these might not be as easy as canvas
edit: found some other usefull question: Expanding circles with CSS3 animations
I want to make a loading bar for my web application and I want to use a html canvas for this. This is the script that I use to fill up the canvas:
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
var xPos = 0;
draw = function() {
if(xPos < 300){
c.rect(0, 0, xPos, 30);
c.fill(255,0,0);
xPos += 0.5;
}
};
</script>
I tested this code on a online code converter (khan academy) and it worked (of course without the first 2 lines and c. in front of most things), and that is also my trouble I don't know where I have to put c. in front of?
I simplified the page a little bit:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<canvas id="bar"></canvas>
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#ff0000"
draw = function(){
if(xPos < 300){
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
}
};
</script>
</body>
</html>
Whatever you are trying to draw... this:
draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
}
};
... it is a definition of variable in global context (context of window object), then assigning a function to it. That's all - it only defines the behavior.
What you need also needs to execute that (a sidenote: to execute it after the canvas is actually created - when you put code in a script tag after canvas tag - it's sufficient and you did it already).
To execute the function use:
draw();
Or don't wrap code in function at all (unless it's to be called multiple times).
Or use a syntax construct to execute the function created in place like this:
(draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
setTimeout(draw,15); // use this to achieve animation effect
}
})();
var xPos = 0;
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#FF0000";
var draw;
(draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
setTimeout(draw,15);
}
})();
#bar {
width: 300px;
height: 50px;
}
<canvas id="bar"></canvas>
Edit: I've been thinking of what you might need, as it's not entirely abvious what you want. I have created this jsfiddle. Maybe it'll be of any help.
Hmmm...
You got some things mixed up. Try this:
<html>
<canvas id = "cvs1" width = "300" height = "30"></canvas>
</html>
And for the script:
var c = document.getElementById("cvs1").getContext("2d");
c.fillStyle = "#ff0000" //Set Fill Color(Set to red)
if(xPos < 300){
c.fillRect(xPos, 0, 30, 30);
xPos += 0.5;
}
If not:
What you did was use fill and rect seperately. You need to set the color, and then use the fillRect() function to draw the rectangle.
EDIT: You got the x,y,width,height as width,height,x,y. Fixed answer.
Good luck!
You need to call draw for every animation step. You could do this using setTimeout, setInterval or requestAnimationFrame :
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<canvas id="bar"></canvas>
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#ff0000";
xPos=0;
draw = function(){
if(xPos < 300){
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
requestAnimationFrame(draw);
}
};
requestAnimationFrame(draw);
</script>
</body>
</html>
I'm having an issue with drawImage() re-sizing a loaded image below a certain width and height. The image I'm trying to re-size is 1080x1920 and I want it to be re-sized to 540x960. If I apply drawImage() to reduce it to 764x1358, it works. But any resolution smaller than that (on either parameter) results in the image not being displayed on the canvas.
There is definitely some correlation between the lower bounds on the resolution, because both are approximately 70.7% of the original resolution. I'm wondering if there's an inherit limit on drawImage but I couldn't find any specification that said so.
Here's the relevant code:
var image = new Image();
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = this.width * 2;
ctx.canvas.height = this.height;
$(image).on("load", function() {
ctx.drawImage(image, 0, 0, 764, 1358);
});
image.src = "test2.jpg";
I edited the code to show where image came from.
Full Code:
<!DOCTYPE html>
<html>
<head>
<title>Canvas from scratch</title>
<meta charset="utf-8">
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="jcanvas.min.js"></script>
</head>
<body>
<canvas id="myCanvas" width="1920" height="1920">
</canvas>
<script>
$(document).ready(
function() {
$("<img>").attr("src", "test2.jpg").on('load', function() {
var imgWidth, imgHeight;
var imageData;
var image = new Image();
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = this.width * 2;
ctx.canvas.height = this.height;
$(image).on("load", function() {
/* This is where the image is loaded and
inserted into the canvas */
ctx.drawImage(image, 0, 0, 763, 1358);
});
image.src = "test2.jpg";
imageData = ctx.getImageData(0, 0,
this.width,
this.height);
/* This is just part of the image manipulation,
bland right now */
var newImgData = ctx.createImageData(imageData.width,
imageData.height);
for ( var i = 0; i < newImgData.data.length; i += 4) {
newImgData.data[i + 0] = 255;
newImgData.data[i + 1] = 0;
newImgData.data[i + 2] = 0;
newImgData.data[i + 3] = 255;
}
// ctx.putImageData(newImgData, imageData.width, 0);
});
});
</script>
</body>
</html>
Last Edit: I found out the solution.
As it turns out, my issue was the version of JQuery I was using. I was originally just version 1, but 1.8.3 fixed everything. So, the solution is to simply change
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
to
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
Question
How do I draw free (using my mouse / fingers) on a canvas element like you can do it in paint with a pencil?
About this question
There are a lot of questions that want to achieve free hand drawing on canvas:
draw by mouse with HTML5 Canvas
KineticJS - Draw free with mouse
Free drawing on canvas using fabric.js
Sketching with JS
Paint canvas not working properly
Mouse position on canvas painting
Implementing smooth sketching and drawing on the element
So I thought it would be a good idea to make a reference question, where every answer is community wiki and contains a explanation for exactly one JavaScript library / pure JavaScript how to do paint on canvas.
Structure of answers
The answers should be community wiki and use the following template:
## [Name of library](Link to project page)
### Simple example
A basic, complete example. That means it has to contain HTML
and JavaScript. You can start with this:
<!DOCTYPE html>
<html>
<head>
<title>Simple example</title>
<script type='text/javascript' src='http://cdnjs.com/[your library]'></script>
<style type='text/css'>
#sheet {
border:1px solid black;
}
</style>
<script type='text/javascript'>
window.onload=function(){
// TODO: Adjust
}
</script>
</head>
<body>
<canvas id="sheet" width="400" height="400"></canvas>
</body>
</html>
If possible, this example should work with both, mouse and touch events.
[JSFiddle](Link to code on jsfiddle.net)
This solution works with:
<!-- Please test it the following way: Write "Hello World"
Problems that you test this way are:
* Does it work at all?
* Are lines separated?
* Does it get slow when you write too much?
-->
* Desktop computers:
* [Browser + Version list]
* Touch devices:
* [Browser + Version list] on [Device name]
### Import / Export
Some explanations how to import / export user drawn images.
### Line smoothing
Explanations about how to manipulate the line the user draws.
This can include:
* Bézier curves
* Controlling thickness of lines
Fabric.js
<!DOCTYPE html>
<html>
<head>
<title>Simple example</title>
<script type='text/javascript' src='http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js'></script>
<style type='text/css'>
#sheet {
border:1px solid black;
}
</style>
<script type='text/javascript'>
window.onload=function(){
var canvas = new fabric.Canvas('sheet');
canvas.isDrawingMode = true;
canvas.freeDrawingBrush.width = 5;
canvas.freeDrawingBrush.color = "#ff0000";
}
</script>
</head>
<body>
<canvas id="sheet" width="400" height="400"></canvas>
</body>
</html>
JSFiddle - Demo
The width of the lines can be controlled with canvas.freeDrawingBrush.width.
The color of the lines can be controlled with canvas.freeDrawingBrush.color.
This solution works with:
Desktop computers:
Chrome 33
Firefox 28
Touch devices:
Chrome 34 on Nexus 4
Opera 20 on Nexus 4
Firefox 28 on Nexus 4
Import / Export
Is only possible by serializing the complete canvas, see Tutorial
Line smoothing
Is done automatically and it seems not to be possible to deactivate it.
Plain JavaScript
Simple example
<!DOCTYPE html>
<html>
<head>
<title>Simple example</title>
<style type='text/css'>
#sheet {
border:1px solid black;
}
</style>
</head>
<body>
<canvas id="sheet" width="400" height="400"></canvas>
<script type='text/javascript'>
/*jslint browser:true */
"use strict";
var context = document.getElementById('sheet').getContext("2d");
var canvas = document.getElementById('sheet');
context = canvas.getContext("2d");
context.strokeStyle = "#ff0000";
context.lineJoin = "round";
context.lineWidth = 5;
var clickX = [];
var clickY = [];
var clickDrag = [];
var paint;
/**
* Add information where the user clicked at.
* #param {number} x
* #param {number} y
* #return {boolean} dragging
*/
function addClick(x, y, dragging) {
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
/**
* Redraw the complete canvas.
*/
function redraw() {
// Clears the canvas
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
for (var i = 0; i < clickX.length; i += 1) {
if (!clickDrag[i] && i == 0) {
context.beginPath();
context.moveTo(clickX[i], clickY[i]);
context.stroke();
} else if (!clickDrag[i] && i > 0) {
context.closePath();
context.beginPath();
context.moveTo(clickX[i], clickY[i]);
context.stroke();
} else {
context.lineTo(clickX[i], clickY[i]);
context.stroke();
}
}
}
/**
* Draw the newly added point.
* #return {void}
*/
function drawNew() {
var i = clickX.length - 1
if (!clickDrag[i]) {
if (clickX.length == 0) {
context.beginPath();
context.moveTo(clickX[i], clickY[i]);
context.stroke();
} else {
context.closePath();
context.beginPath();
context.moveTo(clickX[i], clickY[i]);
context.stroke();
}
} else {
context.lineTo(clickX[i], clickY[i]);
context.stroke();
}
}
function mouseDownEventHandler(e) {
paint = true;
var x = e.pageX - canvas.offsetLeft;
var y = e.pageY - canvas.offsetTop;
if (paint) {
addClick(x, y, false);
drawNew();
}
}
function touchstartEventHandler(e) {
paint = true;
if (paint) {
addClick(e.touches[0].pageX - canvas.offsetLeft, e.touches[0].pageY - canvas.offsetTop, false);
drawNew();
}
}
function mouseUpEventHandler(e) {
context.closePath();
paint = false;
}
function mouseMoveEventHandler(e) {
var x = e.pageX - canvas.offsetLeft;
var y = e.pageY - canvas.offsetTop;
if (paint) {
addClick(x, y, true);
drawNew();
}
}
function touchMoveEventHandler(e) {
if (paint) {
addClick(e.touches[0].pageX - canvas.offsetLeft, e.touches[0].pageY - canvas.offsetTop, true);
drawNew();
}
}
function setUpHandler(isMouseandNotTouch, detectEvent) {
removeRaceHandlers();
if (isMouseandNotTouch) {
canvas.addEventListener('mouseup', mouseUpEventHandler);
canvas.addEventListener('mousemove', mouseMoveEventHandler);
canvas.addEventListener('mousedown', mouseDownEventHandler);
mouseDownEventHandler(detectEvent);
} else {
canvas.addEventListener('touchstart', touchstartEventHandler);
canvas.addEventListener('touchmove', touchMoveEventHandler);
canvas.addEventListener('touchend', mouseUpEventHandler);
touchstartEventHandler(detectEvent);
}
}
function mouseWins(e) {
setUpHandler(true, e);
}
function touchWins(e) {
setUpHandler(false, e);
}
function removeRaceHandlers() {
canvas.removeEventListener('mousedown', mouseWins);
canvas.removeEventListener('touchstart', touchWins);
}
canvas.addEventListener('mousedown', mouseWins);
canvas.addEventListener('touchstart', touchWins);
</script>
</body>
</html>
JSFiddle
The width of the lines can be controlled with context.lineWidth.
The color of the lines can be controlled with strokeStyle.
This solution works with:
Desktop computers:
Chrome 33
Firefox 28
Touch devices:
Firefox 28 on Nexus 4
It does not work with
Touch devices:
Chrome 34 / Opera 20 on Nexus 4 (see issue)
Import / Export
Importing and exporting the image can be done by importing / exporting clickX, clickY and clickDrag.
Line smoothing
Can eventually be done by replacing lineTo() with bezierCurveTo()
Plain JS - ES6
Simple example
Plain Javascript example above has some serious issues: it does not reflect the comments objections, the paint state is redundant, events are not unhooked properly, the redraw() function is not used, it can be simplified a lot and it doesn't work with modern syntax. The fix is here:
var canvas = document.getElementById('sheet'), g = canvas.getContext("2d");
g.strokeStyle = "hsl(208, 100%, 43%)";
g.lineJoin = "round";
g.lineWidth = 1;
g.filter = "blur(1px)";
const
relPos = pt => [pt.pageX - canvas.offsetLeft, pt.pageY - canvas.offsetTop],
drawStart = pt => { with(g) { beginPath(); moveTo.apply(g, pt); stroke(); }},
drawMove = pt => { with(g) { lineTo.apply(g, pt); stroke(); }},
pointerDown = e => drawStart(relPos(e.touches ? e.touches[0] : e)),
pointerMove = e => drawMove(relPos(e.touches ? e.touches[0] : e)),
draw = (method, move, stop) => e => {
if(method=="add") pointerDown(e);
canvas[method+"EventListener"](move, pointerMove);
canvas[method+"EventListener"](stop, g.closePath);
};
canvas.addEventListener("mousedown", draw("add","mousemove","mouseup"));
canvas.addEventListener("touchstart", draw("add","touchmove","touchend"));
canvas.addEventListener("mouseup", draw("remove","mousemove","mouseup"));
canvas.addEventListener("touchend", draw("remove","touchmove","touchend"));
<canvas id="sheet" width="400" height="400" style="border: 1px solid black"></canvas>
Support
It should work everywhere today. I could be further simplified by pointer events, but Safari lacks support for it as of 2021.
Import / Export
For import, use g.drawImage()
g.drawImage(img, 0, 0);
For export, see canvas.toBlob()
function save(blob) {
var fd = new FormData();
fd.append("myFile", blob);
// handle formData to your desire here
}
canvas.toBlob(save,'image/jpeg');
Line smoothing
For antialiasing, See blur() from SVG filters; if you import, don't forget to apply it AFTER the image is imported
context.filter = "blur(1px)";
Paper.js
Simple example
<!DOCTYPE html>
<html>
<head>
<title>Paper.js example</title>
<script type='text/javascript' src='http://paperjs.org/assets/js/paper.js'></script>
<style type='text/css'>
#sheet {
border:1px solid black;
}
</style>
</head>
<body>
<script type="text/paperscript" canvas="sheet">
var path;
function onMouseDown(event) {
// If we produced a path before, deselect it:
if (path) {
path.selected = false;
}
// Create a new path and set its stroke color to black:
path = new Path({
segments: [event.point],
strokeColor: 'black',
strokeWidth: 3
});
}
// While the user drags the mouse, points are added to the path
// at the position of the mouse:
function onMouseDrag(event) {
path.add(event.point);
}
// When the mouse is released, we simplify the path:
function onMouseUp(event) {
path.simplify();
}
</script>
<canvas id="sheet" width="400" height="400"></canvas>
</body>
</html>
JSFiddle
The width of the lines can be controlled with strokeWidth.
The color of the lines can be controlled with strokeColor.
This solution works with:
Desktop computers:
Chrome 33
Import / Export
?
Line smoothing
Line smoothing can be done by adjusting path.simplify();.
EaselJs
Simple example
A basic, complete example. That means it has to contain HTML
and JavaScript. You can start with this:
<!DOCTYPE html>
<html>
<head>
<title>EaselJS example</title>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/EaselJS/0.7.1/easeljs.min.js"></script>
<script>
var canvas, stage;
var drawingCanvas;
var oldPt;
var oldMidPt;
var color;
var stroke;
var index;
function init() {
if (window.top != window) {
document.getElementById("header").style.display = "none";
}
canvas = document.getElementById("sheet");
index = 0;
//check to see if we are running in a browser with touch support
stage = new createjs.Stage(canvas);
stage.autoClear = false;
stage.enableDOMEvents(true);
createjs.Touch.enable(stage);
createjs.Ticker.setFPS(24);
drawingCanvas = new createjs.Shape();
stage.addEventListener("stagemousedown", handleMouseDown);
stage.addEventListener("stagemouseup", handleMouseUp);
stage.addChild(drawingCanvas);
stage.update();
}
function stop() {}
function handleMouseDown(event) {
color = "#ff0000";
stroke = 5;
oldPt = new createjs.Point(stage.mouseX, stage.mouseY);
oldMidPt = oldPt;
stage.addEventListener("stagemousemove" , handleMouseMove);
}
function handleMouseMove(event) {
var midPt = new createjs.Point(oldPt.x + stage.mouseX>>1, oldPt.y+stage.mouseY>>1);
drawingCanvas.graphics.clear().setStrokeStyle(stroke, 'round', 'round').beginStroke(color).moveTo(midPt.x, midPt.y).curveTo(oldPt.x, oldPt.y, oldMidPt.x, oldMidPt.y);
oldPt.x = stage.mouseX;
oldPt.y = stage.mouseY;
oldMidPt.x = midPt.x;
oldMidPt.y = midPt.y;
stage.update();
}
function handleMouseUp(event) {
stage.removeEventListener("stagemousemove" , handleMouseMove);
}
</script>
</head>
<body onload="init();">
<canvas id="sheet" width="400" height="400"></canvas>
</body>
</html>
Demo
The interesting parts in the documentation are:
EaselJS: A starting point for getting into EaselJS.
Stage Class:
This solution works with:
Desktop computers:
Chrome 33
Firefox 28
Touch devices:
Chrome 34 / Firefox 28 / Opera 20 on Nexus 4
Import / Export
?
Line smoothing
?
Here, try my canvas free drawing and erase.
https://jsfiddle.net/richardcwc/d2gxjdva/
//Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
var tooltype = 'draw';
//Mousedown
$(canvas).on('mousedown', function(e) {
last_mousex = mousex = parseInt(e.clientX-canvasx);
last_mousey = mousey = parseInt(e.clientY-canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function(e) {
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function(e) {
mousex = parseInt(e.clientX-canvasx);
mousey = parseInt(e.clientY-canvasy);
if(mousedown) {
ctx.beginPath();
if(tooltype=='draw') {
ctx.globalCompositeOperation = 'source-over';
ctx.strokeStyle = 'black';
ctx.lineWidth = 3;
} else {
ctx.globalCompositeOperation = 'destination-out';
ctx.lineWidth = 10;
}
ctx.moveTo(last_mousex,last_mousey);
ctx.lineTo(mousex,mousey);
ctx.lineJoin = ctx.lineCap = 'round';
ctx.stroke();
}
last_mousex = mousex;
last_mousey = mousey;
//Output
$('#output').html('current: '+mousex+', '+mousey+'<br/>last: '+last_mousex+', '+last_mousey+'<br/>mousedown: '+mousedown);
});
//Use draw|erase
use_tool = function(tool) {
tooltype = tool; //update
}
canvas {
cursor: crosshair;
border: 1px solid #000000;
}
<canvas id="canvas" width="800" height="500"></canvas>
<input type="button" value="draw" onclick="use_tool('draw');" />
<input type="button" value="erase" onclick="use_tool('erase');" />
<div id="output"></div>
(Disclaimer: I wrote this library)
Scrawl.js
Simple example
<!DOCTYPE html>
<html>
<head>
<title>Simple example</title>
<style type='text/css'>
#sheet {border:1px solid black;}
</style>
</head>
<body>
<canvas id="sheet" width="400" height="400"></canvas>
<script src="http://scrawl.rikweb.org.uk/js/scrawlCore-min.js"></script>
<script>
var mycode = function(){
//define variables
var myPad = scrawl.pad.sheet,
myCanvas = scrawl.canvas.sheet,
sX, sY, here,
drawing = false,
currentSprite = false,
startDrawing,
endDrawing;
//event listeners
startDrawing = function(e){
drawing = true;
currentSprite = scrawl.newShape({
start: here,
lineCap: 'round',
lineJoin: 'round',
method: 'draw',
lineWidth: 4,
strokeStyle: 'red',
data: 'l0,0 ',
});
sX = here.x;
sY = here.y;
if(e){
e.stopPropagation();
e.preventDefault();
}
};
myCanvas.addEventListener('mousedown', startDrawing, false);
endDrawing = function(e){
if(currentSprite){
currentSprite = false;
}
drawing = false;
if(e){
e.stopPropagation();
e.preventDefault();
}
};
myCanvas.addEventListener('mouseup', endDrawing, false);
//animation object
scrawl.newAnimation({
fn: function(){
//get current mouse position
here = myPad.getMouse();
if(here.active){
if(drawing){
if(here.x !== sX || here.y !== sY){
//extend the line
currentSprite.set({
data: currentSprite.data+' '+(here.x - sX)+','+(here.y - sY),
});
sX = here.x;
sY = here.y;
}
}
}
else{
//stop drawing if mouse leaves canvas area
if(currentSprite){
endDrawing();
}
}
//update display
scrawl.render();
},
});
};
//Scrawl is modular - load additional modules
scrawl.loadModules({
path: 'js/',
modules: ['animation', 'shape'],
callback: function(){
window.addEventListener('load', function(){
scrawl.init(); //start Scrawl
mycode(); //run code
}, false);
},
});
</script>
</body>
</html>
JSFiddle
This solution works with:
recent versions of IE, Chrome, Firefox, Opera (desktop)
(not tested on mobile/touch devices)
Adding touch support
(try adding a dedicated touch library like Hammer.js?)
Import / Export
Scrawl has experimental support for saving and loading JSON strings
tutorial page: load and save
Line smoothing and other sprite manipulations
line data is saved internally as an SVGTiny Path.d value - any algorithm that can take line data in that format and smooth it should work
line attributes - thickness, color, positioning, rotation, etc - can be set, and animated.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var canvas_variable;
var init_x = 200;
var init_y = 300;
var x_move = 1;
function initialize_canvas()
{setInterval(draw_ball, 10);
canvas_variable = bouncing_ball_canvas.getContext('2d');
}
function draw_ball()
{
canvas_variable.clearRect(0,0, 1000, 500);
canvas_variable.beginPath();
canvas_variable.fillStyle="#FF0000";
canvas_variable.arc(init_x, init_y, 50, 0+init_x/50, Math.PI*2+init_x/50, true);
canvas_variable.lineTo(init_x, init_y);
canvas_variable.stroke();
if( init_x<0 || init_x>1000) x_move = -x_move;
init_x += x_move;
}
</script>
</head>
<body>
<canvas id="bouncing_ball_canvas" width="1000" height="500">
</canvas>
<body onLoad="initialize_canvas();">
</body>
</html>
This is a program of a rolling ball. The function draw_ball is called after every 10 milliseconds.The ball blinks during its motion. What is the solution for this problem?
You forgot to declare the variable bouncing_ball_canvas
Try adding:
bouncing_ball_canvas = document.getElementById("bouncing_ball_canvas");
before you declare canvas_variable.
EDIT:
The problem lies in the line:
canvas_variable.arc(init_x, init_y, 50, 0+init_x/50, Math.PI*2+init_x/50, true);
Change the last variable to false and it should work.
It is blinking because your computation is wrong.
You need to compute the perimeter: 2*pi*r.
Then do a simple cross product:
distance = x
perimeter = 2*pi
So the angle (in radian) is distance*2*pi/perimeter
So try this:
const getAngle=function(distance) {
return distance*2*Math.PI/perimeter;
}
const getPos=function(x, y, angle, r) {
return [x + Math.cos(angle)*r, y + Math.sin(angle)*r];
}
canvas_variable.arc(init_x, init_y, 50, 0, Math.PI*2, true);
canvas_variable.moveTo(..getPos(init_x, init_y, getAngle(init_x-starting_x), r));
canvas_variable.lineTo(init_x, init_y);
canvas_variable.stroke();