I'm trying to do something that seems simple, but not sure how it's not working. I have a map layer and I'm trying to draw circles via Extendscript. I'm trying to test just by trying to draw a simple circle at point 100,100 (I assume top left of map is 0,0), but when I execute it, the circle appears way further down than it should be (seems close to 200,700). Below is my code I'm using...
var dotRadius = 8.136 / 2;
var testDOT = mapLayer.pathItems.ellipse(100, 100, dotRadius*2, dotRadius*2, false, false);
testDOT.strokeWidth = 0.25;
testDOT.strokeColor = getColor("MAROON"); // defined above
testDOT.fillColor = getColor("MAROON");
the getColor just creates a CYMK Color object. Can anyone give me a clue on why the 100,100 point is not where I expect it to be?
TIA!
Just in case, it looks like your script used the 'relative' coordinate system (relative to zero point of current artboard).
To made it to use 'absolute' coordinates (relative to the top-left corner of the first artboard for a new document) you can add this line at the start of your script:
app.coordinateSystem = CoordinateSystem.DOCUMENTCOORDINATESYSTEM;
Or you can use the 'relative' coordinate system:
app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
In this case you can move zero point of any artboard with this commands:
var doc = app.activeDocument;
doc.artboards[0].rulerOrigin = [0,0];
doc.artboards[1].rulerOrigin = [200,700];
// etc
Related
I am trying to animate the drawing of a box that will then fill in when it is complete. I am taking a class in JS so the code has to be JS. The problem is that the right side of the box will not animate correctly. If I put in one set of coordinates for it it animates from the bottom to the top instead of from the corner where the top line started. When I reverse the coordinates it does animate from the proper corner but instead of drawing the line it starts with a solid line and takes away from it, like a disappearing line. Also both the left and right side lines seem to go off the area assigned. For example my area is 600 x 400 and the lines go off the bottom of the page. If I change the dimensions to 600 x 600 the lines still go off the page. The point of this whole project is that we have coded houses using the SVG library and I want to create an animation to make it look as though the house is being drawn before it fills in the colors. This is more for my own knowledge as it is no longer an assignment. There are 2 links to my jsfiddle, the first one is going to be the problem code of drawing the box. The second is what the house that I would like to animate is to look like.
drawing box
"use strict"
var draw = SVG('drawing').size(600, 400);
function makeBox()
{
var line1 = draw.line(25,175,26,175);
line1.stroke({width:1});
line1.animate(4000).size(550);
var line2 = draw.line(575,175,575,176);
line2.stroke({width:1});
line2.animate({duration:4000,delay:4000}).size(200).move(575,375);
var line3 = draw.line(575,375,574,375);
line3.stroke({width:1});
line3.animate({duration:4000,delay:8000}).move(25,375).size(550);
var line4 = draw.line(25,375,25,374);
line4.stroke({width:1});
line4.animate({duration:4000,delay:12000}).size(200).move(25,175);
}
makeBox();
function makeBaseb1(bx,by,c,s)
{
var Baseb1 = draw.rect(550,200).opacity(0).fill(c).stroke();
Baseb1.animate({delay:'16s'}).opacity(1).fill({color:c});
Baseb1.stroke({width:s,color:'black'});
Baseb1.move(bx,by);
}
makeBaseb1(25,175,'#FF9900',1);
house
There are 2 issues with the makeBox function:
The .size method taks 2 arguments instead of 1 (x and y dimension).
For the line drawing in the reverse direction wrt the coordinate system,
both, starting coordinates and line length, need to be animated.
The updated function:
function makeBox() {
var line1 = draw.line(25,175,26,175);
line1.stroke({width:1});
line1.animate(4000).size(550,0);
var line2 = draw.line(575,175,575,176);
line2.stroke({width:1});
line2.animate({duration:4000,delay:4000}).size(0,200);
var line3 = draw.line(574,375,575,375);
line3.stroke({width:1});
line3
.animate({duration:4000,delay:8000})
.during(
function (pos, morph, eased, situation) {
line3.x(morph(574,25));
line3.size(morph(1,550),morph(0,0));
}
)
;
var line4 = draw.line(25,374,25,375);
line4.stroke({width:1});
line4
.animate({duration:4000,delay:12000})
.during(
function (pos, morph, eased, situation) {
line4.y(morph(374,175));
line4.size(morph(0,0),morph(1,200));
}
)
;
}
The use of the .during method is documented here.
We have a web application that displays a SVG map of an office. The map has small icons that represent users walking around with RF tags. This allows administrators of the system to see what rooms users are in. We are using Snap.SVG to load the office SVG file and manipulate it to display the user icons. The challenge is that the map scales to the size of the browser. Using JavaScript to determine the coordinates is not always accurate because the position of the SVG changes based on the browser size.
Here is an example of the map with the icons:
The icons are placed on the map based on X Y coordinates coming from our database. The values for the X Y coordinates are set for each location and were determined using Adobe Illustrator. Currently, we can only place one icon in a room at a time. Because we only have 1 set coordinates the icons overlap if more than one person is in a room at one time.
The second phase of this project is to allow users to draw on of the map to specify locations. Essentially, the user will set points and create a polygon to represent each location on the map. We would use the coordinates of the polygon along with the total area of the polygon to know where on the map we can place icons. This would allow users to define areas without a developer getting involved.
Here is an example of what we want to achieve .
I have been researching how to do this, but have not found anything outside of using something like the Google Maps API to draws polygons on a map. I did find this article that outlines how to dynamically pull points. We thought about using a grid system that is an overlay on the map and the user defines what grid elements are in what locations. So something like [A1,A2,B1,B2]. I persoanlly like the polygon approach as it is more visually appealing and is easier for a user to adopt.
We need some advice on where to start with this and if something like snap.svg is all we need or if we have to rely on other libraries in conjunction with snap.
Update:
With Ian's advice I found a fiddle that describes what he was talking about.
var S;
var pt;
var svg
var box;
window.onload = function(){
svg = $('#mysvg')[0];
S = Snap(svg);
console.log( S );
pt = pt = svg.createSVGPoint(); // create the point
// add the rectangle
box = S.rect(12,12, 12, 12);
box.attr({ fill : 'red', stroke : 'none' });
S.drag(
function(dx, dy, posX, posY, e){
//onmove
pt.x = posX - S.node.offsetLeft;
pt.y = posY - S.node.offsetTop;
console.log(pt.x + "," + pt.y);
// convert the mouse X and Y
//so that it's relative to the svg element
var transformed = pt.matrixTransform(svg.getCTM().inverse());
box.attr({ x : transformed.x, y : transformed.y });
},
function(){
//onstart
},
function(){
//onend
}
);
}
The Fiddle
Im trying to create an interactive seating layout like this Seats.io. However I dont need the exact features but just few things such as:
Plotting seats anywhere on the screen
Plotting list of seats from one point to another
Seats hover as circle when plotting from one mouse click point to another
After much research in Jquery and simultaneously on raphaeljs, I have decided to start working with raphaeljs. Im totally new to the vector graphics. So obviously there might be something that I may be missing. I have followed this fiddle to draw a straight line. I have also created another script to plot circles anywhere on the window(the circles will mean seats) following is the script
window.onload = function () {
var height = $(document).outerHeight(true);
var width = $(document).width();
var radius = 10;
var paper = Raphael(0, 0, width, height);
var i = 0;
$(document).click(function (e) {
i = i + 1;
var x = e.pageX;
var y = e.pageY;
var seat = paper.circle(x, y, radius)
.attr({stroke: "none", fill: "#f00", opacity: .4})
.data("i", i);
seat.mouseover(function () {
this.attr("opacity", 1);
});
seat.mouseout(function () {
this.attr("opacity", .4);
});
});
}
using the above script I'm able to plot circles(seats) on my screen. Now based on the fiddle example lines are drawn using 'path', so is it possible to load circles on every path and draw them as sequential line of circles one after the other, or do I have to take any different approach.
Also on a side note is there any opensource project or code for the Seats.io
Any help would be really appreciated
Ben from seats.io here.
http://raphaeljs.com/reference.html#Element.getPointAtLength is indeed what we use. You'll basically need to
calculate a helper path between start and end point. You already have that.
calculate the distance between seats (based on seat size): helperPath.getTotalLength() / (numberOfSeats - 1);
for each seat, call getPointAtLength and draw a circle around that
point: helperPath.getPointAtLength(distanceBetweenSeatsOnHelperPath * i++)
Obviously, it gets more interesting if you want to snap to a grid to align rows, curve rows, etc, but you should be able to get started with the above.
This one requires a bit of visualisation, so sorry if my explanation sucks.
So, I have a central point at 0,0. From this point, I am plotting random points on its circumference, at a radius of 350 pixels (random number). For this I am using this code:
var angle = Math.random()*Math.PI*2;
var x = Math.cos(angle)*radius;
var y = Math.sin(angle)*radius;
x+=parent.position.x;
y+=parent.position.y;
The parent.position this is because each point that is plotted also acts as a central node, which has children that act as nodes and so on. This just sets the position of the new node relative the position of its parent.
So this code works perfectly well for the central node. The problem is that once you've branched away from the centre, you want to continue moving in a particular direction to avoid a big cluster of nodes interfering with each other. So, whereas this code plots a point on the circumference, I need to be able to plot a point on a segment of the circumference. I'm thinking maybe about a third of the circumference should be accessible. The other obstacle is that this has to be the CORRECT segment of the circumference i.e If the nodes are branching upwards, I don't want the segment to be the bottom half of the circumference, the branch needs to continue moving in the upwards direction.
I can establish a general direction based on the position of the new parent node relative to the position of its parent. But does anyone have any ideas of how to use this data to reduce the field to the a segment in this direction?
Let me know if that made no sense, it's kinda hard to explain without diagrams.
I think one easy way of doing that would be to split your circle in n segments (each covering 2*PI / n angle). You could set n to whatever you want, depending on how precise you want to be. Then when you calculate a new point x, first get the segment in which x.parent is (relative to its own parent), and use that to put x in the same section wrt x.parent. You could then have something like this:
var getSection = function(point) {
var parent = point.parent;
var angle = Math.acos((point.x - parent.x) / radius) % (Math.PI*2);
var section = Math.floo(angle / (Math.PI * 2 / n))
return section;
}
var section = getSection(parent); // return the index of the section
var angle = (Math.random() + section) * Math.PI * 2 / n
var x = Math.cos(angle)*radius;
var y = Math.sin(angle)*radius;
x+=parent.position.x;
y+=parent.position.y;
I don't understand how to rotate my object at a certain point. This is the javascript I have
// create needle
var rsr = Raphael('rsr', '320', '240');
var needle = rsr.path("m 156.74443,870.84631 -2.26177,119.38851
4.38851,0 z"); needle.attr({id: 'needle',parent: 'layer1',fill:
'#ff6600',stroke: '#000000',"stroke-width": '0.61',"stroke-linecap":
'butt',"stroke-linejoin": 'miter',"stroke-miterlimit": '4',"stroke-
opacity": '1',"stroke-dasharray": 'none'});
needle.rotate(0);
needle.transform("t0,-812.36218").data('id', 'needle');
// get needle bounding box
var needleBox = needle.getBBox();
// calculate rotation point (bottom middle)
var x_rotate_point = needleBox.x + (needleBox.width/2);
var y_rotate_point = needleBox.y + needleBox.height;
// rotate needle
needle.attr({rotation: 0}).animate({transform:"r45,"+x_rotate_point
+","+y_rotate_point}, 6000);
// Creates circle at rotation point
var circle = rsr.circle(x_rotate_point, y_rotate_point, 10);
circle.attr("fill", "#f00");
circle.attr("stroke", "#fff");
I have created a dummy circle to check if my coordinates of my center point is correct
and it is, but it doesn't rotate around that point :-/
When I created gauges in different frameworks that always seemed the way to go, but that logic doesn't seem to translate well into Raphael 2.0.
I did google for it and found some entries but the problem seems it is for
older versions which doesn't translate well because a lot of
stuff got changed or is deprecated.
You are setting the center of rotation correctly, but there are some other things going on which are causing some confusion. I was able to get this to work by changing the animation target to:
{transform: needle.attr("transform") + "R45,"+x_rotate_point+","+y_rotate_point}
I think the way you had it, the animation was gradually removing the previous translation while also doing the rotation. This addition allows it to accumulate the transformations. Also, note that I had to switch the 'r' to 'R'. It is not really clear to me what the small 'r' is doing in this example.
Anyway, here is a working demo.
Btw, I also commented out a few rotations that didn't seem to be doing anything.