How to determine which (object) control has been clicked? - fabricjs

I'm after some advice re "how to determine which (object) control has been clicked"?
On mouse:over I hide the corner controls (and the border):
Image -> https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/my-2d-diagram-editor-with-ports.png
On mouse:down I use getCenterPoint() (of the mouse:over target) to start drawing a line:
Image -> https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/my-2d-diagram-editor-with-connections.png
On mouse:move I update the (connector) lines x2 and y2, and on mouse:up I use getCenterPoint() (of the mouse:over target) as the line's end point.
What I would like to do is use the nearest connect point (ml, mt, mr, mb) rather than getCenterPoint().

update to latest fabric js if your application allows it, because this fix is recent.
then on mouse up you can check for:
object.__corner
That should have value 'mt', 'mr'... and so on.
Be carefull that if i'm not wrong fabricjs check first for object, and then if it fails it check for corner click.
(target.containsPoint(xy) || target._findTargetCorner(pointer))
It means that it will first check for the bounding box and then for the corners. In other words the corner targeting will work just in the outer part of the corner.

Related

Wrong TileMap coordinates on zoom with InputEventScreenTouch

The goal is to enable the player to drow the patch for the character.
So I start with simple think, set value for cell(0, 0) in tilemap
and replace the value when the user clicks on it
and it works as expected.
But when I change the camera zoom and try it again it set value in another cell:
I was trying to multiple/divide the click position by the zoom value but it also not resolve the problem
Can anyone give me the hint on how should I handle that?
repo: Github
Once you zoom, the coordinates you get from the input event (screen coordinates) do not match the world.
If you have an input event, the recommended way to do this is with make_input_local:
tilemap.world_to_map(tilemap.make_input_local(event).position)
However, if you don't, but you have screen coordinates, you can do this:
var transform = tilemap.get_canvas_transform() * tilemap.get_global_transform()
tilemap.world_to_map(transform.affine_inverse() * screen_coordinates)

How do I get the elementView size of UML classes using JointJS?

I'm implementing the class diagram where the users can change the class' name, attributes and methods. I'm having trouble with resizing the class rectangle width depending on name, attribute or method length. These can overflow and go outside the rectangle, and I just can't find a method to get the correct size.
I also have added an element tool to the elementView, and set its x and y to "100%". According to documentation: "Use percentage strings (e.g. '40%') to position the button relatively to the element width/height." but I guess this isn't the model's size, as I typed JSON.stringify(graph.toJSON()) and got the following.
JSON.stringify(graph.toJSON())
The size is the default value I set (260x100).
I checked the size of the attribute using DevTools:
Size of attribute
The gray button detects the width number I need (330), so I guess that the x in element tools is the elementView's width. I looked at the documentation and can't find any method like .size() or .getSize() for the elementView. I need to resize the rectangle to the size of Max(name length, attribute length, method length) + some aditional space to not look cramped up. I have seen some solutions like "Use [number of letters] * [some constant]" but that is no good as typing 5 "W"s doesn't take the same space as typing 5 "i"s.
So how do I get the width of the whole element (in my case 330 from text length + the three pixels from the left border of the rectangle to the first text letter)?
Okay, so after searching through several Google Groups chats I found some pieces of code that helped me.
For getting the width I needed, I used elementView.getBBox().width.
Where I didn't have the element view right at hand, I at least had the model ID, and so I used paper.findViewByModel(modelId) to get the element view.

Check if polygon is completely filled by other polygons

I'm currently creating a map in Openlayers for a customer that requires validation for drawing polygons inside another polygon (base-area). By using JSTS and Openlayers native methods, i'm able to validate that all shapes are drawn inside the polygon, and do not intersect with other shapes inside the polygon. This includes markers and polygons.
Another requirement is to check if the base-area is completely filled by other polygons, with pre-defined margins. I've not been able to think of any way to do this yet. What would be a good way to accomplish this?
EDIT:
Methods i used to check if polygon contains other polygon:
const geoJSONFormat = new GeoJSON();
const jstsGeoJSONReader = new jsts.io.GeoJSONReader();`
polygon1 = jstsGeoJSONReader.read(geoJSONFormat.writeFeatureObject(feature1)).geometry;
polygon2 = jstsGeoJSONReader.read(geoJSONFormat.writeFeatureObject(feature2)).geometry;
polygon1ContainsPolygon2= polygon1.contains(polygon2); `
First i pass the given feature the geoJSONFormat.writeFeatureObject which is imported from OL. And then assign this to a variable using the JSTS GeoJSON-reader.
contains-method from JSTS will return a boolean indicating if polygon2 is contained inside polygon1
Since you've already validated the polygons are inside the base-area and that they aren't overlapping. To check the base-area is completely filled, just check the sum of the area of the polygons is equal to the base-area.
I'm not entirely sure what you mean by margin but you could check the sum of the area of the polygons is at least some x% of the area of the base-area to give some "wiggle" room.

Set z-index of shapes in a Kinetic.Group

How do I set z-index on the shapes that I'm adding to Kinetic.Group? My group contains rectangles and images. I want to do this:
rectangle.setZIndex(1);
image.setZIndex(2);
This gives me the following error: Uncaught TypeError: Cannot read property 'children' of undefined.
I'm using drag and drop and then grouping the objects together. I want the images to be on top of the rectangle. the moveToTop() method gives errors when I call it inside my code.
EDIT :
http://jsfiddle.net/Dcevd/ . Try this use case: drag&drop two rects, then drag the image and drop it on the first rect, then move it to the second one (when you do it inversely it works). it moves to top only on dragend.
Answer to your edit
You are calling moveToTop() on a child of the group, so it will only put the image on the op of that specific group. Once you place the second rectangle on the right stage, it gets a higher z-index then the first one your placed and will therefor be 'on top of' the first rectangle (including it's images). To solve this I've set the parent of the image (the group) to move to top on the dragstart, this fixes it for me:
cloneImg.on('dragstart', function(){
this.startX=this.x();
this.startY=this.y();
this.getParent().moveToTop();
});
See also the fiddle: http://jsfiddle.net/Dcevd/3/
PS. If you look in the KineticJS docs, you see that setZIndex is available on Kinetic images (as with all other Shapes). http://kineticjs.com/docs/Kinetic.Image.html

Can LiveCode objects be anchored to one or more sides of a form?

If so, how? ... Just for clarity, if there are 2 pixels between a form and object's edges, and I resize the form, I'd like the distance between the form and object to still be 2 pixels after resizing.
Thank you, as always.
There's a few ways to do this but the simplest and most reliable is to script it with a resizeStack handler in your card script:
on resizeStack pWidth,pHeight
put the rect of field "name" into tRect
put pWidth-2 into item 3 of tRect
set the rect of field "name" to tRect
end resizeStack
Monte's answer is dead on if what you are doing is keeping objects in a desired arrangement when resizing the stack window. But if you are wondering how to keep relative positioning while resizing or moving an object or group of objects (you said "form" so I'm assuming that's a group of objects) in a card layout, you simply have to update it in the same code that you use to resize your form or group.
constant kOffset
on resizeMyGroup
-- code for resizing group here
set the left of button "myButton" to the right of group "myForm" + kMargin
set the bottom of button "myButton" to the bottom of group "myForm"
-- etc.
end resizeMyGroup
This is the general approach to maintaining a layout in LiveCode.

Resources