I have a circle added to a layer. In the top of the layer I added a text. I would like to run an animation when the mouse is over the circle, but when the mouse reaches the text the mouseout callback function is called. How can I prevent that?
var circle = new Kinetic.Circle({
x: j * xcenterstep + xshift,
y: i * ycenterstep + yshift,
radius: t_radius,
fill: t_fill,
stroke: t_stroke,
strokeWidth: t_stroke_w,
strokeOpacity: 0.1,
opacity: 0.3 + t_number * 0.05,
});
if (t_number) {
circle.tw;
circle.on("mouseover", function () {
this.tw = new Kinetic.Tween({
node: this,
duration: 0.3,
strokeWidth: 6
});
this.tw.play();
});
circle.on("mouseout", function () {
this.tw.reverse();
});
}
// Adding the text
var radiusText = new Kinetic.Text({
x : circle.getX(),
y : circle.getY(),
text : t_number,
fontSize : radius,
fill : '#fff',
fontStyle: 'bold',
align : 'center'
});
radiusText.setOffset({
x : radiusText.getWidth()/2,
y : radiusText.getHeight()/2
});
bgLayer.add(circle);
bgLayer.add(radiusText);
I think it is better to use mouseenter event. You can disable text's events to prevent mouseout from circle.
radiusText.listening(false)
Reviewing your code, you were missing a } to close the if (t_number) {. I am not sure if it was supposed to encompass the mouseover and mouseout events, but it might have caused your code to respond differently than you are expecting.
Related
I have a little problem with my "app" using google maps. I just want to dynamic add a rectangle into my map and each rectangle add a little event...
My code:
google.maps.event.addListener(this.canvas, "click", function(event)
{
var left = event.latLng.lng() - 0.1;
var right = event.latLng.lng() + 0.1;
var top = event.latLng.lat() - 0.1;
var bottom = event.latLng.lat() + 0.1;
var rectangle = new google.maps.Rectangle({
bounds: {north: top, south: bottom, east: right, west: left},
editable: true,
draggable: true,
fillColor: 'blue',
strokeColor: 'blue'
});
rectangle.setMap(map.canvas);
rectangle.addListener("rightclick", function ()
{
if(rectangle.editable)
{
rectangle.setOptions({
editable: false,
draggable: false,
fillColor: "black",
strokeColor: "black"
});
}
else
{
rectangle.setOptions({
editable: true,
draggable: true,
fillColor: "blue",
strokeColor: "blue"
});
}
});
});
All what I want is just add new rectangle after click, and when I use right click -> enable / disable rectangle...
This code works fine, but when I lock one or more rectangles, all rectangles does not move and they are !draggable.
Can you help me with this? Thanks!
live demo : https://jsfiddle.net/3fuf5bqo/ just 2x click on the map (create 2 rectangles) and after this just click (right click) on one of them - both of them does not move
HMMMM, the problem was in "rightclick" event, when I use just "click" or "dbclick" the problem was solved... I do not get it... :-D but it works
I have the following code which creates me rectangle that contains some text. I need to create multiple addressable instances of this rectangle so that I can individually animate them. Each rectangle needs to contain a different text label.
var s = Snap(800, 600);
var block = s.rect(50, 50, 100, 100, 5, 5);
block.attr({
fill: "rgb(236, 240, 241)",
stroke: "#1f2c39",
strokeWidth: 3
});
var text = s.text(70, 105, "Hello World");
text.attr({
'font-size':20
});
block.attr({
width: (text.node.clientWidth + 50)
});
Rather than repeating my code I would like to create a function that accepts the text and the coordinates for placing the rectangle. What is the best way to achieve this ? Is this capability already included within snap.svg ?
UPDATE
I created another plugin, this time to import and scale SVG images. Is this the best approach to take for this ? Is the only way to scale the image using the `transform attribute ?
Import SVG plugin example.
Snap.plugin( function( Snap, Element, Paper, global ) {
Paper.prototype.importImage = function( x, y, scale ) {
var ig1 = s.group();
var image = Snap.load("../package.svg", function ( loadedFragment ) {
ig1.attr({transform: 'translate(' + x + ',' + y + ') scale('+ scale +')'});
ig1.append( loadedFragment);
} );
return ig1;
}
});
You could create a plugin to give you a new element option that does it for you, for example...
Snap.plugin( function( Snap, Element, Paper, global ) {
Paper.prototype.textRect = function( text, x, y ) {
var block = s.rect(x, y, 100, 100, 5, 5)
.attr({
fill: "rgb(236, 240, 241)",
stroke: "#1f2c39",
strokeWidth: 3,
});
var text = s.text(x + 20, y + 50, text).attr({ 'font-size': 20 });
block.attr({ width: (text.node.clientWidth + 50) });
}
});
var s = Snap(800,800)
s.textRect('Hi', 100, 100 );
s.textRect('There', 100, 200 );
example fiddle
You may want to put them both in a 'g' group element if you will move them around or drag them or something, so you can perform operations on the group.
currently i have a problem displaying my whole image with my puzzle and with the "click" rotation it had a bug which when i click one piece other piece also rotates why? Can anyone help me see my fiddle and help me with it? thanks so much
fillPatternImage:imageObj,
x:-pieceWidth*i,
y:-pieceHeight*j,
stroke: "#000000",
strokeWidth: 4,
lineCap: "round",
rotation : Math.PI * 0.5 * Math.floor(Math.random() * 4),
draggable: true,
offset: [pieceWidth/2,pieceHeight/2],
x: pieceWidth*i+pieceWidth/2 + (Math.random()*2)*((stage.getWidth()+pieceWidth)/20),
y: pieceHeight*j+pieceHeight/2 + (Math.random()*2)*((stage.getHeight()+pieceHeight)/20),
});
piecesArray[i][j].shape.on("mousedown", function(){
this.moveToTop();
});
piecesArray[i][j].shape.on("click", function(){
this.moveToTop();
this.rotateDeg(90)
});
My JsFiddle : http://jsfiddle.net/e70n2693/
Thanks
piecesArray[i][j].shape.on("click", function(){
this.moveToTop();
this.rotateDeg(90)
layer.draw();
});
http://jsfiddle.net/e70n2693/2/
I've been having some trouble with adding an event listener to a concentric group of circles. My intended functionality is this: when the mouse is over the group, a new black dot (a "Bullseye" -- circle3 in the code below) should appear at the center of the group. When the mouse is not above the group, black dot should not appear.
The following code comes close to accomplishing this:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.4.min.js"></script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer({});
var group = new Kinetic.Group({
x: 0, //
y: 0 //
});
var circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
var circle2 = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 50,
fill: 'white',
stroke: 'black',
strokeWidth: 4
});
var circle3 = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 20,
fill: 'black',
stroke: 'black',
strokeWidth: 4,
visible: false
});
group.add(circle);
group.add(circle2);
group.add(circle3);
group.on("mouseenter", function(event){
circle3.setVisible(true);
stage.draw();
});
group.on("mouseleave", function(event){
circle3.setVisible(false);
stage.draw();
});
// add the shape to the layer
layer.add(group);
// add the layer to the stage
stage.add(layer);
</script>
</body>
</html>
However, the problem is that "bulleye" flickers as it leaves the outercircle (circle) and enters the inner circle (circle2).
(*) I have tried various solutions -- but nothing seems to be working. For one, I tried to capture the mouseposition (layerX and layerY) and detect a collision with the group region on the canvas. That is, if x and y are within its boundaries, I paint the bullseye. Otherwise, I get rid of it. However, the problem with this solution is that the bullseye is sometimes orphaned in the group even if the mouse has left the group. That is because the mouseout/mouseleave event sometimes has a layerX or layerY position that is still within the circle.
(*) Using mouseover and mouseout instead of mouseenter/mouseleave doesn't seem to affect anything.
(*) I can't add the eventlistener to the outer circle alone, since that makes the bullseye disappear when the mouse is over the innercircle.
You can prevent the flickering by turning off event listening for the nested circles, like so:
group.add(circle);
group.add(circle2);
group.add(circle3);
// Don't listen for any events (e.g. mouseenter/leave) on the inner circles
circle2.setListening(false);
circle3.setListening(false);
It fixes the issue you describe, but I'm not sure if you need to listen for other events on those circles... If so, you may need to cancel propagation of events from the inner circles.
I'm working on a board game with kineticjs and I'm facing a problem with mouse handling.
I have an image with a mousemove event that draw a preview selection.
The problem is with the click event on the same image that is firing only 1 on 9 times..
If I remove the on_mousemove the on_click is working perfectly..
Anyone has an explanation and/or workaround ?
Thanks
Edit
Fiddle link: http://fiddle.jshell.net/gTuCE/12/
Your code was a bit messy so I cleaned it up and it's working now: jsfiddle
In your function createSquareItem(), squareLayer was undefined.
You only have to add Kinetic.Layers once. In both your createSquareItem createTemporarySquareItems functions, you were adding mainLayer to the stage every time you call the function. This is wrong since you already added mainLayer to the stage earlier.
In your createTemporarySquareItems function, I had to add mainLayer.drawScene() and in createSquareItem I had to add mainLayer.draw()
function createSquareItem(point, color) {
var boardPoint = point;
var rect = new Kinetic.Rect({
x: boardPoint.x,
y: boardPoint.y,
width: 18,
height: 18,
fill: color,
stroke: 'black',
strokeWidth: 0
});
mainLayer.add(rect);
//squareLayer.drawScene(); //squareLayer is undefined.
mainLayer.draw();
}
function createTemporarySquareItems(point, cleanLayer) {
if (cleanLayer == true) {
do {
var r = tempSquareArray.pop();
if (r != null) {
//tempSquareLayer.remove(r);
r.destroy();
}
} while (r != null);
}
var boardPoint = point;
var rect = new Kinetic.Rect({
x: boardPoint.x,
y: boardPoint.y,
width: 18,
height: 18,
fill: 'orange',
stroke: null,
strokeWidth: 0
});
tempSquareArray.push(rect);
mainLayer.add(rect);
mainLayer.drawScene();
}
For more information on KineticJS' draw methods, see here: What is the difference between KineticJS draw methods?