Cancel a draggable 'dragmove' on kineticjs? - draggable

I have to set a limit for the movement of a circle when the coordinate 'y' is on the pixel 'y-15', on a specific coordinate (x,y). I've tried to use 'draggable=true' with the event 'mouseup' and 'mousedown', but I can't get the results that I need. Can someone help me, please?
My code is:
circle.on('mouseover',function(){
this.setAttr('draggable',true);
});
circle.on('dragmove',function(e){
var mousePos = stage.getMousePosition();
var x = mousePos.x;
var y = mousePos.y;
if(y < y2- 15){
//do anything
}
else{
this.setAttr('draggable',false);
}
});

If I understand correctly, what you want is dragBoundFunc.
See this tutorial:
http://www.html5canvastutorials.com/kineticjs/html5-canvas-drag-and-drop-bounds-tutorial-with-kineticjs/
// bound below y=50
var blueGroup = new Kinetic.Group({
x: 100,
y: 70,
draggable: true,
dragBoundFunc: function(pos) {
var newY = pos.y < 50 ? 50 : pos.y;
return {
x: pos.x,
y: newY
};
}
});
You'll just have to modify your code to look for y-15 when you grab your mouse coordinates, and set the dragBoundFunc to reflect the coordinates you clicked on.
If you're trying to limit the y-axis on a known fixed y value, then this becomes even easier, exactly like how the tutorial shows you, except you just have to change the coordinate that you want to limit Y to.
Check this one as a quick reference too:
http://www.html5canvastutorials.com/kineticjs/html5-canvas-drag-and-drop-shapes-horizontally-or-vertically-tutorial/

Related

jCanvas method drawRect() position issue

I have a problem with jCanvas which is a framework drawing canvas and jquery.
When I set x = 0 , y = 0 The .drawRect output should be same as the pure javascript result.
I tried the document and google but I did not find anything to solve this.
Screen shoot:
Pure js result
jCanvas result
Please help me.
Many thanks.
// Pure javascript
var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext("2d");
ctx.fillStyle = 'blue';
ctx.fillRect(0, 0, 100, 100);
// jCanvas
$('canvas').drawRect({
fillStyle: '#000',
x: 0, y: 0,
width: 100,
height: 100
});
To run this code, please copy and pass to this sanbox.
https://projects.calebevans.me/jcanvas/sandbox/
From jCanvas documentation:
The [.drawRect's] fromCenter property determines if a rectangle’s x and y properties lie at its center (as opposed to its top-left corner). This property is true by default.
So yeah. Your X and Y with jCanvas, refer to the center of the rectangle, unlike canvas' fillRect X and Y, which refer to the top left corner of the rectangle.

Openlayers 3 pan map always to the left

I am developing an app where I get a user location from the server and I display it on the map.
I am also provided with an angle so I can display in which direction the user is looking.
There is also a possibility to open a sidepanel for some more information. In this situation I have to move the map center left which I do like this.
var center = map.getView().getCenter();
var pan = ol.animation.pan({
duration: 500,
source: (center)
});
if (isSidePanelVisible) {
center[0] += 1000;
} else {
center[0] -= 1000;
}
map.beforeRender(pan);
map.getView().setCenter(center);
This works great while the user is "looking" north but not when I rotate the map by an angle. Is there a quick way to pan the map always left by a certain amount regardles of angle?
You could use ol.Map.html#getPixelFromCoordinate to convert the center to pixel coordinates, do your calculation and then convert back to real coordinates with ol.Map.html#getCoordinateFromPixel:
var view = map.getView();
var center = view.getCenter();
var centerInPx = map.getPixelFromCoordinate(center);
var newCenterInPx = [centerInPx[0] - 100, centerInPx[1]];
var newCenter = map.getCoordinateFromPixel(newCenterInPx);
view.setCenter(newCenter);
http://jsfiddle.net/6mh110xv/1/
To pan left , right , bottom , top , you can use the following code :
panMap(direction: string) {
let newCenterInPx;
let center = map.getView().getCenter();
let centerInPx = map.getPixelFromCoordinate(center);
switch (direction) {
case 'left': newCenterInPx = [centerInPx[0] - 100, centerInPx[1]]; break;
case 'right': newCenterInPx = [centerInPx[0] + 100, centerInPx[1]]; break;
case 'top': newCenterInPx = [centerInPx[0], centerInPx[1] - 100]; break;
case 'bottom': newCenterInPx = [centerInPx[0], centerInPx[1] + 100]; break;
}
var newCenter = map.getCoordinateFromPixel(newCenterInPx);
map.getView().setCenter(newCenter);
}

How do I draw horizontal bars with a label using either ChartJS or D3?

What's the best way of drawing multiple horizontal lines and labels for a simple line graph in either ChartJS or D3? I know that I could draw these as individual lines and then do a text overlay but I'm wondering if there is a simpler solution. Ideally I'd be able to create each of the labels below as one unit and move it anywhere.
If this is simpler in another JS graph library then feel free suggest.
Example below
To do it with Chart.js you have to extend the line chart
Chart.types.Line.extend({
name: "LineAlt",
initialize: function (data) {
// it's easier to programmatically update if you store the raw data in the object (vs. storing the geometric data)
this.marks = data.marks;
this.marks.xStart = Number(data.labels[0]);
this.marks.xStep = data.labels[1] - data.labels[0];
// make sure all our x labels are uniformly apart
if (!data.labels.every(function (e, i, arr) { return !i || ((e - arr[i - 1]) === this.marks.xStep); }, this))
throw "labels must be uniformly spaced";
Chart.types.Line.prototype.initialize.apply(this, arguments);
},
draw: function () {
Chart.types.Line.prototype.draw.apply(this, arguments);
// save existing context properties
var self = this;
var ctx = self.chart.ctx;
var scale = self.scale;
ctx.save();
// line properties
ctx.lineWidth = 1;
ctx.fillStyle = "#666";
ctx.strokeStyle = "#666";
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
ctx.font = scale.font;
// draw marks
self.marks.forEach(function (mark) {
// assuming that the marks are always within the data range
var y = scale.calculateY(mark.y);
var x1 = scale.calculateX((mark.x1 - self.marks.xStart) / self.marks.xStep);
var x2 = scale.calculateX((mark.x2 - self.marks.xStart) / self.marks.xStep);
// draw line
ctx.beginPath();
ctx.moveTo(x1, y);
ctx.lineTo(x2, y);
// draw edges
ctx.moveTo(x1, y + 10);
ctx.lineTo(x1, y - 10);
ctx.moveTo(x2, y + 10);
ctx.lineTo(x2, y - 10);
ctx.stroke();
// draw text
ctx.fillText(mark.label, (x1 + x2) / 2, y + scale.fontSize * 1.5);
})
ctx.restore();
},
});
You pass in the data for drawing the lines like so
var data = {
...
marks: [
{
x1: 1.5,
x2: 3.5,
y: 50,
label: 'Label1'
},
{
x1: 5,
x2: 7,
y: 60,
label: 'Label2'
}
]
};
and you create the chart using this extended chart type
var myLineChart = new Chart(ctx).LineAlt(data);
You can update the lines like this
myLineChart.marks[0].y = 80;
myLineChart.marks[0].x1 = 9;
myLineChart.marks[0].x2 = 10;
and then call
myLineChart.update();
to reflect those changes on the canvas
Caveats
The (x axis) labels should be numeric and uniformly spaced.
The lines should be within the scale range of the y axis (alternatively you can do a scaleOverride to set the scale parameters so that the lines are within the y scale range)
Fiddle - http://jsfiddle.net/en92k763/2/

rotate to mouse kinetic js

I looked at many examples but so far nothing worked. I want the circle to rotate on mousemove and it is rotating centered, so no problems so far. But, it does a 180 jump when I pass half of the stage. So everything is fine till I pass the half of the stage, clearly I'm missing something. Math.atan2 gives me an error: the circle jumps to the (0,0) of the stage.
Please help I really need this badly.
Thanks in advance!
new Kinetic.Tween({
node: cGrad1,
x: stage.getWidth()/2,
y: stage.getHeight()/2,
duration: 1,
opacity:1,
easing: Kinetic.Easings.EaseInOut
}).play();
clickO.on('mousemove', function() {
for(var n = 0; n < 16; n++) {
var shape = cGradlayer1.getChildren()[n];
var stage = shape.getStage();
var mousePos = stage.getMousePosition();
var x = mousePos.x - shape.getPosition().x;
var y = mousePos.y -shape.getPosition().y ;
var degree = (Math.PI)+(Math.atan(y/x));
shape.setAttrs({
rotation: degree
})
cGradlayer1.draw()
}
})
Well this is what I came up with, and hopefully it's close to what you were looking for: jsfiddle
Basically, to calculate the angle you want to rotate to, we need to store two points:
The origin of the shape (centre coordinate)
The coordinate of the mouse click
Once you have that, you can calculate the angle between the two points with a little bit of trigonometry (Sorry if I am not accurate here, Trigonometry is not my strong suit). Calculate the distance between the two points (dx, dy) and then use the trig formula to find the angle in degrees.
layer.on('click', function() {
var mousePos = stage.getMousePosition();
var x = mousePos.x;
var y = mousePos.y;
var rectX = rect.getX()+rect.getWidth()/2;
var rectY = rect.getY()+rect.getHeight()/2;
var dx = x - rectX;
var dy = y - rectY;
var rotation = (Math.atan2(dy, dx)*180/Math.PI+360)%360;
var rotateOnClick = new Kinetic.Tween({
node: rect,
duration: 1,
rotationDeg: rotation,
easing: Kinetic.Easings.EaseInOut
});
rotateOnClick.play();
});
EDIT:
Based off the gathered information below (which I came to the same conclusion as) I have updated my fiddle: jsfiddle
As markE mentioned below in the comments, KineticJS does not support "force-clockwise flag", so the rotation always jumps when rotating past 360 in the clockwise direction, or past 0 in the counter clockwise position. Otherwise, we know that the rotation works properly.
So, to fix this manually there are two cases we need to consider:
When we rotate past 360 in the clockwise direction.
When we rotate past 0 in the counter clockwise direction.
And this is the math I used to calculate whether to counter the rotation or not:
var currentDeg = rect.getRotationDeg();
var oneWay = rotation - currentDeg;
var oneWayAbsolute = Math.abs(rotation - currentDeg);
var otherWay = 360-oneWayAbsolute;
if (otherWay < oneWayAbsolute) {
//Take the other way
if (oneWay > 0) {
//Clicked direction was positive/clockwise
var trueRotation = currentDeg - otherWay;
} else {
//Clicked direction was negative/counter clockwise
var trueRotation = currentDeg + otherWay;
}
} else {
//Take the clicked way
var trueRotation = rotation;
}
Basically we want to figure out which way to rotate, by comparing the angle degrees of which direction would be closer, the direction we clicked in, or the opposite way.
If we determined that the otherWay was closer to the currentDeg, then we need to see if the direction we clicked in was in the counter clockwise (negative) or clockwise (positive) direction, and we set the otherWay direction to go in the opposite direction.
And then you can normalise the rotationDeg onFinish event.
var rotateOnClick = new Kinetic.Tween({
node: rect,
duration: 1,
rotationDeg: trueRotation,
easing: Kinetic.Easings.EaseInOut,
onFinish: function() {
trueRotation = (trueRotation+360)%360;
rect.setRotationDeg(trueRotation);
layer.draw();
}
});
You might need to set the x and y position of the Tween as follows:
new Kinetic.Tween({
x: mousePos.x,
y: mousePos.y,
node: shape,
rotation: degree,
easing: Kinetic.Easings.EaseInOut,
duration:1,
}).play();
See this tutorial for reference http://www.html5canvastutorials.com/kineticjs/html5-canvas-stop-and-resume-transitions-with-kineticjs/

kineticjs rotate to mouseposition [duplicate]

I looked at many examples but so far nothing worked. I want the circle to rotate on mousemove and it is rotating centered, so no problems so far. But, it does a 180 jump when I pass half of the stage. So everything is fine till I pass the half of the stage, clearly I'm missing something. Math.atan2 gives me an error: the circle jumps to the (0,0) of the stage.
Please help I really need this badly.
Thanks in advance!
new Kinetic.Tween({
node: cGrad1,
x: stage.getWidth()/2,
y: stage.getHeight()/2,
duration: 1,
opacity:1,
easing: Kinetic.Easings.EaseInOut
}).play();
clickO.on('mousemove', function() {
for(var n = 0; n < 16; n++) {
var shape = cGradlayer1.getChildren()[n];
var stage = shape.getStage();
var mousePos = stage.getMousePosition();
var x = mousePos.x - shape.getPosition().x;
var y = mousePos.y -shape.getPosition().y ;
var degree = (Math.PI)+(Math.atan(y/x));
shape.setAttrs({
rotation: degree
})
cGradlayer1.draw()
}
})
Well this is what I came up with, and hopefully it's close to what you were looking for: jsfiddle
Basically, to calculate the angle you want to rotate to, we need to store two points:
The origin of the shape (centre coordinate)
The coordinate of the mouse click
Once you have that, you can calculate the angle between the two points with a little bit of trigonometry (Sorry if I am not accurate here, Trigonometry is not my strong suit). Calculate the distance between the two points (dx, dy) and then use the trig formula to find the angle in degrees.
layer.on('click', function() {
var mousePos = stage.getMousePosition();
var x = mousePos.x;
var y = mousePos.y;
var rectX = rect.getX()+rect.getWidth()/2;
var rectY = rect.getY()+rect.getHeight()/2;
var dx = x - rectX;
var dy = y - rectY;
var rotation = (Math.atan2(dy, dx)*180/Math.PI+360)%360;
var rotateOnClick = new Kinetic.Tween({
node: rect,
duration: 1,
rotationDeg: rotation,
easing: Kinetic.Easings.EaseInOut
});
rotateOnClick.play();
});
EDIT:
Based off the gathered information below (which I came to the same conclusion as) I have updated my fiddle: jsfiddle
As markE mentioned below in the comments, KineticJS does not support "force-clockwise flag", so the rotation always jumps when rotating past 360 in the clockwise direction, or past 0 in the counter clockwise position. Otherwise, we know that the rotation works properly.
So, to fix this manually there are two cases we need to consider:
When we rotate past 360 in the clockwise direction.
When we rotate past 0 in the counter clockwise direction.
And this is the math I used to calculate whether to counter the rotation or not:
var currentDeg = rect.getRotationDeg();
var oneWay = rotation - currentDeg;
var oneWayAbsolute = Math.abs(rotation - currentDeg);
var otherWay = 360-oneWayAbsolute;
if (otherWay < oneWayAbsolute) {
//Take the other way
if (oneWay > 0) {
//Clicked direction was positive/clockwise
var trueRotation = currentDeg - otherWay;
} else {
//Clicked direction was negative/counter clockwise
var trueRotation = currentDeg + otherWay;
}
} else {
//Take the clicked way
var trueRotation = rotation;
}
Basically we want to figure out which way to rotate, by comparing the angle degrees of which direction would be closer, the direction we clicked in, or the opposite way.
If we determined that the otherWay was closer to the currentDeg, then we need to see if the direction we clicked in was in the counter clockwise (negative) or clockwise (positive) direction, and we set the otherWay direction to go in the opposite direction.
And then you can normalise the rotationDeg onFinish event.
var rotateOnClick = new Kinetic.Tween({
node: rect,
duration: 1,
rotationDeg: trueRotation,
easing: Kinetic.Easings.EaseInOut,
onFinish: function() {
trueRotation = (trueRotation+360)%360;
rect.setRotationDeg(trueRotation);
layer.draw();
}
});
You might need to set the x and y position of the Tween as follows:
new Kinetic.Tween({
x: mousePos.x,
y: mousePos.y,
node: shape,
rotation: degree,
easing: Kinetic.Easings.EaseInOut,
duration:1,
}).play();
See this tutorial for reference http://www.html5canvastutorials.com/kineticjs/html5-canvas-stop-and-resume-transitions-with-kineticjs/

Resources