how to make rectangle scale vertically animation in Raphael JS - javascript

The Raphael Js website is down so I can't find any documentation or anything on how to do this. I want to create a rectangle with initial vertical size of 0 and make it animate so that it gets vertically larger and larger when I click another object. Thanks!
so i've got a rectangle
var water = paper.rect( 0, 300, 600, 0).attr({fill:"blue"});
how do I make it animate?

In particular, check out the documentation for
Element.attribute(),
Element.animate(),
Element.click(), and
Raphael.animation().
The following snippet demonstrates a simple animation like the one you are looking for. Click the red square to make the water "fill". It may not work in some browsers (e.g. Chrome) possibly because the snippet is trying to access an external third-party library, i.e. Raphael.js. So, to run it, either go to this SO question/answer page on Firefox or copy the code and run it on your own computer.
Note that, to make the water "fill" in the up direction, you can't just increase the height of the water rectangle...that would make the rectangle grow downwards. You also have to simultaneously raise the top of the rectangle by the identical amount. Thus you have to animate height and y simultaneously, as shown in the code.
UPDATE: provided an up-to-date link for the Raphael minified library
var paper = Raphael(0, 0, 500, 120);
var button = paper.rect( 10, 10, 40, 20).attr({fill:"red"});
var water = paper.rect( 10, 100, 400, 0).attr({fill:"blue"});
var anim = Raphael.animation({
height: 60,
y: (100 - 60)
}, 2000);
button.click(function() {water.animate(anim);});
<script src="https://raw.githubusercontent.com/DmitryBaranovskiy/raphael/master/raphael.min.js"></script>
To get the animation to start, click on the red rectangle.

Related

Animate along motionpath in responsive SVG

I'm trying to make an animation with greensock. I want to move a balloon over a painted line and the graphic/animation shall be scalable.
I have a problem to align the balloon svg to the painted line. As soon as the browser width does not equal the svgs viewport width, the animation does not work. I'm pretty sure that's not the real spirit of scalable (!) vector graphics. So what am i doing wrong? How can I align the balloon to the line, also when the svg's size is changing?
Here is a simplified codepen of the little project:
TweenMax.to("#balloon", 3, {
bezier: {
values: MorphSVGPlugin.pathDataToBezier("#Path23",{
//matrix:[1.5,0,0,1.5,0,scaleX+"%"],
offsetX: -50,
offsetY: -50,
align:"#balloon"}),
type: "cubic"
},
ease: Linear.easeNone,
repeat: -1,
force3D: true
});
CodePen
The problem was, that i was using two svgs instead of one container. Also the transformOrigin made it work in the end. I updated the codepen. Now it works.

Resize a fabricjs rect to maintain border size

I would like to resize a fabricjs rect instead of scale it, but I'm seeing weird behaviour while dragging the resize handles. The border starts to disappear or duplicate. I've tried both the stable version 1.7.19 and the beta 2.0.0 of fabricjs.
Here is the essence of the code I'm using:
canvas.on('object:scaling', function(){
var obj = canvas.getActiveObject(),
width = obj.width,
height = obj.height,
scaleX = obj.scaleX,
scaleY = obj.scaleY;
obj.set({
width : width * scaleX,
height : height * scaleY,
scaleX: 1,
scaleY: 1
});
});
Working example here: https://codepen.io/bramchi/pen/GMLYEV/
Try scaling it up and down a bit by dragging the resize handles.
Screenshot of scaling up and down issues
What I would expect to happen is the rectangle growing and shrinking while dragging the handles, and the border size to stay the same. But somehow rendering starts to go bonkers if you cross 270px or so. When the mouse button is released, it renders properly again.
What am I doing wrong? Who knows a fix? Or could this be a bug in the library I can report?
Disable object caching to avoid this rendering behaviour:
fabric.Object.prototype.objectCaching = false;
For performance reasons Fabric.js caches objects by default during drag rotate skew and scale operations. One of the moderators of the fabric.js repo pointed me in the right direction, hooray for him!
as described here:
http://fabricjs.com/fabric-object-caching ( really last line )
disabling noScaleCache is enough.
That gives you caching anyway, just it invalidates cache everytime you scale the object.
Not that caching a rect is that usefull, but if you have the same behaviour for complex paths, that is still a good thing to have.
new fabric.Rect({
left: 50,
top: 50,
width: 250,
height: 250,
stroke: 'gray',
fill: 'lightgray',
strokeWidth: 10,
noScaleCache: false,
})

KineticJS - Moving 4000 tiles with Stage.draggable

(Sorry if this is a duplicate, but I don't think it is)
Just so you know, I'm using Google Chrome 29.0.1547.66 m.
I have a KineticJS Project going on at the moment which builds a tiled "staggered" map 40 x 100 tiles. The map takes about 500ms to render which is fine. All 4000 tiles have been put onto one layer.
Once that has completed, I try to drag the stage but I am getting very poor performance as it tries to move all 4000 tiles at once. We are talking about 160ms of CPU time.
I have tried breaking each row up into its own separate layer as others suggested, but that made it even worse (620ms CPU time) as it had to move each layer separately.
I wouldn't say I'm very good at JavaScript but I can't see a way to improve the performance of the drag and I have done some descent research.
Maybe caching the entire layer or something could work?
The project so far has quite a lot of code, so I'm just going to show snippets:
//Stage Object
window.stage = new Kinetic.Stage({
container: element,
width: 800,
height: 600,
draggable: true
});
//Map Loop for create and position tiles
var tempLayer = map.addLayer(); //makes a new layer and adds it to stage etc.
for (var y = 0; y < height; y++) { //100 tiles high
for (var x = width-1; x > -1; x--) { //40 tiles wide
var tileImg = map._tiles[mapArray[x][y]-1]; //map._tiles is just an array of Kinetic.Image objects
if (typeof(tileImg) != "undefined"){
var tileClone = tileImg.clone();
map.place(x, y, 0, tileClone, tempLayer); //places tile in world scope positions
}
}
}
tempLayer.draw();
If I can't work out how to improve the performance, there is no way anyone will be able to run this and the project is going to have to be binned, so all thoughts are appreciated! Thanks!
Have a look at this SO Question: How to cache a whole layer right before dragstart and revert it back on dragend?
The question and my answer describes a similar issue and I think the solution I came up with may help.
Basically what I was suggesting (although I haven't tried it completely so I don't know if it will work well):
Cache the layer using toImage
Drag the image on a different layer while hiding the original layer.
Calculate dx and dy (the distance that you moved)
Update the original layer with dx and dy
Hide image layer, show shapes layer.
I managed to create a quick example JSFIDDLE to work with so check it out. One thing I noticed is that the stage size really affected the performance of the drag, even if it was just 1 rectangle instead of 4000. So, if the stage is really big, even with this image caching thing it didn't really help. But when I decrease the stage size it seems to help
UPDATE:
I found the reason for that "stretched/scaled" image when dragging. It's because I had the image size set statically like so:
var image = new Kinetic.Image({
image: img,
x: 0,
y: 0,
width: 2000,
height: 5000
});
This caused the image to stretch since the image was larger than the stage. If we remove the width and height properties like so:
var image = new Kinetic.Image({
image: img,
x: 0,
y: 0
});
You'll see that the image doesn't stretch anymore.
The other good news is that I reduced the stage dimensions by half (although the number of rectangles, area taken by rectangles and size of image remains the same) and the performance has improved greatly. Hopefully your stage dimension isn't as large (2000x5000) as I had it before right? Check the JSFIDDLE now and see it in action!

How can I use scrollbars to pan around a virtual canvas?

I want to create a jQuery plugin that implements a virtual HTML5 Canvas, i.e. a canvas that is physically no larger (or not much larger) that its appearance on the page. But the contents of what is intended to be shown on the canvas may be many times larger that the canvas and will be dynamically redrawn on depending on scrollbars.
You would think that this is very common functionality, but so far i have not been able to find examples either with jQuery plugins or otherwise. This is very similar to what e.g. SlickGrid does for a Div, except this is with a Canvas. I can think of two solutions:
Use a jQuery UI Slider to implement a scrollbar as a completely separate element and use its event to control the Canvas redrawing.
Do whatever it is SlickGrid does for the Div. It appears to make a Div that is slightly larger than what is being displayed and the hook up to scroll events to dynamically add/remove element to/from the Div. But I can't see how it modifies the scrollbar to make it appear as if there is much more in the Div that what is currently being displayed.
What would you recommend? Sample code would be greatly appreciated.
I dug into the SlickGrid code and used method 2) (sort of) - it was something like this I had in mind:
/*
jensk#migselv.com
Simple virtual CANVAS controlled by a native scrollbar made with two DIVs
Uses jCanvas by Caleb Evans (http://calebevans.me/projects/jcanvas/index.php)
Thanks to Michael Leibman of SlickGrid fame for ideas.
Still need to clean it up (get rid of hardcoded values) and make it a nice, configurable
jQuery component.
Currently also redraws the entire canvas on each scroll event. Could be optimized to
do real browser scrolling and only redrawing the needed parts.
Another gotcha is that since it is the zero width DIVs that causes the scroll events,
mouse wheel, trackpad, touchscreen etc. scrolling over the Canvas will not work - only
the scrollbar is active. To solve this, one could make the Canvas larger inside a
smaller DIV too, catch scroll events from it and perform redrawing and setting the DIV's
scrollTop accordingly.
*/
var h = 10000; // virtual canvas height
var vp = 400; // viewport height
var viewport, fakescrolldiv, canvas;
function onScroll() {
var scrollTop = viewport.scrollTop();
console.log("onScroll scrollTop=" + scrollTop);
$("canvas").clearCanvas();
// Red box top
$("canvas").drawRect({
fillStyle: "#F00",
x: 150,
y: 20 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
// Green box middle
$("canvas").drawRect({
fillStyle: "#0F0",
x: 150,
y: 140 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
// Blue box bottom
$("canvas").drawRect({
fillStyle: "#00F",
x: 150,
y: 260 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
var i = 0;
for (i = 0; i <= 396; i++) {
$("canvas").drawLine({
strokeStyle: "#000",
strokeWidth: 1,
x1: 0,
y1: i,
x2: (scrollTop + i) % 50,
y2: i
});
if ((scrollTop + i) % 50 === 0) {
$("canvas").drawText({
fillStyle: "#729fcf",
text: (scrollTop + i).toString(),
align: "left",
baseline: "top",
font: "normal 12pt Verdana",
x: 60,
y: i
});
}
}
}
$(function() {
viewport = $("#viewport");
fakescrolldiv = $("#fakescrolldiv");
canvas = $("#gfx");
viewport.css("height", vp);
fakescrolldiv.css("height", h);
viewport.scroll(onScroll);
viewport.trigger("scroll");
});
Live demo
Any suggestions for improvements or simplifications are greatly appreciated.
From my personal experience your option (1) is an attractive choice, but there might be some interesting points in making it into a useable jQuery plugin.
I've been working on a financial data visualisation system that explicitly uses HTML5 Canvas for graph and chart drawing. We have different virtual 'scenes' or 'slides' in the canvas which 'slide in' and 'slide out' in the canvas, much like the same way you'd navigate in a big virtual canvas. All the event handling buttons are exclusively drawn on the canvas which dictate which screen we'd be showing, but we have a one/two normal HTML forms that take user inputs and brings those 'slides'. We use jQuery to handle events from these text boxes, but the jQuery codes are deeply nested inside the other Canvas drawing codes, (unlike an externalised call, which would be an idea candidate for making a plugin).
Sliding or updating the canvas is another thing. This is because not only it depends on the jQuery event that triggers the update but it also depends on the Canvas Framework (plain code or KineticJS, EaselJS, jCotton etc) that is responsible for the update. If you use a framework, you'll need to interface with the framework as well.
For simplicity let's assume that there is a callback function that you can call for that Canvas framework with parameters like movement offset (x, y), and the framework will add/remove this offset to the x and y positions of all the objects drawn in the canvas, most Canvas drawing frameworks also have a render() function that it calls periodically so that next time it draws the scene the results will automatically show (in your case, scrolling through the virtual canvas).
So it basically comes down to not only writing it as a jQuery plugin but also a binding it to a particular Canvas Framework e.g. KineticJS or others.
If you use basic Canvas functions instead of using any of those Frameworks, then it's another story, you can write your own render and update functions for the canvas, but in that case it'll be restricting the potential user to adhere the limitations of your drawing functions, unless you expose an API to extend them; but then again, that means you are writing your own Canvas framework :)
I'm not sure if I understood your problem correctly, in that case you can safely ignore my advice :), but If I'm right, my opinion would be: making a plugin like this would require also binding to a Canvas framework to make it really useable.
Hope it helps.

What's the best way to create a user turnable wheel in HTML5/JavaScript?

I need to create a wheel which will be dragged around 360 degrees by the user (in order to have a specific segment of the wheel placed at the top).
I've found examples of a roulette wheel using HTML5 canvas which just spin an image of a wheel for a random amount of time. However, when it comes to allowing a user to drag a wheel as they wish, I'm stumped.
I'd also rather make the wheel from HTML/CSS rather than use an image, because it needs to be dynamically updated.
mmm this looks like a math problem...
so define a center point and then use trigonometry to define the angle of the line (from the center point to the mouse) from the horizon
http://en.wikipedia.org/wiki/Trigonometry
now draw in a canvas on the center point inside the cnavas the weel, get the angle and redraw the weel as needed
The Sencha drawing framework allows you to just about do anything that you might have seen done in flash - but without flash. It works in just about all browsers without plugins. It uses SVG or VML depending on the browser. Have a look at the draggable tiger example here
Edit:
Documentation for the drawing framework which is part of the larger ExtJS framework is found at: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.draw.Component
This is the code I knocked up for a draggable circle/wheel. Didn't put any spinning action in as I think you've got that worked out.
<script src="ext-all-debug.js" type="text/javascript"></script>
<script type="text/javascript">
Ext.onReady( function() {
//create the drawing surface
var drawComponent = Ext.create('Ext.draw.Component', {
width: 400,
height: 400,
draggable: {
constrain: true,
constrainTo: Ext.getBody()
},
autoShow:true,
floating: true,
renderTo: Ext.getBody(),
items:[{
//add the circle sprite to the
//drawing surface
type: 'circle',
fill: '#79BB3F',
"stroke-width": "1",
stroke: "#000",
radius: 100,
x: 100,
y: 100
}]
});
});
</script>
You will want to use probably Canvas to draw: http://diveintohtml5.info/canvas.html
For dragging the wheel you will need to handle mouse down, mouse move and mouse up events.

Categories

Resources