I am beginning to use snap.svg, and stuck in a probably simple question. I draw a circle, and want to let the user drag it around, and when the user stops dragging, I want to know the alert the final position of the circle.
I started with this:
var s = Snap("#svg");
var d = s.circle(20,20,5);
Then I created the following functions as drag event-handlers; I only need the drag-end event so I made the two other event-handlers null:
var endFnc = function(e) {
alert("end: "+e.layerX+","+e.layerY);
}
var startFnc = null;
var moveFnc = null;
Then I installed the drag event handlers:
d.drag(moveFnc,startFnc,endFnc);
Whenever I tried to drag a circle, the end event fired, but, the circle did not move.
So I figured maybe I have to also create the drag move event (although I don't need it):
var moveFnc = function(dx, dy, x, y) {
this.transform('t' + x + ',' + y);
}
Now the circle did move, but, not exactly at the mouse, but approximately 20 pixels at its bottom right.
I read the documentation here: http://snapsvg.io/docs and there seems to be no explanation about how to create working drag events.
How does anyone get this knowledge?!
After struggling for some hours to do this with snap.js, I finally discovered svg.js and its draggable plugin, with which it is so much easier:
var draw = SVG('svg');
var circle = draw.circle(10).attr({cx:30,cy:30,fill:'#f06'});
circle.dragend = function(delta, event) {
alert(this.attr('cx'))
}
circle.draggable();
So, I switched to svg.js ...
Related
I'm not sure how to flip the axes of my chart. Below is the code I'm using.
Please see also the picture on how it looks right now. Instead of drawing the data vertically I'd like to show it horizontally. It suppose to look like a stock chart because that is what it actually is. I'm using YQL to get the historical data of the symbol as Json format.
I also see the data is scooped in the whole screen. I'd like to see the last month for example and just allow the user to swipe to the right for more or just to zoom out.
I'd appreciate some help.
float vals=0;
String[] resultStrs = new String[StockHistoryArray.length()];
for (int i = 0; i < StockHistoryArray.length(); i++) {
JSONObject chartDataObj = StockHistoryArray.getJSONObject(i);
yVals.add(new Entry(vals,(int) Float.parseFloat(chartDataObj.getString("Adj_Close")),i+1));
xVals.add(i, String.valueOf(vals));
vals++;
}
LineDataSet setting = new LineDataSet(yVals, "Stock Chart");
ArrayList<ILineDataSet> dataSets = new
ArrayList<ILineDataSet>();
dataSets.add(setting);
LineData data = new LineData(xVals, dataSets);
lineChart.setData(data);
Legend l = lineChart.getLegend();
l.setForm(Legend.LegendForm.LINE);
l.setTextColor(Color.WHITE);
XAxis x1 = lineChart.getXAxis();
x1.setTextColor(Color.WHITE);
x1.setDrawGridLines(false);
x1.setAvoidFirstLastClipping(true);
YAxis y1 = lineChart.getAxisLeft();
y1.setTextColor(Color.WHITE);
y1.setAxisMaxValue(120f);
y1.setDrawGridLines(true);
return null;
Here is the screen shot after I run this code. It is one year history.
screen capture
You are doing wrong in the following line.
yVals.add(new Entry(vals,(int) Float.parseFloat(chartDataObj.getString("Adj_Close")),i+1));
Use like this to draw the chart correctly
yVals.add(new Entry(entryVal,entryXIndex);
If your value in chartDataObj.getString("Adj_Close")
then you need to add like this
yVals.add(new Entry(Float.parseFloat(chartDataObj.getString("Adj_Close")), i);
I found that if I add a Sprite (with inputEnabled = true) to a group and don't add the group to the stage, I can still interact with the Sprite (although it's not shown).
var group = App.phaser.add.group(null, null, false, false);
var bmd = App.phaser.add.bitmapData(100, 100);
bmd.ctx.beginPath();
bmd.ctx.rect(0, 0, 100, 100);
bmd.ctx.fillStyle = '#ff9900';
bmd.ctx.fill();
var sprite = App.phaser.add.sprite(0, 0, bmd);
group.addChild(sprite);
// group.visible = false;
sprite.x = 100;
sprite.y = 100;
sprite.inputEnabled = true;
sprite.input.useHandCursor = true;
The stage is completely blank (which is good). But when I move my mouse over the top left corner I see a mousecursor (and any added event handlers would also respond).
Only way to prevent this form happening is to set the group's visibility to false, but this is clearly not the best solution.
I'm doing somthing wrong or this is a bug in Phaser?
Sprites don't have to be on the display list in order to be interactive, they just have to have 'inputEnabled' set on them. This is commonly used to allow you to create 'invisible' hit areas.
If you want the sprite to be ignored for input you can call sprite.input.stop() and toggle it back on as needed with start.
Also please use Group.add otherwise the sprite doesn't get assigned a z value, throwing it out of sequence in the Group.
I created a triangle and I am trying to make it red. However it remains black. The problem doesn't seem to be the material as it works on other Geometries I've made.
Here is my triangle:
var triangle = new THREE.Geometry();
triangle.vertices.push(
new THREE.Vector3(-10,10,0),
new THREE.Vector3(-10,-10,0),
new THREE.Vector3(10,-10,0)
);
triangle.faces.push(new THREE.Face3(0,1,2));
triangle.computeBoundingSphere();
this.redtriangle = new THREE.Mesh(triangle, this.redMat)
I tried some suggestions online to color it using:
triangle.faces.push(new THREE.Face3(0,1,2));
triangle.faces[0].vertexColors[0] = new THREE.Color(0xFF0000);
triangle.faces[0].vertexColors[1] = new THREE.Color(0xFF0000);
triangle.faces[0].vertexColors[2] = new THREE.Color(0xFF0000);
My material
this.redMat = new THREE.MeshLambertMaterial ({
color: 0xFF0000,
shading:THREE.FlatShading,
// I added this line for the suggestion above
// vertexColors:THREE.VertexColors,
side:THREE.DoubleSide
})
I've also tried to insert
triangle.colorsNeedUpdate = true;
or
geometry.colorsNeedsUpdate = true;
but no matter what variations/where I put it, it doesn't want to work. The triangle stays black.
Your vertices definition is in clockwise order when it should have been counter-clockwise. So if you change your new THREE.Face3(0,1,2) to new THREE.Face3(0,2,1) you should see something.
I love KineticJS, its speed, marriage with GSAP, but what is making my head spin is there a way to freely transform KineticJS objects like the way in FabricJS? Here is the link reference to what I am trying to say: http://fabricjs.com/customization/
I don't want to use FabricJs as its really slow, and its low performance evident from various unit tests.
I am really looking forward to finding a way to be able to freely transform object in KineticJS as it would make life so much easier.
Is there a way to do it?
Thanks for your help,
Praney
Like markE said, this tutorial on Eric's (creator of KineticJS) tutorial site is the basis for all free transforming within KineticJS.
I'll go into detail about the actual free transform logic, there are 2 main functions:
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
//Create the anchor shape
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 8,
name: name,
draggable: true,
dragOnTop: false
});
//Calls the update function which handles the transform logic
anchor.on('dragmove', function() {
update(this);
layer.draw();
});
//When the anchor is selected, we want to turn dragging off for the group
//This is so that only the anchor is draggable, and we can transform instead of drag
anchor.on('mousedown touchstart', function() {
group.setDraggable(false);
this.moveToTop();
});
//Turn back on draggable for the group
anchor.on('dragend', function() {
group.setDraggable(true);
layer.draw();
});
// add hover styling
anchor.on('mouseover', function() {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
layer.draw();
});
anchor.on('mouseout', function() {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
The addAnchor function, like the name says, adds a single anchor (or free transform handle) to a Kinetic.Group. By default it uses a Kinetic.Circle but really you can use any shape you want.
group - the group to add the anchor to
x - the x position of the anchor
y - the y position of the anchor
name - name of the anchor (usually describe which position the anchor represents, like topLeft or bottomRight
You'll notice a bunch of events attached to the newly created anchor, most of these are pretty straight-forward but the one you want to pay attention to is the dragmove event - this event is the one that calls the update function which handles all the logic for transforming the group/node. It's useful to note that the update function is called for every pixel that you are dragging an anchor.
The tutorial uses 4 corner anchors (thus calling addAnchor 4 times for each group/node), but if you wanted 8 anchors (4 corners - 4 sides) then you just have to adjust the logic to position the anchors correctly and to move the anchors properly when transforming.
By the way, the reason we're adding Anchors to a Group, is because we need them to group with the node in question, and stick with each node through dragging and transforming.
The second method is the update function:
function update(activeAnchor) {
var group = activeAnchor.getParent();
//Get each anchor inside the group, by name. Keep a standard set of names for every anchor you use and note they have to be names not ids because there will be multiple anchors named .topLeft in your app
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var image = group.get('.image')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
//When topLeft is being dragged, topRight has to update in the Y-axis
//And bottomLeft has to update in the X-axis
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
image.setPosition(topLeft.getPosition());
//New height and width are calculated with a little math
//by calculating the distance between the update anchor positions.
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if(width && height) {
image.setSize(width, height);
}
}
The update function only takes one argument: the activeAnchor which is the anchor being dragged.
After that, it selects the other anchors within the group (using static names that you need to give each node and keep consistent throughout your app) so that we can translate their positions while the activeAnchor is being dragged.
The switch statement can get pretty large if you use 8 anchors instead of 4. This is because you need to consider translating almost all the other anchors while dragging one of them.
For an 8 anchor example: If you drag the topLeft anchor, you need to update the y position of the topRight anchor, the x position of the bottomLeft anchor, and for the topMid and leftMid anchors you need to adjust both the x,y values to stay in between the other anchors.
After updating the anchor position, the function handles the logic to resize the shape. Notice that the shape is selected by var image = group.get('.image')[0]; But, what you can do is use the get function to select by type and do something like:
var shape = group.get('Shape')[0];
Obviously this will work best if you just have 1 shape per group (to transform) + 4 or 8 anchors.
Let me know if you have any other questions or comments! Good luck!
this project adds a transfrom tool (resize) and some nice handlers which can be used as a basis:
https://github.com/soloproyectos/jquery.transformtool
Hi please see my previous answer about this. just search my name. hope it will be a bid help for you :) Transform (Move/Scale/Rotate) shapes with KineticJS
I forgot to include the html tags there so here it is... :)``
<!-- INSIDE THE HEAD TAGS -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- I am using jquery transform tool for kineticjs -->
<script type="text/javascript" src="../lib/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="../lib/jquery.timer-1.0.3.js"></script>
<script type="text/javascript" src="../lib/kinetic-v4.7.4.min.js"></script>
<script type="text/javascript" src="../src/jquery.transformtool-1.0.2.js"></script>
<script type="text/javascript">
//PUT THE JAVSCRIPT SNIPPET HERE FROM THE LINK THAT I PROVIDED ABOVE
</script>
//THE ADD div element with id = canvas and file element with id = files and name files[] INSIDE THE BODY
A few small questions on this web page I am putting together.
http://dansiop.com/guyc/our-team/
I am looking to get the content that appears when you click on an image to slide with the mouse as you scroll down. Not sure if this is possible, if so can anyone help.
I have tried looking but as I am such a n00b to jquery I'm not sure what I am looking for. I found some code that used the tag slide and it was not what i wanted at all so not sure what the command would be.
You need to wrap your prof_1, prof_2, etc, in a wrapper I'm going to call this wrapper prof_wrapper
<div id="prof_wrapper"></div>
jQuery(document).ready( function(){
var orig_t = jQuery("#prof_wrapper").offset().top;
var mt = jQuery("#main").offset().top;
var mh = jQuery("#main").outerHeight();
jQuery(document).bind("scroll", function(event){
var ph = jQuery("#prof_wrapper").outerHeight();
var mo = (mt+mh) - jQuery(document).scrollTop();
var t = jQuery(document).scrollTop();
if(mo <= ph){ //Find out if the #main element's offset top plus it's height minus the scroll position is less than the prof_wrapper's height; if it is, leave the prof_wrapper at the bottom of the #main element
jQuery("#prof_wrapper").css({'position':'absolute', 'bottom':'0px', 'top':'auto'});
}else if(t >= orig_t){ //Otherwise, if we have scrolled past the prof_wrapper, make the prof_wrapper follow us down
jQuery("#prof_wrapper").css({'position':'fixed', 'top':'0px', 'bottom':'auto'});
}else{ //We are probably at the top of the page, so reset the original positioning
jQuery("#prof_wrapper").css({'position':'relative', 'top':'0px', 'bottom':'auto'});
}
});
});
You need to add - position:relative to your #main element, then I think this should be pretty close. Take a look at my comment about the padding and margin on the prof_wrapper.
The positioning of absolute, assumes that #main is the first parent element to have a position assigned to it; if so, then it will use this as the positioning for the bottom.
Something like that?