Raphael.js how to find click on path's stroke? - javascript

How can I find out with Raphael.js (when the user click on a SVG path) the click was on the stroke?
Here is the path:
var polycoords = [['M',10,10],['L',30,10],['L',35,50],['L',5,45],['Z]];
var poly = paper.path(polycoords).attr({'stroke':'#00f','stroke-width':5});
poly.click(function(e) {
// I think here can I find it somehow...
});

As far as your path it closed but not filled with a color or a pattern, only the strokes are clickable, so the problem seems to resolve itself.
If in some not pasted code lines, you actually fill this path, then, also the inside is clickable and there is no difference in the event argument provided to the click callback.
Two ways:
having the stroke and the inside as two differents path (one filled and without strokes, the other not filled but with strokes) and attach seperate click handlers
on click, create a temporary path surrounding the pixel you clicked (whose coordinates are in the event argument), and search for intersections with the existing path with Raphael.pathIntersection(path1, path2) (RaphaelJS documentation: pathIntersection)

Related

mapBOX - find the element ID on click

Context:
I have my project setup that draws a road on the mapbox as layers (the road is basically a line with styling and painting implemented). Now I need to click an existing line, and wherever I click it, I want to draw a sub-road originating from the point it clicked it
Blue line is Actually line, the surrounding is just styling.
What I want:
I want to get the ID of the line element (or main road), and the point where it is clicked and then when user has clicked on target coordinate on the map, I want to grab that info and add it into existing line so that the line becomes a single with additional breakpoints. This will make the line look like
(the line is single yet it has multiple stops. This makes it consistent. Feels part of line)
The Problem:
I click on the road (the line), and then click somewhere else to stop drawing, I see new road drawn but since it is a separate layer, it looks not consistent with existing one.
Findings:
Every line, every shape is separate layer, since first road, even though it had multiple stops, was in-fact a single road so the design was consistent 3. But since the new line is a new layer, it has its own styling.
I need to find a way to add new data in existing layer
Roadblocks:
Need to find the ID of existing element when I click on it to use it as a source for my new line
Need the pin-point location of click
Need the data for new line/ new layer
find a way to merge into existing layer
Now with all the above context in mind, I am not even able to get the ID of element
SideNote:
While drawing a line in mapbox (using draw.changeMode('draw_line_string'); and then a create various stop points by clicking on map geoJsons) that line stays in one piece even though it has various sub-lines.
Now I need to grab the ID of that line and then specific point when I did click.
Here is my relavent parts of code
draw the line on map
draw.changeMode('draw_line_string');
map.on('draw.create', configureAndUpdateMapBoxDevices);
in configureAndUpdateMapBoxDevices function
draw.add(e.features[0]); //updating event real time for all callbacks where e is passed on as argument so its have these properties.
const json_data = {
json_id: e.features[0].id,
json_string: JSON.stringify(e.features[0])
};
updateMapboxDevice(selected_edit_site_id, json_data); // update on db and models
to style the road defined various variable layers for main road element
map.addLayer(bottomLine);
map.addLayer(left_yellowBelt);
map.addLayer(right_yellowBelt);
map.addLayer(topLayer);
map.addLayer(lineSeparator2L);

Adobe Animate CC - Reused Button Not Working HTML5

I am having an issue with reusing the same button within an HTML5 canvas. The button needs to be reused over the course of several separate frames as well as several times within the same frame.
The button works correctly with the first use:
this.button_13.addEventListener("click", fl_ClickToGoToAndStopAtFrame_24.bind(this));
function fl_ClickToGoToAndStopAtFrame_24()
{
this.gotoAndStop(72);
}
At frame 72, I reuse the same button symbol with a new instance name. Unfortunately, this button does not work:
this.button_14.addEventListener("click", fl_ClickToGoToAndStopAtFrame_25.bind(this));
function fl_ClickToGoToAndStopAtFrame_25()
{
this.gotoAndStop(78);
}
Clicking this second button shows the button states, but will not advance the user to frame 78.
*If the 2nd button exists on the timeline for frame 72 only, it is not present in the published result at all. If the 2nd button exists on frame 72-77, the button is present but not functional.
Any ideas?
Try to do this
this.button_13.removeEventListener("click", fl_ClickToGoToAndStopAtFrame_24.bind(this));
before creating the second event listener.
You have two options here.
Put your separate button instances on different layers.
Create one button instance on its own layer, have a script set the button's visible property (true/false) as needed, and modify your click handler to react based on the value of this.currentFrame.
Animate CC (2015.2 for me at the time of this writing) seems to generate its HTML 5 script output with animation in mind. When you have like object instances on multiple frames on the same layer, instead of creating a new instance of that object, it re-purposes the instance from a prior frame.
e.g. I create a dynamic text box named "myText" on frame 1. On frame 2, I create another dynamic text box and name it "myOtherText". When I publish and look at the script, the script calls Tween.to() first to place the "myText" object on the canvas and give it its appearance and position, then chains another .to() call to make myText look like myOtherText. Under the hood, myOtherText simply doesn't exist.
Creating another layer forces Animate to create the instances explicitly in CreateJS. However, if you have a lot of buttons, that could end up making a ton of layers and making your timeline look messy. I'd recommend option 1 if you only have a couple button instances, but for the latter case, option 2 may be the way to go.
Create a new layer. Name it whatever you want, like "button layer".
This layer will have only one keyframe.
Place your button instance on this layer. For continuity's sake, let's name it button_13.
Bind a tick handler to the root MovieClip (i.e. this) to handle whether the button should appear or not.
var tickHandler = function () {
switch (this.currentFrame) {
//Add case statements for each frame you want the button to appear on
//Remember, frame indexes in CJS are 0-based!
case 12: case 13:
this.button_13.visible = true;
break;
default:
this.button_13.visible = false;
}
}.bind(this);
this.removeEventListener('tick', tickHandler); //Make sure not to double-bind
this.addEventListener('tick', tickHandler);
Bind a click handler to the button that will gotoAndStop on a frame dependent on the current frame.
var clickHandler = function () {
switch (this.currentFrame) {
//Add case statements for each frame that should have a jump
//Remember, frame indexes in CJS are 0-based!
case 12:
this.gotoAndStop(72);
break;
case 13:
this.gotoAndStop(78);
break;
}
}.bind(this) //Proxy the handler, as done above.
this.button_13.removeEventListener('click', tickHandler); //Make sure not to double-bind
this.button_13.addEventListener('click', tickHandler);
Place both of those scripts onto frame 1 of your movie.
I haven't tested this myself as presented, but it should accomplish what you're looking for.
The solution is to move the instance on another layer. In that way, two different instances can be used in different images with different scripts and different names.

Checking visibility of layer in KineticJS

I am trying to figure out how to check whether or not a layer in KineticJS is visible. I need this in order to appropriately toggle the visibility of any given layer when the user clicks a button. If it's visible, I want to hide it when they click the button. If it isn't visible, then I want to show it. Thoughts? I saw that there is a isVisible function, but nothing at all happens when I try to use it on a layer. The below code doesn't error, but it isn't doing anything. This is written in KineticJS on Angular. In my tests, I found that this event is appropriately getting triggered, so it's not that. I also found that the draw function is appropriately firing.
scope.$on('layertoggle', function(event){
var layerShapes = scope.kineticStageObj.get('#layer1');
if(!layerShapes.isVisible()){
layerShapes.hide();
}
else{
layerShapes.show();
}
scope.kineticStageObj.draw();
});
Try this:
var layerShapes = scope.kineticStageObj.get('#layer1')[0];
get returns a collection of shapes that match that criteria. Despite id being unique, you still have to access the first position of the array to access the desired shape.

Fabricjs - select object programatically for immediate movement/drag

I am able to select object programatically using fabricjs. However, it does not behave like when one selects an object using mouse click. On a mouse click, the object comes under focus, and one can, for example, drag it. However, on programatic selection, I cannot immediately move an object. An example jsfiddle:
http://jsfiddle.net/ThzXM/1/
Programmatic selection:
canvas.setActiveObject(canvas.item(0));
What I would like to ultimately achieve is this: on clicking a button, a new rectangle is added to canvas, which the user can move around before placing it on canvas - without requiring extra clicks. Is it possible to do this in a cross-browser compatible way? (I know in some browsers I can fire a mouseclick event but most disallow it.)
You have to do this. Don´t forget to call setCoords() to update the bounding box of your object.
// Set the active element
canvas.setActiveObject(canvas.item(0));
// Set left, o right,or angle... check documentation.
//Don´t forget to call setCoords() after changes.
canvas.item(0).setLeft(80).setCoords();
//Then render the canvas
canvas.renderAll()

Paper.js - Get first ''selected item'' from selectedItems

I'm trying my way around building a graphics editor with Paper.js
I would like to select the first(1st) element that was picked using a selection tool(either Shift+Click, or dragging a selection box). Direct-click detection is done via hit-testing and selection box via getIntersection
If it's Shift+Click its the first selected element. Which element was clicked is found with HitResult
If its selectionBox, the first intersection? result of the selection box.
Is it possible to get this?
I do a FOR loop to get all the elements in the Paper.js selectedItems array which returns all the selected items on the canvas.
I've tried this:
var selected = paper.project.selectedItems;
var firstSelected = selected[0];
but this doesn't return what i need.
The above code snippet fetches an array that is agnostic to which element was selected first. It simply orders the selectedItems in the array starting from the ''oldest drawn path''.
What i need is a way to find out which is the 1st element that was selected.
Either the 1st that get's ''touched(intersected)'' with the selection
rectangle
Or the first that was clicked while in Shift+Click
functionality(Select more than one element with click).
The reason for this is that i would like to add to my editor, align-relative-to functionality.
In order to have a correct UX, the user must have the ability to align an element relative to another that he sets as the ''reference item''. Therefore i need to know the 1st element selected relative to others in order to use it as the ''reference item''.
Any ideas ?
Here is a working example of what I understood you want to achieve for the selection (without the align-relative-to functionality).
And here is the code (under SelectPaperJS) https://c9.io/arthursw/oiio/
It should not be too hard to make something similar on Stylii (since you're using it).
You can have an array to keep track of the order of selection of your items. For example in the mousedown function of the direct select tool (from line 789 of editor.js) you can add the newly selected element to this array (line 800). Same thing when you select with the rectangular selection tool.

Categories

Resources