KineticJS takes hold of the canvases and controls their size and position.
I would like to have KineticJS render a layer to an offscreen 5000x2500 canvas, it seems a little complicated and "hacky" to get something like this done within KineticJS.
The only viable solution I can think of is to create a separate KineticJS Stage object and hide the container.
Any ideas, what the best method would be? Thanks!
Use a KineticJS custom shape object as a viewport into an offscreen html5 canvas element
The Kinetic.Shape object gives you access to many of the canvas and context properties/methods necessary to interface with a regular offscreen canvas element.
Related
i'm a beginner in Javascript so please bear with me.
Basically I'm making a sandbox drawing facility for a website using Javascript. And this is done using the canvas. What I need to do is to be able to resize the canvas dynamically but at the same time keep everything on the canvas to scale.
I don't think this question has been asked before. It seems trivial but I currently have all my objects on the canvas defined in absolute coordinates. I also have mouse events to use to draw things. And when I want to enlarge the canvas (by doubling the size say). All the objects inside won't be enlarged properly to scale and the mouse coordinate system would be messed up too.
Only solution i can think of is add a scale factor to ALL my drawing parts, but this is very tricky with a lot of code. Is there a better way?
If you don't mind jaggies on your double-sized canvas drawings then you can simply use CSS to double-size your canvas. Then divide every incoming mouseEvent coordinate by 2.
If you don't want jaggies on your double-sized canvas then:
Double-size the canvas element: canvas.width*=2 and canvas.height*=2 This automatically erases all canvas content.
Scale up the canvas: context.scale(2,2)
Redraw all your drawing parts using the unchanged original coordinates. A happy note: you do not have to scale any of your drawing coordinates -- context.scale automatically does that for you.
Divide every incoming mouseEvent coordinate by 2.
I'm creating an animated diagram and I'm trying to use a native canvas element as well as kineticjs for the animations. I know that kinetic creates a hidden canvas element, but my question is. Is it possible to stop kinetic from doing this and implement the kinetic framework into a native canvas element?
Every KineticJS layer is a visible drawing canvas plus an invisible canvas used for Kinetic's internal purposes.
The drawing canvas is a "native canvas element".
Normally Kinetic does all the drawing for you, but...
You can use Kinetic.Shape objects to issue native drawing commands directly to the html canvas element.
The Kinetic.Shape object gives you a canvas context that you can use to create your custom diagram.
This context is actually a Kinetic wrapper around the actual context. If there is a command that the wrapper hasn't implemented yet you can get the real canvas context like this:
var myRealCanvasContext=this.getContext()._context;
I've looked around for layering objects within the same canvas but haven't found a lot of information about it.
At the moment I've used the multiple canvas technique to layer things on top of each other
example:
canvas Holder <--- this holds all other canvas's
loading canvas
menu canvas
game canvas
background canvas
and by adding them to the "stage = new stage (mainCanvas)" in a specific order, i get the desired layering
stage.addChild(background);
stage.addChild(game);
stage.addChild(menu);
stage.addChild(loading);
This works great, however I'm wondering whether there is a way to change the zIndex of an image added to the 'game' canvas if I had 2 images in that canvas?
I've seen this sort of thing done in the fieldrunners game, the game follows a grid like format and when you place a shooter in the square above another shooter, is gets repositioned behind it..
http://fieldrunnershtml5.appspot.com/#sd --- works in chrome
any ideas how it was done?
Thanks
There is no need for multiple canvases. When you work with a game in canvas 2d you usually clear and redraw the canvas ~60 times per second. What you draw last ends up on top. So in order to simulate layers you sort all game objects in an array based on their z-index then you iterate over all objects in the array, invoking their draw methods.
There is much room for optimizing such a renderer, but this is a basic and simple way to make it work.
A canvas is just pixels - it has no "layers".
If you want to perform parallax scrolling, that sort of thing, put multiple canvases in the same place, and use transparency to show the ones behind.
Your technique using multiple canvases to implement layers is totally good approach. You should also keep track on which layer needs to be cleared/redrawn - for example map should be refreshed only when scrolled or GUI/HUD really doesn't need to be redrawn 60 times per second.
There is no such thing as z-index or objects in canvas, all mechanisms depends on your own implementation. For example you can make an array of commands or objects to draw - then sort it by zIndex (or whatever you name it) and execute each element.
Is it possible to export Kinetic JS object to SVG?
Or workaround is to convert Kintetic JS's canvas to SVG.
EDIT:
The best is to use fabricJS since it supports canvas to SVG rendering while working with fabric objects.
I accepted Phrogz's answer since it also does conversion canvas to svg without using some other library for drawing on canvas.
EDIT 2: OK, i messed up, Phrogz's library is wrapper around canvas element so you use it's methods to draw on canvas (I thought that it just 'listens' on canvas and creates SVG paths). So the best solution is fabricJS definitely.
The best solution is to use Fabric.js!
I've created an alpha version of a library that allows you to extend an HTML5 Canvas Context such that it tracks all vector drawing commands and stores them as an array SVG elements in a ctx.svgObjects property of the context.
You can see the library in action here: http://phrogz.net/svg/HTML5CanvasRecordsSVG.html
The demo turns on recording, draws a few shapes to the HTML5 Canvas, and then appends the 'recorded' SVG objects to an SVG container next door.
In general the library:
Keeps track of the current context transformation via an SVGMatrix object. (This is because the HTML5 Context api lets you set the current transform to a matrix, but does not let you get the current matrix.) It does this by intercepting calls like translate() and rotate() and updating the matrix accordingly.
Intercepts beginPath() and creates a new SVG Path element, and then intercepts further commands like moveTo() and lineTo() in order to add the equivalent path commands to the SVG path.
Note: not all path commands are supported or tested in the library at the time of this writing.
Intercepts fill() and stroke() to add a copy of the current SVG <path> to the svgObjects array, setting the current transformation matrix, fill and stroke styles.
Note: not all stroke styles (lineCap, lineJoin, miterLimit) are supported as of this writing.
Note: calling fill() followed by stroke() creates two separate SVG elements; there is no optimization to differentiate this specific case from stroke/fill, or changing the transform or path between calls.
Intercepts fillRect() and strokeRect() to create an SVG <rect> element.
More work could be done on this library to flesh out all the commands (not just path commands, but also things like fillText()). But it's not something that I personally need, so I'm not inclined to spend hours carrying it over the finish line.
basicly you can convert the canvas to base64 png and then put it on svg
maybe this could help you
http://svgkit.sourceforge.net/tests/canvas_tests.html
I'm currently implementing a HTML canvas based webapp that features panning. Is there a way to use an auxiliary buffer to hold the presently visible area so when I pan I don't have to redraw the whole canvas and only have to draw the newly visible areas?
See my previous response to a related question: What is the fastest way to move a rectangular (pixel) region inside a HTML5 canvas element
Just draw the entire canvas in a div that has overflow:hidden and implement panning as re-positioning the top and left of the canvas within that div. It is much faster. And don't worry about drawing canvases tens of thousands of pixels wide/tall, I've successfully used this on very-very large and complex HTML and SVG elements.
Take a look at the pixel manipulation API.
http://dev.w3.org/html5/2dcontext/#pixel-manipulation