been looking at easeljs and seem to be confused about what's the best way to go about event delegation. Here's what I'm trying:
function init() {
var canvas = document.getElementById('canvas');
var stage = new createjs.Stage(canvas);
var txt1 = new createjs.Text('Test With Hit Area', '24px Arial', '#0000ff');
txt1.x = 50;
txt1.y = 50;
console.log('txt1', txt1);
var hit = new createjs.Shape();
hit.graphics.beginFill('#000000').drawRect(500, 50, txt1.getMeasuredWidth(), txt1.getMeasuredHeight())
txt1.hitArea = hit;
// neither seem to work with a hitArea
// txt1.addEventListener('click', handleClick);
txt1.on('click', handleClick);
var txt2 = new createjs.Text('Test Without Hit Area', '24px Arial', '#0000ff');
txt2.x = 50;
txt2.y = 80;
console.log('txt2', txt2);
// both addEventListener() and on() work fine without hit area
// txt2.addEventListener('click', handleClick);
txt2.on('click', handleClick);
stage.addChild(txt1, txt2);
stage.update();
}
function handleClick() {
console.log('clicked', this);
}
init();
I've created a simple jsfiddle to demonstrate my attempts here: http://jsfiddle.net/brrWn/1/
The hitArea will automatically align itself with the Shape, so you should set the x & y of the rectangle to 0,0.
hit.graphics.beginFill('#000000')
.drawRect(0, 0, txt1.getMeasuredWidth(), txt1.getMeasuredHeight())
http://jsfiddle.net/lannymcnie/brrWn/2/
I turned on mouseover and set the cursor, which makes it easier to visualize the hitArea.
Cheers.
Related
I have a problem when I go to paint the PIXI.Text in the cursor position.
This is the simple demo to reproduce the problem, when you go over the node with the cursor I paint the text, in this case, "#author vincenzopalazzo" but I want the position on the node, so I think for resolving the problem I have got the solution I must set the position of the mouse.
But I don't have an idea got get this position, so this is an example to reproduce the problem with PIXI
//setup Pixi renderer
var renderer = PIXI.autoDetectRenderer(600, 400, {
backgroundColor: 0x000000
});
document.body.appendChild(renderer.view);
// create new stage
var stage = new PIXI.Container();
// create helpful message
var style = {
font: '18px Courier, monospace',
fill: '#ffffff'
};
// create graphic object called circle then draw a circle on it
var circle = new PIXI.Graphics();
circle.lineStyle(5, 0xFFFFFF, 1);
circle.beginFill(0x0000FF, 1);
circle.drawCircle(150, 150, 100);
circle.endFill();
circle.alpha = 0.5;
stage.addChild(circle);
// designate circle as being interactive so it handles events
circle.interactive = true;
// create hit area, needed for interactivity
circle.hitArea = new PIXI.Circle(150, 150, 100);
// make circle non-transparent when mouse is over it
circle.mouseover = function(events) {
var message = new PIXI.Text('Hover your mouse over the circle to see the effect.', style);
message.x = events.clientX;
message.y = events.clientY;
circle.message = message;
circle.addChild(message);
}
// make circle half-transparent when mouse leaves
circle.mouseout = function(mouseData) {
this.alpha = 0.5;
circle.removeChild(circle.message);
delete circle.message;
}
// start animating
animate();
function animate() {
requestAnimationFrame(animate);
// render the root container
renderer.render(stage);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.1.4/pixi.js"></script>
This is my real code
module.exports = function (animatedNode, ctx) {
ctx.on('hover', function(animatedNode, ctx){
let x = animatedNode.pos.x;
let y = - animatedNode.pos.y / 2;
if(animatedNode.label === undefined){
animatedNode.label = new PIXI.Text('#author vincenzopalazzo', { fontFamily: "Arial", fontSize: "20px" , fill: 0x000000} );
animatedNode.label.x = x;
animatedNode.label.y = y + animatedNode.width/2;
ctx.addChild(animatedNode.label);
}else{
animatedNode.label.x = x;
animatedNode.label.y = y + animatedNode.width/2;
}
});
ctx.on('unhover', function(animatedNode, ctx){
ctx.removeChild(animatedNode.label);
delete animatedNode.label;
});
ctx.mouseover = function() {
console.debug('I\'call the hover events');
this.fire('hover', animatedNode, ctx);
}
ctx.mouseout = function() {
console.debug('I\'call the unhover events');
this.fire('unhover', animatedNode, ctx);
}
}
I'm using the ngraph.events on the ctx (it is the PIXI graphics) object, the method on and fire is the module nghraph.events
In your example code (first snippet) the "moseover" handler should be changed from:
// make circle non-transparent when mouse is over it
circle.mouseover = function(events) {
var message = new PIXI.Text('Hover your mouse over the circle to see the effect.', style);
message.x = events.clientX;
message.y = events.clientY;
circle.message = message;
circle.addChild(message);
}
to:
// make circle non-transparent when mouse is over it
circle.on('mouseover', function(event) {
// console.log('mouse is over the circle');
// console.log(event); // see in (for example in Chrome Devtools console) what is inside this variable
var message = new PIXI.Text('Hover your mouse over the circle to see the effect.', style);
// By looking at what "console.log(event)" shows we can see that instead of:
// message.x = events.clientX;
// message.y = events.clientY;
// should be:
message.x = event.data.global.x;
message.y = event.data.global.y;
circle.message = message;
circle.addChild(message);
});
To understand it more you can uncomment the "console.log" lines to observe it in your browser devtools console.
Then we also need to handle 'mouseover' event like this:
circle.on('mousemove',function (event) {
if (!circle.message) {
return;
}
var newPosition = event.data.getLocalPosition(this.parent);
circle.message.x = newPosition.x;
circle.message.y = newPosition.y;
});
so whole runnable example will be like this:
//setup Pixi renderer
var renderer = PIXI.autoDetectRenderer(600, 400, {
backgroundColor: 0x000000
});
document.body.appendChild(renderer.view);
// create new stage
var stage = new PIXI.Container();
// create helpful message
var style = {
font: '18px Courier, monospace',
fill: '#ffffff'
};
// create graphic object called circle then draw a circle on it
var circle = new PIXI.Graphics();
circle.lineStyle(5, 0xFFFFFF, 1);
circle.beginFill(0x0000FF, 1);
circle.drawCircle(150, 150, 100);
circle.endFill();
circle.alpha = 0.5;
stage.addChild(circle);
// designate circle as being interactive so it handles events
circle.interactive = true;
// create hit area, needed for interactivity
circle.hitArea = new PIXI.Circle(150, 150, 100);
// make circle non-transparent when mouse is over it
circle.on('mouseover', function(event) {
// console.log('mouse is over the circle');
// console.log(event); // see in (for example in Chrome Devtools console) what is inside this variable
var message = new PIXI.Text('Hover your mouse over the circle to see the effect.', style);
// By looking at what "console.log(event)" shows we can see that instead of:
// message.x = events.clientX;
// message.y = events.clientY;
// should be:
message.x = event.data.global.x;
message.y = event.data.global.y;
circle.message = message;
circle.addChild(message);
});
circle.on('mousemove',function (event) {
if (!circle.message) {
return;
}
var newPosition = event.data.getLocalPosition(this.parent);
circle.message.x = newPosition.x;
circle.message.y = newPosition.y;
});
// make circle half-transparent when mouse leaves
circle.mouseout = function(mouseData) {
this.alpha = 0.5;
circle.removeChild(circle.message);
delete circle.message;
}
// start animating
animate();
function animate() {
requestAnimationFrame(animate);
// render the root container
renderer.render(stage);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.1.4/pixi.js"></script>
Please also see:
"Interaction/Dragging" Pixi.js demo (with source code): https://pixijs.io/examples/#/interaction/dragging.js
tutorial "Rotate towards mouse and shoot in that direction" by Igor Neuhold : http://proclive.io/shooting-tutorial/
Pixi.js API reference:
https://pixijs.download/dev/docs/PIXI.DisplayObject.html#event:mousemove
https://pixijs.download/dev/docs/PIXI.interaction.InteractionEvent.html
https://pixijs.download/dev/docs/PIXI.interaction.InteractionData.html
I have not been able to scroll through canvas move whole paper horizontally and
vertically.
It is possible?
<script type="text/javascript" src="~/Scripts/PaperJS/paper-full.js"></script>
<script type="text/javascript" src="~/Scripts/PaperJS/paper-core.js"></script>
<script>
$(document).ready(function () {
var canvas = document.getElementById('odbCanvas');
paper.setup(canvas);
var path = new paper.Path();
path.strokeColor = 'white';
var start = new paper.Point(100, 100);
path.moveTo(start);
path.lineTo(start.add(0,40));
path.lineTo(start.add(40,40));
path.lineTo(start.add(40,0));
path.lineTo(start.add(0,0));
paper.view.draw();
path.on('mousedrag', function (event) {
this.position = event.point;
});
});
</script>
You can use paper.view.scrollBy(new Point(x, y)) to scroll the whole View
Here's some example code:
// Draw a Rectangle for reference
var rect = new Path.Rectangle(new Point(200, 100), new Point(50, 50))
rect.strokeColor = 'black'
rect.strokeWidth = 1
// Create a Tool so we can listen for events
var toolPan = new paper.Tool()
toolPan.activate()
// On drag, scroll the View by the difference between mousedown
// and mouseup
toolPan.onMouseDrag = function (event) {
var delta = event.downPoint.subtract(event.point)
paper.view.scrollBy(delta)
}
And here's a Sketch for this (drag your mouse on the canvas)
Side note: You don't need to include both paper-core.js and paper-full.js. Use one or the other, depending whether you need PaperScript support as well (paper-full.js includes PS as well).
How do you remove only the shape that's in CreateJS? For my example, I have created a few squares with a function called createSquare. My goal is to have a function, or a click event, that removes only the square that is clicked.
I have tried event listeners and on click, and have had no luck. I have commented out the code that I tried to use.
Here is a link to a working fiddle.
JS is as follows:
var canvas;
var stage;
var square;
function init() {
canvas = document.getElementById("canvas");
stage = new createjs.Stage(canvas);
}
function createSquare(){
square = new createjs.Shape();
square.graphics.beginFill("red").drawRect(0, 0, 50, 50)
square.x = Math.random() * canvas.width;
square.y = Math.random() * canvas.height;
stage.addChild(square);
stage.update();
}
// This code should remove the squares
/*
square.on("click", function(evt) {
stage.removeChild(this);
});
*/
window.onload = init();
createSquare();
createSquare();
createSquare();
createSquare();
createSquare();
createSquare();
Event handlers in CreateJS are passed an event object. Mouse events receive a MouseEvent.
The target of the event will be what was clicked on.
square.on("click", function(evt) {
stage.removeChild(evt.target);
stage.update();
});
You will need to add the listener to each square when it is created.
Alternatively, you could listen to the stage one time.
stage.on("click", function(evt) {
stage.removeChild(evt.target);
stage.update();
});
I am trying to free draw rectangle on canvas.
Here's my JSFiddle.
Code:
var canvas1 = new fabric.Canvas("canvas2");
var freeDrawing = true;
var divPos = {};
var offset = $("#canvas2").offset();
$(document).mousemove(function(e) {
divPos = {
left : e.pageX - offset.left,
top : e.pageY - offset.top
};
});
$('#2').click(function() {
console.log("Button 2 cilcked");
// Declaring the variables
var isMouseDown = false;
var refRect;
// Setting the mouse events
canvas1.on('mouse:down', function(event) {
// Defining the procedure
isMouseDown = true;
// Getting yhe mouse Co-ordinates
// Creating the rectangle object
if (freeDrawing) {
var rect = new fabric.Rect({
left : divPos.left,
top : divPos.top,
width : 0,
height : 0,
stroke : 'red',
strokeWidth : 3,
fill : ''
});
canvas1.add(rect);
refRect = rect; // **Reference of rectangle object
}
});
canvas1.on('mouse:move', function(event) {
// Defining the procedure
if (!isMouseDown) {
return;
}
// Getting yhe mouse Co-ordinates
if (freeDrawing) {
var posX = divPos.left;
var posY = divPos.top;
refRect.setWidth(Math.abs((posX - refRect.get('left'))));
refRect.setHeight(Math.abs((posY - refRect.get('top'))));
canvas1.renderAll();
}
});
canvas1.on('mouse:up', function() {
// alert("mouse up!");
isMouseDown = false;
// freeDrawing=false; // **Disables line drawing
});
});
The problem that I am facing is after drawing a rectangle I am unable to move, resize or at least select the drawn rectangle.
Mistake is you are not adding the object finally when mouse is up. Just change the mouse:up event function like this:
canvas1.on('mouse:up', function() {
// alert("mouse up!");
canvas1.add(refRect);
isMouseDown = false;
// freeDrawing=false; // **Disables line drawing
});
It will work fine. :)
I am also facing the same issue, thanks for the solution provided. If you noticed in this fiddle, duplicate object is creating when moving the shape.
How to solve the issue.
$(document).ready(function(){
//Getting the canvas
var canvas1 = new fabric.Canvas("canvas2");
var freeDrawing = true;
var divPos = {};
var offset = $("#canvas2").offset();
$(document).mousemove(function(e){
divPos = {
left: e.pageX - offset.left,
top: e.pageY - offset.top
};
});
$('#2').click(function(){
console.log("Button 2 cilcked");
//Declaring the variables
var isMouseDown=false;
var refRect;
//Setting the mouse events
canvas1.on('mouse:down',function(event){
//Defining the procedure
isMouseDown=true;
//Getting yhe mouse Co-ordinates
//Creating the rectangle object
if(freeDrawing) {
var rect=new fabric.Rect({
left:divPos.left,
top:divPos.top,
width:0,
height:0,
stroke:'red',
strokeWidth:3,
fill:''
});
canvas1.add(rect);
refRect=rect; //**Reference of rectangle object
}
});
canvas1.on('mouse:move', function(event){
// Defining the procedure
if(!isMouseDown)
{
return;
}
//Getting yhe mouse Co-ordinates
if(freeDrawing) {
var posX=divPos.left;
var posY=divPos.top;
refRect.setWidth(Math.abs((posX-refRect.get('left'))));
refRect.setHeight(Math.abs((posY-refRect.get('top'))));
canvas1.renderAll();
}
});
canvas1.on('mouse:up',function(){
//alert("mouse up!");
canvas1.add(refRect);
isMouseDown=false;
//freeDrawing=false; // **Disables line drawing
});
});
});
JS Fiddle Link here.
http://jsfiddle.net/PrakashS/8u1cqasa/75/
None of the other answer's implementations worked for me. All seem to be un compatible with latest fabric.js versions or have important issues.
So I implemented my own (check the JS in the HTML sources)
https://cancerberosgx.github.io/demos/misc/fabricRectangleFreeDrawing.html?d=9
supports two modes: one that will create and update a rectangle onmousedown and another that won't and only create the rectangle onmouseup
doesn't depend on any other library other than fabric.js (no jquery, no react no nothing)
Doesn't use offsets or event.clientX, etc to track the coordinates. It just uses fabric event.pointer API to compute it. This is safe and compatible since it doesn't depend on the DOM and just on a fabric.js public API
carefully manages event listeners
TODO:
I probably will also add throttle support for mousemove
Thanks
I'm really struggling with the changing of my canvas drawn image so I thought I would see if anyone could assist me on here or offer advice.
I've drawn a static flag in canvas, and I've also drawn a waving flag. I'm trying to get this flag to wave on mouseover.
I initially thought that I was going to have to create two separate files, one for the static and one for the waving aspect. Then save each of them as a jpg/gif image using window.location = canvas.toDataURL("image/");.
But I've just discovered that you can apparently do this all in the same file via jquery/hover. Which seems a lot simpler and a more efficient way of doing it.
Here is the code for the waving flag:
window.onload = function(){
var flag = document.getElementById('banglaFlag');
banglaStatic( flag, 320 );
var timer = banglaWave( flag, 30, 15, 200, 200 );
};
function banglaStatic( canvas, width ){
//Drawing the Bangladesh flag.
//Declaring variables that regard width and height of the canvas.
//Variables C to L are needed for the waving function.
var a = width / 1.9;
var b = 200;
var c = 7*a/13;
var l = a / 13;
canvas.width = b;
canvas.height = a;
var ctx = canvas.getContext('2d');
var radius = 45;
};
function banglaWave( canvas, wavelength, amplitude, period, shading ){
var fps = 30;
var ctx = canvas.getContext('2d');
var w = canvas.width, h = canvas.height;
var od = ctx.getImageData(0,0,w,h).data;
// var ct = 0, st=new Date;
return setInterval(function(){
var id = ctx.getImageData(0,0,w,h);
var d = id.data;
var now = (new Date)/period;
for (var y=0;y<h;++y){
var lastO=0,shade=0;
for (var x=0;x<w;++x){
var px = (y*w + x)*4;
var o = Math.sin(x/wavelength-now)*amplitude*x/w;
var opx = ((y+o<<0)*w + x)*4;
shade = (o-lastO)*shading;
d[px ] = od[opx ]+shade;
d[px+1] = od[opx+1]+shade;
d[px+2] = od[opx+2]+shade;
d[px+3] = od[opx+3];
lastO = o;
}
}
ctx.putImageData(id,0,0);
// if ((++ct)%100 == 0) console.log( 1000 * ct / (new Date - st));
},1000/fps);
}
Thanks in advance for any advice/assistance.
I am not sure where your problem is. I did not see any event handling code, so I assume that's your question:
Define a function to "handle the mouse event". For example, if you want to move the flag when the user moves the mouse over it, define something like:
function mouseMove(event) {
var mouseX,
mouseY;
event.preventDefault(); // stops browser to do what it normally does
// determine where mouse is
mouseX = event.pageX;
mouseY = event.pageY;
// do something useful, e.g. change the flag to waving when mouse is over flag
}
Then, register this function to be called when the mouse moves:
canvas.addEventListener("mousemove", mouseMove, false);
canvas is the canvas you paint the flag on, "mousemove" is the name of the event (many more exist, such as "mousedown", "mouseup", "mouseout" (leaving canvas), "mousewheel", etc.), mouseMove is the name of your function (the event handler, as it's called).
Events are a little different from browser to browser (and even browser version), so you might need to implement different event handler if you need it across browsers.
Hoping this helped...
canvas is like a sheet. there is no any object on which you can hover.
for doing what you wanted to do is just,bound an area on the flag,
follow the 'virtualnobi' answer and calculate if mouse co-ordinate falls on that region,
if true do what ever you want.
like
if (mouseX<100 && mouseX>0 && mouseY>0 && mouseY<100){
//animate the flag
}
use mouseX=event.clientX;
mouseY=event.clientY;
bounded area is x=(0,100) , y=(0,100) here.