I would like to create an interface where I can scroll or scrub through the frames of an animation that was created using svg.js (http://www.svgjs.com/). Is there any way I can create this, maybe using a web app framework like Angular JS?
E.g there is a div with the animation and a timeline below in which I could scroll and move through the animation.
You can scrub through animations with svg.js:
http://documentup.com/wout/svg.js#animating-elements/controlling-animations-externally
Here is a quick example:
// Create svg.js canvas
var draw = SVG('canvas')
// Create circle
var circle = draw.circle(100).move(100, 10).fill('#fff').animate('=', SVG.easing.backOut).move(200,200)
// Create image
var image = draw.image('http://distilleryimage11.s3.amazonaws.com/89ac2e90d9b111e297bf22000a1f9263_7.jpg', 100, 100).move(10, 100).animate('=', SVG.easing.elastic).y(300)
// Use mouse movement to animate elements
document.onmousemove = function(event) {
circle.to(event.clientX / 1000)
image.to(event.clientY / 1000)
}
(load both svg.js and the svg.easing.js plugin to make it work)
You can see it in action here:
http://jsfiddle.net/wout/BqqNs/
Roll your mouse over the pink canvas to see the result.
Related
I am using Fabric JS to allow the user to have an interactive experience on my React app. Is it possible to apply a frame around a Fabric JS that is taken from an image? For instance, if the canvas is 400x400 px I can resize an image of a frame that is transparent in the middle to 410x410px and apply it on top of the canvas for the user to see? I have attached two images for reference.
Edit: This is the code I am using for zooming in
const zoomIn = useCallback(() => {
// Get original height of canvas
const canvasDimensions = getInitialCanvasSize()
let zoom = HTML5Canvas.getZoom()
zoom += 0.2
if (zoom >= 2) zoom = 2
HTML5Canvas.setZoom(zoom)
HTML5Canvas.setWidth(canvasDimensions.width * HTML5Canvas.getZoom());
HTML5Canvas.setHeight(canvasDimensions.height * HTML5Canvas.getZoom());
}, [HTML5Canvas])
There is no option for canvas's border in fabricjs canvas docs
But you can still achieve this easily using following steps.
PART 1: Creating the Illusion of border
CSS Method
First one can easily create CSS border around the canvas.
Best way to do this is to create div around canvas, as fabricjs split canvas in 2 while running.
You can create slider to control width and color/image for div's border.
This will looks like exactly your second image with customization.
OR
Another Canvas Method
Behind current canvas put this second canvas and control its width and image.
I don't recommend this one, as this will make it more complex to implement.
PART 2: Making Illusion real
If you used CSS METHOD
Now you get what your canvas looks like. You have width of border, image/color of border.
Steps:
Create new canvas (lets' call it 2nd Canvas) of 410px if canvas's width 400px with border of 5px.
Export main canvas as image and put it over 2nd Canvas. And now you can export this as final image.
For 2nd step check my answer on this stack
If you used Another Canvas Method
Directly follow above 2nd step
Export main canvas as image and put it over 2nd Canvas. And now you can export this as final image.
For 2nd step check my answer on this stack
This application is made with Easeljs, to work in HTML5 canvas.
I want to be able to draw different kinds of arrows on the board. I tried inserting arrows as images and then making them draggable and resizable, but that made these images pretty ugly.
To illustrate:
Field to draw on
Arrows to draw on the field
The functionality should be as follows:
Click on the button
Draw a line
At mouseup event: convert line into corresponding arrow
Arrow should be draggable and resizable
How would I get this result?
You can fairly easily draw arrows using the Graphics API. I spent about 20 mins making this demo:
http://jsfiddle.net/lannymcnie/ukjb1g2g/2/
http://jsfiddle.net/lannymcnie/ukjb1g2g/3/
Code:
var w = startX - endX;
var h = startY - endY;
var lineLength = Math.sqrt(w*w+h*h);
arrow.graphics.clear().setStrokeStyle(3).beginStroke("#000").moveTo(0,0);
// Logic to draw to the end. This is just a straight line
arrow.lineTo(lineLength-arrowHeadSize, 0);
arrow.graphics.beginFill("#000");
arrow.graphics.drawPolyStar(lineLength, 0, arrowHeadSize, 3);
// Rotate
arrow.rotation = Math.atan2(h, w) * 180/Math.PI;
Drawing it straight and rotating it is the easiest way to add effects to the line. The demo I posted draws a sort of sine-wave like one of your examples. There is some more magic in there to make it the right length, etc.
I have s1,s2,s3,s4,...s40 SVG image files in deployment subfolder .i want to load each image with replacing other with the help of cursor key controls/mouse clicks on parts of html text.Is it possible through d3.js?
Yes it is possible using d3.js.
// There are probably better ways of loading the SVG, but this is one example I found
d3.xml("test.svg", "image/svg+xml", function(xml) {
d3.select("body").node().appendChild(xml.documentElement);
svg=d3.select("body").select("svg");
console.log(svg[0][0])
slides = svg_slides(svg,1500);
setTimeout(function() { svg_interact(svg);console.log("OK")},100);
// Lets test the slide scales - put a bouncing ball on slide id 3
s = slides[3];
circle = svg.append("svg:circle")
.attr("cx",s.scale_x(500)).attr("cy",s.scale_y(500))
.attr("r",20)
.style("fill","steelblue");
next = 500;
function bounce() {
next = -next;
circle.transition().duration(2500).attr("cx",s.scale_x(500+next))
.each("end",bounce);
}
bounce();
});
See the demo here.. http://bl.ocks.org/ZJONSSON/raw/1254855/
You can find the detailed explanation and code snippet here.. http://bl.ocks.org/ZJONSSON/1254855
I am currently experimenting with parallax effect that i am planning to implement to my HTML5-canvas game engine.
The effect itself is fairly easy to achieve, but when you add zooming and rotating, things get a little more complicated, at least for me. My goal is to achieve something like this:Youtube video.
As you can see, you can zoom in and out "to the center", and also rotate around it and get the parallax effect.
In my engine i want to have multiple canvases that are going to be my parallax layers, and i am going to translate them.
I came up with something like this:
var parallax = {
target: {
x: Mouse.x,
y: Mouse.y
},
offset: {
x: -ctx.width / 2,
y: -ctx.height / 2
},
factor: {
x: 1,
y: 1
}
}
var angle = 0;
var zoomX = 1;
var zoomY = 1;
var loop = function(){
ctx.canvas.width = ctx.canvas.width; //Clear the canvas.
ctx.translate(parallax.target.x * parallax.factor.x, parallax.target.y * parallax.factor.y);
ctx.rotate(angle);
ctx.scale(zoomX, zoomY);
ctx.translate((-parallax.target.x - parallax.offset.x) * parallax.factor.x, (-parallax.target.y - parallax.offset.y) * parallax.factor.y);
Draw(); //Function that draws all the objects on the screen.
}
This is a very small and simplified part of my script, but i hope that's enough to get what i am doing. The object "parallax" contains the target position, the offset(the distance from the target), and the factor that is determining how fast the canvas is moving away relatively to the target. ctx is the canvas that is moving in the opposite direction of the target.(In this example i am using only one layer.) I am using the mouse as the "target", but i could also use the player, or some other object with x and y property. The target is also the point around which i rotate and scale the canvas.
This method works completely fine as long as the factor is equal to 1. If it is something else, the whole thing suddenly stops working correctly, and when i try to zoom, it zooms to the top-left corner, not the target. I also noticed that if i zoom out too much, the canvas is not moving in the opposite way of the target, but in the same direction.
So my question is: What is the correct way of implementing parallax with zooming and rotating?
P.S. It is important to me that i am using canvases as the layers.
To prepare for the next animation frame, you must undo any previous transforms in the reverse order they were executed:
context.translate(x,y);
context.scale(sx,sy);
context.rotate(r);
// draw stuff
context.rotate(-r);
context.scale(-sx,-sy);
context.translate(-x,-y);
Alternatively, you can use context.save / context.restore to undo the previous transforms.
Adjust your parallax values for the current frame,
Save the un-transformed context state using context.save(),
Do your transforms (translate, scale, rotate, etc),
Draw you objects as if they were in non-transformed space with [0,0] at your translate point,
Restore your context to it's untransformed state using context.restore()/
Either way will correctly give you a default-oriented canvas to use for your next animation frame.
The exact parallax effects you apply are up to your own design, but using these methods will make the canvas return to a normal default state for you to design with.
I'm building a canvas user interface with jquery and fabric.js library and I set an overlay png image with a transparent section using the following code
var bgImgSrc = bgImg.attr('src');
canvas.setOverlayImage(bgImgSrc, function(img){
canvas.renderAll();
});
I also added an image behind the overlay and resized to fit the container using the following code
var photoImg = $('#img-photo');
var photoImgSrc = photoImg.attr('src');
fabric.Image.fromURL(photoImgSrc, function(img) {
var photoImgWidth = photoImg.width();
var photoImgHeight = photoImg.height();
var hRatio = 380/photoImgWidth;
var vRatio = 300/photoImgHeight;
var ratio = Math.min(hRatio, vRatio);
pImg = img.set({left: 380/2, top: 300/2, angle: 0})
img.scale(ratio).setCoords();
canvas.add(pImg);
canvas.sendToBack(pImg);
canvas.renderAll();
});
And it works as expected, however, when I click on the image to scale/resize it, I don't see the controls, except through the transparent space of the overlay image. Controls are behind the overlay image, is there a way to force show the image controls without having to put the entire image in front of the overlay?
Just set the boolean controlsAboveOverlay:
canvas.controlsAboveOverlay = true;
The problem here is that overlay image is rendered on top of objects' controls. This is expected behavior. Take a look at this wiki article, which shows the z-index of various things on fabric canvas and in which order they're rendered.
There are plans to add support for object controls that are always on top, as you can see from this ticket, but I can't tell you when that's going to happen.
You can also try using "after:render" callback and draw image manually onto canvas.
canvas.controlsAboveOverlay = true; //did the job... but:
I don't want to render controls above the overlay image (as overlay means overlay to me). I just want to render the stack exactly as described in Wiki (by default).
I just wonder...as described in the Wiki rendering-stack, the controls should be rendered on top of all objects (always visible by default), but they do not (look at kitchensink demo).
IMHO this behaviour should be set by a flag like canvas.controlsInStack = true.
By the way ... that thing is really beautiful!