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();
}
Related
I'm drawing rectangles on a canvas with Javascript. When the user moves his mouse over one of the rectangles, a text should appear in that rectangle. At only that rectangle (i.e., not the other rectangles).
So I managed to draw the rectangles and created the mouseover event. It works perfectly: as soon as the mouse moves over one of the rectangles the text appears. However, the text appears in ALL rectangles... Any thought about what I'm doing wrong? There seems to be a looping problem, but I can't seem to fix it.
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
for(var i=0;i<entities.length;i++){
var entity=entities[i];
ctx.rect(entity.x, entity.y, width, height);
if(ctx.isPointInPath(mouseX,mouseY)){
ctx.font = "10px Arial";
ctx.fillStyle = "black";
ctx.textAlign = "left";
ctx.fillText("edit", entity.x + 5 , entity.y + 5 );
}
}
}
The isPointInPath method will check if the given coordinates are in any of the shapes formed by the current path. Every rect is added to the same, single path which has already been created during your initialisation code that draws the rectangles.
So the effect is that once your mouse is over any of the drawings, the condition is true in each iteration of your loop.
Solve this by creating a new path in each iteration:
for(var i=0;i<entities.length;i++){
var entity=entities[i];
ctx.beginPath(); // <----
ctx.rect(entity.x, entity.y, width, height);
// ...etc
I have an HTML5 Canvas. I am using the KineticJS(KonvaJS) canvas library. On a blank canvas I dram an image as shown in the figure below. Now I want to create a circle Shape which can be used to erase parts of the image. The red circle in the image is the eraser.
How can I erase parts of an Image on HTML5 Canvas?
You can use Compositing to "erase" pixels.
Specifically you use destination-out compositing.
KineticJS does not support compositing, but you still have a couple of options:
(Note: KineticJS has become KonvaJS and I haven't checked whether KonvaJs supports compositing. If it now does, just use destination-out compositing inside KonvaJS)
Option#1: Use a native canvas element as your Kinetic.Image source
Create an in-memory html5 canvas using var c=document.createElement,
Resize the canvas to image size,
drawImage your image onto the canvas,
Create a Kinetic.Image and set its image property to a reference to the native canvas. The Kinetic.Image will display whatever is drawn onto the native canvas.
var kImage=new Kinetic.Image({
...
image:c,
...
Set the canvas Compositing to cause new drawings to "erase" existing pixels:
c.globalCompositeOperation='destination-out';
Listen for drag events on your circle-eraser. Use those events to draw a circle on the canvas that move just like the Kinetic circle-eraser moves. Since the canvas's compositing is set to "erase", new drawings of the circle on the canvas will erase the image on the canvas.
Your Kinetic.Image exactly reflects its canvas source (var c), so your Kinetic.Image will also display the image being erased in response to the Kinetic circle-eraser movements.
Option#2: Use a Kinetic.Shape
You can do the same operation as Option#1 by creating a Kinetic.Shape on a separate layer and getting a reference to the native canvas context using:
var ctx = myShapeLayer.getContext()._context;
This is a weaker option because KineticJS will redraw the shape--causing your erasing to be undone. Therefore you must do the additional step of saving all your circle-eraser's movements and replaying those movements (in drawFunc) to redo your erasing.
Thanks for markE for his detailed answer,
I have tried to get the context from the Konva.Layer() and it worked.
var freeHandDrawingImage = new Image();
freeHandDrawingImage.onload = function() {
var context = freeHandDrawingLayer.getContext('2d');
context.drawImage(this, 0,0);
context.globalCompositeOperation='destination-out';
freeHandDrawingLayer.draw();
};
freeHandDrawingImage.src = "image.png";
and I have used the Konva.Shape to erase by "destination-out" and draw free draw by custom "source-over":
freeDrawingType = 'brush';
isFreeDrawingMode = false;
isPaint = false;
lastPointerPosition = {};
drawFreeDrawings = function(){
var freeDraw = new Konva.Shape({
name: "freeDraw",
stroke: 'black',
strokeWidth: 5,
closed : false,
sceneFunc: function(context){
// free draw quad
debugger;
if(isPaint){
if (freeDrawingType === 'brush') {
context.globalCompositeOperation = 'source-over';
}
if (freeDrawingType === 'eraser') {
context.globalCompositeOperation = 'destination-out';
}
context.beginPath();
context.moveTo(lastPointerPosition.x, lastPointerPosition.y);
var newPosition = stage.getPointerPosition();
context.lineTo(newPosition.x, newPosition.y);
context.stroke();
debugger;
lastPointerPosition = newPosition;
context.strokeShape(this);
}
}
});
freeHandDrawingLayer.add(freeDraw);
// now we need to bind some events
// we need to start drawing on mousedown
// and stop drawing on mouseup
selectionBoxBackground.on('mousedown', function() {
if(isFreeDrawingMode){
isPaint = true;
lastPointerPosition = stage.getPointerPosition();
stage.draw();
}
});
selectionBoxBackground.on('mouseup', function() {
if(isFreeDrawingMode){
isPaint = false;
}
});
// and core function - drawing
selectionBoxBackground.on('mousemove', function() {
if (!isPaint) {
return;
}
freeHandDrawingLayer.draw();
});
}
In plain JavaScript this is pretty straight forward.
First get your canvas and drawing context ready:
var context=document.getElementById("your_canvas_id").getContext("2d");
var image=document.getElementById("your_image_id");
Now you want to draw the image to the context:
context.drawImage(image,0,0,image.width,image.height,0,0,image.width,image.height);
Now, when you want to erase part of your image, just draw over the canvas:
var x=y=radius=10;// Circle coordinates and radius.
context.fillStyle="#ffffff";// Your eraser color (not transparent)
context.beginPath();
context.arc(x,y,radius,0,Math.PI*2);
context.fill();
This only simulates erasing, however. If you want what you erase to be transparent afterwards, you might look into context.clearRect, but I'm not sure how you would do that with a circle.
In HTML/CSS we can align a child to any side of the parent through: top, right, left, bottom
Can this be applied to rectangles, lines etc.. on canvas's?
Alternatively is their a way to use percentages in positioning?
My end goal is to get a rectangle whose position snaps to the right of the canvas and stays their if the canvas is resized.
I can't seam to figure out a way to do this.
This is what I'm working with it.
ctx.rect(20,20,150,100);
Html & CSS can reposition child elements because the definitions of those children are saved in the Document Object Model (DOM).
The Html Canvas element does not save the definitions of any rectangles, lines, etc. that it draws on itself. Therefore, it cannot "recall" your rectangle to reposition it. To Canvas, your rectangle becomes unremembered pixels on its bitmap display.
To reposition your rectangle, you will have to manually "remember" its definition using code. This is usually done by saving your rectangle's definition in a javascript object like this:
var myRect={
x:20,
y:20,
width:150,
height:100,
}
When you want to reposition a canvas rectangle (as when you want it to "stick" to a resized canvas), you:
Resize the canvas. (Note: resizing the canvas element automatically clears its contents).
Calculate the new [x,y] that will keep your rectangle "stuck" to the right side of the canvas. If you want your rectangle stuck to the right side, you recalculate: var newX=canvas.width-myRect.width
Change the [x,y] in myRect to those new x,y values.
Use myRect to redraw your rectangle in its new desired postion.
Here's annotated example code and a Demo:
// canvas related variables
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
// the definition of your rectangle
// (this definition is used when your rectangle must be redrawn)
var myRect={
x:20,
y:20,
width:150,
height:100,
}
// call helper function to reset your rectangle's "x"
// so it's positioned to the right side
stickRight(myRect);
// call helper function to redraw your rectangle
redrawRect(myRect);
// listen for changes in the html slider that resizes the canvas
$myslider=$('#myslider');
$myslider.change(function(){
// fetch the scaling factor the user has specified with the slider
var scale=parseInt($(this).val());
// resize the canvas to the specified size
// NOTE: resizing the canvas automatically erases all content
canvas.width=cw*scale/100;
canvas.height=ch*scale/100;
// again call helper function to reset your rectangle's "x"
// so it's positioned to the right side
stickRight(myRect);
// call helper function to redraw your rectangle
redrawRect(myRect);
});
function stickRight(rect){
rect.x=canvas.width-myRect.width;
}
function redrawRect(rect){
ctx.beginPath();
ctx.rect(rect.x,rect.y,rect.width,rect.height);
ctx.stroke()
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Resize: <input id=myslider type=range min=0 max=200 value=100><br>
<canvas id="canvas" width=300 height=300></canvas>
I am using kinetics Javascript. I draw a couple of rect, it smooths. When mouse focus on Rect, I want to show some points/joints on the rect, so that it gives hints rect could be linked with each other by this particular points/joints. I have other pictures also, for example triangle, it shall also has joints. How to have a figure(Rect for example) when it is normal state and another state with little bit changed figure when mouse focuses?
The simplest would be to display a "linkable" icon on top of any rectangle that the mouse enters and remove that icon when the mouse leaves.
Demo: http://jsfiddle.net/m1erickson/6dgAD/
You can handle mouseenter and mouseleave events on your rectangles like this:
This code puts a Kinetic.Image containing a "linkable" icon over the rect.
rect.on("mouseenter",function(){
link.setPosition(this.getPosition());
link.show();
layer.draw();
});
rect.on("mouseleave",function(){
link.hide();
layer.draw();
});
Here's an example of how you might create a "linkable" icon using Kinetic.Image:
var link;
var img=new Image();
img.onload=function(){
link=new Kinetic.Image({
image:img,
listening:false,
});
layer.add(link);
link.hide();
layer.draw();
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stack1/addLink.png";
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