Snap to grid the dragged element with Google closure library - closures

Please,
how to make in Google Closure Library draggable element and snap to grid?
Example: jQueryUI has option grid:
$(".selector").draggable({grid: [50, 20]});

I needed to do this in my project, so posting the solution (although I am sure there are many). My approach was to inherit the goog.fx.Dragger class and extend:
constructor for supporting the grid parameters
default action for doing the actual snapping
The code follows:
SnapDragger = function(target, grid, opt_handle, opt_limits) {
goog.base(this, target, opt_handle, opt_limits);
this.grid = grid;
}
goog.inherits(SnapDragger, goog.fx.Dragger);
SnapDragger.prototype.defaultAction = function(x, y) {
x = Math.round(x / this.grid.x) * this.grid.x;
y = Math.round(y / this.grid.y) * this.grid.y;
goog.base(this, 'defaultAction', x, y);
}
You would then use the SnapDragger the same way as goog.ui.Dragger
var dragger = new SnapDragger(element, {x: 20, y: 50});

Related

How to get clicked element's position and id to change color and draw lines on it

I'm developing a basic window frame configurator. I splitted glasses in function below. I want to change color when i clicked and get the position of clicked glass to draw openin direction lines.
I tried to understand and implement Lavrton's method(https://codesandbox.io/s/0xj7zml2zl?file=/src/index.js) but i couldn't succeed.
function glassDraw(piece, frameWidth, frameHeight) {
var glassGroup = new Konva.Group();
for (i = 0; i <piece; i++) {
var glass = new Konva.Rect({
name: 'Rect',
x: padding + (frameWidth / piece) * i,
y: padding,
width: frameWidth / piece,
height: frameHeight - padding * 2,
fill: 'lightblue',
id: 'glass'+i,
});
glassGroup.add(glass);
}
glassGroup.find("Rect").on('click', function (e) {
// get id of the cube i drag
var clickedId = e.target.attrs.id;
$('#theId').html(clickedId);
})
return glassGroup;
}
When i use getelementbyid method with id of konva element("glass"+i), it returns null. I think i need to get as a konva element.
You have to create a click listener for all of your rectangles.
for (let rect of glassGroup.children) {
rect.on('click', () => {
console.log(rect.x(), rect.y()); // current position of the object
console.log(rect.id()); // log id of the object
rect.fill('green'); // set color to green
layer.batchDraw(); // update layer (batchDraw just for better performance .draw() would work to)
})
}
Make sure you always update the stage by either call stage.draw() or layer.draw() (or batchDraw() for better performance) after changing something, otherwise your stage will not show anything of what you do.
If something with this code don't work feel free to ask.
Have a nice day.

Konva - visualize custom hit area

Is there an easy way to visualize a custom hit area shape?
As described here
https://konvajs.github.io/docs/events/Custom_Hit_Region.html
the hitFunc attribute can be set to a function that uses the supplied context to draw a custom hit area / region. Something like this:
var star = new Konva.Star({
...
hitFunc: function (context) {
context.beginPath()
context.arc(0, 0, this.getOuterRadius() + 10, 0, Math.PI * 2, true)
context.closePath()
context.fillStrokeShape(this)
}
})
For debugging purposes, I would like an easy way to toggle visual rendering of the shape (circle in this case), eg by filling it yellow.
Thanks :)
Currently, there is no public API for that. But you still can add hit canvas into the page somewhere and see how it looks:
const hitCanvas = layer.hitCanvas._canvas;
document.body.appendChild(hitCanvas);
// disable absolute position:
hitCanvas.style.position = '';
http://jsbin.com/mofocagupi/1/edit?js,output
Or you can add hit canvas on top of the stage and apply an opacity to make scene canvases visible:
const hitCanvas = layer.hitCanvas._canvas;
stage.getContainer().appendChild(hitCanvas);
hitCanvas.style.opacity = 0.5;
hitCanvas.style.pointerEvents = 'none';
http://jsbin.com/gelayolila/1/edit?js,output

Highcharts: Positioning the toolip with chart.plotLeft

In the highchart documentation is says:
positioner: Function
A callback function to place the tooltip in a default position. The callback receives three parameters: labelWidth, labelHeight and point, where point contains values for plotX and plotY telling where the reference point is in the plot area.
Add chart.plotLeft and chart.plotTop to get the full coordinates.
http://api.highcharts.com/highcharts#tooltip.positioner
But I'm not sure where I am supposed to add plotLeft, or plotTop
I don't see it on the scope, and I can't see it in the "chart" property options.
Can anyone explain?
Example for you: http://jsfiddle.net/j92p2/
tooltip: {
positioner: function (w, h, p) {
var chart = this.chart, // get chart
plotLeft = chart.plotLeft, // get plotLeft
plotTop = chart.plotTop; // get plotTop
console.log(this, plotTop, plotLeft); // watch console while hovering points
return { x: 80, y: 50 };
}
}
See inline comments. Let me know if you have any more questions.

highcharts 3 addPoint Point order

In Highcharts 2, it was easy to add a point using series.addPoint(p) where the x value of that point fell between the x-values of two existing points.
Example: Let's say you wanted to create a chart with one series containing two points:
var p1 = {x: 100, y: 50};
var p2 = {x: 200, y: 40};
var data = [];
data.push(p1);
data.push(p1);
var c = new Highcharts.Chart({
...//code omitted
type: 'line',
data: data,
...//code omitted
});
In version two you could call add a point between those two by going:
var p3 = {x: 150, y: 60};
c.series[0].addPoint(p3, true);
For 'line' charts, highcharts 2 would automatically determine that the x value of p3 falls between the x values of p1 and p2 and so the line would be plotted through the points in the order: p1, p3, p2.
We are finding that in highcharts 3, the line gets plotted through the points in the order p1, p2, p3 - which implies that it "turns back on itself".
I have prepared the following jsFiddle examples, which add 50 points to an existing series with randomized x and y value.:
Highcharts 2.1.9: http://jsfiddle.net/HdNh2/4/
Highcharts 3.0.0: http://jsfiddle.net/HdNh2/5/
Is this something that could be fixed or do we need to try and circumvent the issue?
Thanks in advance...
H
So just to close this issue: Highcharts has confirmed that the logic changed since 2.2.x.
In our case it was simple enough to just re-render the entire chart, but I suspect series.setData() would also have been an option.
Here's a workaround. This will sort points on their x-values as they're added manually. This events object is in the chart object options block.
events: {
click: function(e) {
// find the clicked values and the series
var series = this.series[DIA.currentSeriesIndex],
x = parseFloat(e.xAxis[0].value),
y = parseFloat(e.yAxis[0].value);
// Add it
series.addPoint([x, y]);
if ( series.data.length > 1) {
// grab last point object in array
var point = series.data[series.data.length-1];
// sort the point objects on their x values
series.data.sort(function (a, b)
{
//Compare "a" and "b" and return -1, 0, or 1
return (a.x - b.x);
});
// force a redraw
point.update();
}
}
}

JQplot tooltip for multiple y axes

For a JQplot chart with 2 y axes, I am able to set the tooltip but when i hover over a datapoint i need to know to which y axis the tooltip belongs. I need this so that i can display the tooltip after multiplying with the appropriate scale factor. The code i tried is shown below. I thought y will be null when we hover over a data point belonging to y2 axis. But y is never null.
$("#"+sTargetId).bind('jqplotcustomDataMouseOver',
function (ev, seriesIndex, pointIndex, data) {
var chart_left = $("#"+sTargetId).offset().left,
chart_right = ($(window).width() - ($("#"+sTargetId).offset().left + $("#"+sTargetId).outerWidth())),
chart_top = $("#"+sTargetId).offset().top,
x = oPlot.axes.xaxis.u2p(data[0]),
y = oPlot.axes.yaxis.u2p(data[1]),
y2 = oPlot.axes.y2axis.u2p(data[1]);;
if(y===null|| y===undefined){ //this condition doesnt work
var tooltipDataYaxis = data[1]*scaleYaxis1;
var sYDisplay = this.sYAxis1MeasureName;
$('#tooltip').css({left:chart_left+x, top:chart_top+y, marginRight:chart_right});
}
else{
tooltipDataYaxis = data[1]*scaleYaxis2;
sYDisplay = this.sYAxis2MeasureName;
$('#tooltip').css({left:chart_left+x, top:chart_top+y2, marginRight:chart_right});
}
$('#tooltip').html(
'<span style="font-family: Arial;font-size:'+sTooltip+';font:bold;color:#000000;">'+ sYDisplay+': ' + tooltipDataYaxis +'</span>');
$('#tooltip').show();
});
$("#"+sTargetId).bind('jqplotcustomDataUnhighlight',
function (ev, seriesIndex, pointIndex, data) {
$('#tooltip').empty();
$('#tooltip').hide();
});
}
The variable seriesIndex will help to identify which series the tooltip belongs to. :)
I was just playing with jqplot for the first time. quite fun.
In the highlighter plugin jqplot.highlighter.js
I extended it on line 336
elem.html(str + " component:"+neighbor.data[2]);
You might use Chrome developer tools to get the data model at this point and look at the contents of the neighbor object.
(scope variables > Local > neighbor > data )
That's how I did it anywho. Hope it helps.

Resources