Drawing on a canvas - javascript

So I want to be able to draw onto this canvas I created, let me show you my Javascript code and i'll explain whats happening:
I have two canvas's, one that has a square 50X50 always following the mouse, and another that i want to use to draw on. So far this works, but i want to be able to drag the mouse and continue to draw, instead of clicking the mouse every time i want to draw.
function start(){
var canvas_hover_tmp = document.getElementById('canvas_hover');
canvas_hover = canvas_hover_tmp.getContext('2d');
var canvas_click_tmp = document.getElementById('canvas_draw');
canvas_click = canvas_click_tmp.getContext('2d');
window.addEventListener('mousemove', moved, false); //move square with mouse on mouse move
window.addEventListener('mousedown', draw, false); //draw square to canvas at specific location from where mouse is
}
This function just gets the canvas's i want to use and sets them up, i then call event listeners, one to follow the mouse and one to click down and drag and draw
function moved(pos){
canvas_hover.clearRect(0,0,1000,600);
var x = pos.clientX;
var y = pos.clientY;
canvas_hover.fillRect(x-25, y-25,50,50);
}
This function allows me to hover a box, it hovers with the mouse
function draw(draw_pos){
var x = draw_pos.clientX;
var y = draw_pos.clientY;
canvas_click.fillRect(x-25,y-25,50,50);
}
This is the function that draws onto the canvas at a specific location according to where the mouse is, I can click and it will draw a square but i can't click down and drag and continue the drawing, as i would like. How can i do that?
window.addEventListener('load', drawRect, false); //call first function start
I have tried setting a variable called draw = 1 and when it equals one that means continue drawing and when 0 stop. But i put it in a while loop and all that happens is the page crashes.
I have these two canvas's set up in CSS3 to overlay each other.
Sorry if this is confusing, i wasn't sure how to word this
Any help would be awesome,
Thanks :)

Your "setting variable" approach is right. You want to draw as long as the mouse button is hold, so you have to listen on mousedown, mousemove and mouseup and introduce some global variable (say drawOnSecond for "draw on second layer"):
//move square with mouse on mouse move
window.addEventListener('mousemove', moved, false);
//draw square to canvas at specific location from where mouse is
//you shouldn't drop this listener, as this would prevent drawing via clicking
window.addEventListener('mousedown', draw, false);
// enable/disable drawing while moving the mouse
window.addEventListener('mousedown', enableDraw, false);
window.addEventListener('mouseup', disableDraw, false); // disable
Then you have to adjust your moved function a little bit and implement enableDraw/disableDraw:
function moved(pos){
canvas_hover.clearRect(0,0,1000,600);
var x = pos.clientX;
var y = pos.clientY;
canvas_hover.fillRect(x-25, y-25,50,50);
if(drawOnSecond) // <<---- global variable, default false
draw(pos);
}
function enableDraw(){
drawOnSecond = true;
}
function disableDraw(){
drawOnSecond = false;
}
JSFiddle

Related

Use of absolutePan() to move background image and elements around on canvas with touch event

I am using next code to force content of canvas to follow finger touch movement on screen (drag and drop).
document.addEventListener('touchmove', function(e){
if(e.targetTouches.length ==1) {
var canavasMovex=e.targetTouches[0].pageX-canvasLeftofset-canvas.width/2;
var canavasMovey=e.targetTouches[0].pageY-canvasTopofset-canvas.height/2;
document.getElementById("a").innerHTML= canavasMovex;
document.getElementById("b").innerHTML= canavasMovey;
var delta = new fabric.Point(-canavasMovex,-canavasMovey);
canvas.absolutePan(delta);
canvas.renderAll();
}
}, false);
Note: "-canavasMovex,-canavasMovey" values have the negative sign (I had to use it because otherwise the canvas was moving opposite to finger moment(I think you can ignore this fact and that it has noting to do with offset, which I am trying to solve asking for help here))
I have displacement of position proportional to the distance of touch point from the centre of canvas. If I start the movement pressing from the centre of screen, then displacement is not so notable. But if I start from top corner (for example) I get centre of canvas there in that touch point. From attached drawing I was trying with taking of consideration of "d" parameter (distance of touching point to the centre of canvas), to find right value for the equation for the canvas.absolutePan() function, but no success. Can you help me with this case,pleas? I was trying to use some solutions from browsing the internet to find the way to move canvas content. But then I had lost some of functions of my app because "new" libraries were not interacting correctly with my existing fabric.min.js library. Image info(external rectangle-web page,internal rectangle-canvas): a-canvas offset,b-distance to centre of canvas,c- touch point,d-distance from touch point to centre of canvas. So on the end I am trying to get to accomplish this task in this way.
Malfunction:
Bigger than distance "d" is on starting of dragging , bigger is then the offset. (actuary if I start dragging from canvas corner, canvas content transfers its centre there)
The solution is to get the finger position, calculate the difference to previous position, add difference to the previous position and then finally do the panning.
var canvasMovexoold = 0;
var canvasMoveyoold = 0;
document.addEventListener('touchstart', function(e){
canvasMovexoold = canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX;
canvasMoveyoold =canvasTopofset+canvas.height/2- e.targetTouches[0].pageY;
}, false);
document.addEventListener('touchmove', function(e){
if(e.targetTouches.length ==1) {
var canvasMovexo += canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX-canvasMovexoold ;
var canvasMoveyo +=canvasTopofset+canvas.height/2- e.targetTouches[0].pageY-canvasMoveyoold ;
var delta = new fabric.Point(canvasMovexo,canvasMoveyo);
canvas.absolutePan(delta);
canvasMovexoold = canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX;
canvasMoveyoold =canvasTopofset+canvas.height/2- e.targetTouches[0].pageY;
}
}, false);

Smoothing mouse animation in Javascript

I am trying to create a simple animation based on my mouse movement. An object that is placed in the center of the screen should pull away from the center based on my mouse movement. But when i try to do that the object jitters around a lot despite the mouse movement being smooth.
I have created a fiddle to show the problem: https://jsfiddle.net/ahof0gLc/
The object is moved as follows when the mouse moves:
animX += event.movementX||event.mozMovementX||event.webkitMovementX||0;
It is then pulled back toward the center like so:
if (animX) animX *= Math.pow(0.99, delta);
I have tried several methods. But because the mouse movement is counteracting the deceleration it jitters a lot. How can I fix this?
Updated with a really hacky spring model. Using mouse over and mouse leave to track mouse.
https://jsfiddle.net/eex3aphm/
You have a fight between your mousemove and your animation.
I changed your mouse movement handler to use a temporary variable to hold the movement:
var pullX = 0;
var onMouseMove = function(event) {
event.preventDefault();
pullX = event.movementX||event.mozMovementX||event.webkitMovementX||0;
};
Then moved the update to the deceleration equation:
animX = (animX + pullX) * Math.pow(0.99, delta);
pullX = 0;
This keeps you from messing with your deceleration on mouse move.
https://jsfiddle.net/r57t7v3o/

Moving multiple objects simultaneously in createJS/easelJS

I've been using easelJS within the createJS framework for a project and have enjoyed it a lot until recently hitting a roadblock. I have multiple objects that I'd like to move simultaneously when one of the group is dragged. Here is my current situation:
What I'd like to do is when the red circle is moved, the red crosshairs would also move so that they appear to be "locked" to the circle. The same with the green circle.
I have been able to accomplish something very close to this by adding the circles and crosshairs to a container, as mentioned in the answers to this question:
Easeljs Scrollable Container
But the issue I encounter is that the container is actually a rectangle, such that I can click anywhere between the circle and crosshairs to move the various objects contained within the container. Instead I would like for the objects to be moved only when I click on a circle.
Does anyone have any idea how to accomplish this? Am I correct in thinking this can be accomplished somehow with easelJS containers?
Containers should be fine. You can turn off mouseEnabled on the cross-hair in order to make it ignore the mouse.
You could also just store the offset for each cross-hair/circle, and just set the cross-hair position when the circle moves.
Here is a quick demo:
http://jsfiddle.net/lannymcnie/kah9of6e/
// Set the offset when the circle is pressed
circle.on("mousedown", function(e) {
circle.offset = new createjs.Point(crosshair.x-circle.x, crosshair.y-circle.y);
});
// Add drag and drop to each shape
circle.on("pressmove", handleDrag);
crosshair.on("pressmove", handleDrag);
function handleDrag(e) {
// Move the target to the mouse
e.target.x = e.stageX; e.target.y = e.stageY;
// If the target is the circle, also move the cross-hair
if (e.target == circle) {
// Move the cross-hair
crosshair.x = circle.x + circle.offset.x;
x.y = circle.y + circle.offset.y;
}
}

HTML5 Canvas event listening [duplicate]

I am new in canvas can anyone please help to short this issue.
I create 5 canvas circle. When I hover on any circle I need to change canvas color only, when hover on circle I added one class on canvas but is it possible to change only color. I don't want to create canvas again change only color when hover.
$(document).ready(function(){
$('.menuballs').hover(function () {
$(".menuballs").children('canvas').toggleClass('hover-intro');
if($(this).is(':hover'))
{
var c = document.getElementsByClassName("hover-intro");
var graphics = c.getContext( '2d' );
graphics.fillStyle = 'green';
graphics.fill();
}
});
});
Try this as taking hover-intro class but its given HTMLElement, and I need CanvasElement to fill in circle.
Your :hover will never be triggered.
Circles drawn on html canvas are not DOM elements. Instead they are like forgotten painted pixels on a canvas.
These are the steps to apply a hover-effect to your circle
Keep track of your circle's definition (x,y,radius,etc) in a javascript object.
Listen for mousemove events and test if the mouse is inside your circle
When the mouse enters or leaves your circle, redraw your circle
This is how those steps might look in code:
Demo: http://jsfiddle.net/m1erickson/rV9cZ/
Keep track of your circle's definition (x,y,radius,etc) in a javascript object.
var myCircle={
x:150,
y:150,
radius:25,
rr:25*25, // radius squared
hovercolor:"red",
blurcolor:"green",
isHovering:false
}
Listen for mousemove events and test if the mouse is inside your circle
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
var dx=mouseX-myCircle.x;
var dy=mouseY-myCircle.y;
// math to test if mouse is inside circle
if(dx*dx+dy*dy<myCircle.rr){
// change to hovercolor if previously outside
if(!myCircle.isHovering){
myCircle.isHovering=true;
drawCircle(myCircle);
}
}else{
// change to blurcolor if previously inside
if(myCircle.isHovering){
myCircle.isHovering=false;
drawCircle(myCircle);
}
}
}
When the mouse enters or leaves your circle, redraw your circle
function drawCircle(circle){
ctx.beginPath();
ctx.arc(circle.x,circle.y,circle.radius,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=circle.isHovering?circle.hovercolor:circle.blurcolor;
ctx.fill();
}

PaperJS: Events are caught when I'm outside the canvas

I'm working in a tool to draw in a canvas using the framework Paper.js
I got an issue using iPad. When I'm drawing with one finger, that works. When I'm drawing with two fingers, one in the canvas and one outside the canvas, the second finger event is caught by the event onMouseDrag, and that put some stroke from the first finger to the second finger, not a good behaviour for me.
Example:
At the beginning, I start to draw with one finger. After I put the second finger outside the canvas and I continue to move my first finger. This is what happen.
Do you have any idea to avoid event when I'm outside the canvas?
Thanks.
If you don't want the finger outside to be detected, limit the target to your canvas.
var canvasElement = document.getElementById('canvasId') //or element
tool.onMouseDrag = function(event) {
if (event.event.target === canvasElement) { //my target canvas was nested like this
path.add(event.point);
path.smooth();
}
}
Well, you could test event.point.isInside(view.bounds). This will likely kill your performance if you test it while drawing, but you could cull the points after you're finished.

Categories