Make kineticjs use existing canvas - javascript

I am attempting to use kinetic.js with an existing canvas. The problem is that the kinetic.js API requires that you specify the id of the container element and then kinetic.js creates a Kinetic.Stage (which creates and uses its own canvas).
For instance:
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 239,
y: 75,
width: 100,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 4
});
// add the shape to the layer
layer.add(rect);
// add the layer to the stage
stage.add(layer);
</script>
I want to be able to use an existing canvas element with kinetic.js instead of it creating its own. Is this possible?
A similar question has been asked before, however it doesn't seem to provide a correct answer.
Any ideas? Thanks!

An html canvas is just a bunch of pixels.
You can convert those pixels into an image and then use that image as the source for a Kinetic.Image.
// create an image from the existing canvas
var canvas2Image=new Image();
canvas2Image.onload=function(){
// create a Kinetic.Image using that image
var kImage=new Kinetic.Image({
x:0,
y:0,
width:canvas2Image.width,
height:canvas2Image.height,
image:canvas2Image
});
}
canvas2Image.src=canvas.toDataURL();

Related

How to include typeface.json font file in three.js?

I want to add 3D text in my website using the code (according to Labelling the vertices in AxisHelper of THREE.js ) below:
var textGeo = new THREE.TextGeometry('Test', {
size: 10,
height: 5,
curveSegments: 6,
font: "helvetiker",
style: "normal"});
var color = new THREE.Color();
color.setRGB(255, 250, 250);
var textMaterial = new THREE.MeshBasicMaterial({ color: color });
var text = new THREE.Mesh(textGeo , textMaterial);
scene.add(text);
This requires including helvetiker_regular.typeface.js font file before using text Geometry as Three.js needs it for loading text geomtery.
What I find is json file such as "helvetiker_regular.typeface.json" (https://github.com/mrdoob/three.js/tree/master/examples/fonts).
Just a rookie in JS programing.
Can someone tell me how to include it to make my code work?
You'll need to use a font loader to load the font first:
var fontLoader = new THREE.FontLoader();
fontLoader.load("../path/to/font.json",function(tex){
var textGeo = new THREE.TextGeometry('Test', {
size: 10,
height: 5,
curveSegments: 6,
font: tex,
});
var color = new THREE.Color();
color.setRGB(255, 250, 250);
var textMaterial = new THREE.MeshBasicMaterial({ color: color });
var text = new THREE.Mesh(textGeo , textMaterial);
scene.add(text);
})
Something like that will work if you just want to load it once and dont care about keeping the texture for another time. If you need to keep the "tex" object you could preload it somewhere in the code, and have it accessible for all future textgeometry objects..

Paper.js eraser tool made using layers and blendMode

I am making simple drawing app using Paper.js and Node.js. There are 2 layers:
- bottom layer with images
- top layer for drawing.
Layer with images is background to drawing layer.
I want to make a simple eraser tool which will erase drawing on a path. I'm trying to do it adding second path in my top layer which has blendMode set to "destination-out".
drawingLayer.activate();
path = new Path();
path.strokeColor = 'black';
path.strokeWidth = 5;
if (mode == "erase") {
path.strokeWidth = 15;
path.blendMode = 'destination-out';
}
My problem is that this "destination-out" path erases not only everything on top layer (drawing layer) but also everything on the bottom layer (images). Of course I want images to stay untouched by eraser. When I set some background in css for my page it is not erased by the eraser path.
Do you know a way to make eraser to modify one top layer while not modyfing bottom layer?
The solution is to activate the layer you want to erase in just before using the eraser tool, like this:
var firstLayer = paper.project.activeLayer; //This one is used to erase
var shapesLayer = new Layer(); // We don't want to erase on this one
so basically, when eraser tool is selected I do
firstLayer.activate();
Then when I want to draw shapes just activate the 'shapesLayer' the same way. This avoids the tool (the one used for erasing) touch anything from 'shapesLayer'
In order to do this, you have to encapsulate your drawings items and your eraser items into a group which has the blend mode source-over.
This way, the background items won't be affected by the eraser items destination-out blend mode.
Here's a simple sketch demonstrating this.
const backgroundCircle = new Path.Circle({
center: view.center,
radius: 50,
fillColor: 'orange'
});
const foregroundCircle = new Path.Circle({
center: view.center + 20,
radius: 50,
fillColor: 'blue'
});
const eraserCircle = new Path.Circle({
center: view.center + [10, 0],
radius: 50,
fillColor: 'black',
blendMode: 'destination-out'
});
const foreground = new Group({
children: [foregroundCircle, eraserCircle],
blendMode:'source-over'
});

Draw Multiple figures in a stage using Kineticjs?

I want to draw multiple figures on a canvas on different button clicks.
HTML
<body>
<div id="container">
</div>
<div id="option">
<button value="rect" onclick="rect();">rect</button>
<button value="circle" onclick="circle();">circle</button>
</div>
</body>
Javascript:
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer();
function rect(){
var redLine = new Kinetic.Line({
points: [100, 5, 100, 300, 450,300],
stroke: 'black',
strokeWidth: 3,
lineCap: 'square',
lineJoin: 'mitter'
});
// add the shape to the layer
layer.add(redLine);
// add the layer to the stage
stage.add(layer);
}
function circle(){
var wedge = new Kinetic.Wedge({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
angleDeg: 60,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
rotationDeg: -120
});
// add the shape to the layer
layer.add(wedge);
// add the layer to the stage
stage.add(layer);
}
But it gives error as layer and stage are not defined. How do I solve it ?
The reasons that stage and layer would not be defined are that either they are outside of scope, or your code is breaking before they are instantiated in the first place.
First, make sure that your stage and layer are outside of any functions; global scope.
Second, your functions 'circle()' and 'rect()' are being called with the button click, which I suspect is breaking your code. You want to remove this onclick handler from inline:
<button value="circle" onclick="circle();">circle</button>
and assign onclick using javascript, after you have created your stage. You can assign handlers easily using jQuery. So your code should look something like:
HTML
<button value="rect" id='rect'>rect</button> //assign an id to your button
JS
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer();
$('#yourButtonId').click(function(){ // button id here would be '#rect' if you use the id above
rect();
});

In kinetic.js Issue with rotating a kinetic.group

I am using kinetic js. I am adding image, lines, etc to a kinetic.group and trying to rotate the group and it is getting rotated correctly. But after rotating the group, if I try to draw a line it is not correctly drawing on the present mouse position. It is drawing as it was before rotating.
The problem may be that if I rotate the group, the stage co-ordinates are not getting rotated it seems. What should I do to prevent this?
reference code---
var rootGroup = new Kinetic.Group({
x: stage.getWidth()/3,
y: stage.getWidth()/6,
draggable: true,
offset: [images.darthVader.width/2, images.darthVader.height/2]
});
rootGroup.add(line);
rootGroup.setRotationDeg(rootGroup.getRotationDeg()+90);
IN THIS WAY I AM DRAWING THE LINE.
var activeline = new Kinetic.Line({
points: [{x:0,y:0}],
stroke: "blue",
strokeWidth: 3,
lineCap: "round",
lineJoin: "round",
});
var mousePos = stage.getMousePosition();
points.push({
x: mousePos.x,
y: mousePos.y
});
activeline.setPoints(points);
rootGroup.add(activeline);
I'm not familiar with KineticJS, but it seems that you have to reset the transformation matrix back to its default state. OpenGL has the glLoadIdentity() method. Search for a similiar method on KineticJS.
See this tutorial
http://www.html5canvastutorials.com/advanced/html5-canvas-reset-transform-tutorial/
This should get you fairly close: http://jsfiddle.net/k4qB8/24/
// This rotates that added active line along with your group.
// This makes the draw direction correct
activeline.setRotationDeg(0-rootGroup.getRotationDeg());

Kinetic.js Can't Load image onto canvas

I have to be missing something simple. I have gone fairly line-by-line, but it just doesn't seem to work. I can't get the image to load.
var imageToCanvas = function(){
var stage = new Kinetic.Stage("imgarea", 250, 256);
var layer = new Kinetic.Layer();
var imageobj = new Image();
imageobj.onload = function(){
var img = new Kinetic.Image({
x: 10,
y: 10,
image: imageobj,
});
layer.add(img);
stage.add(layer);
};
imageobj.src = "/static/img/unit-test-image.png";
console.log(imageobj);
};
$(document).ready( function(){
imageToCanvas();
});
<canvas id="imgarea" width="250px" height="256px"></canvas>
the same code seems to work in another canvas app that I used Kinetc.js with. I just can't seem to figure out why this one isn't working.
The code also looks fairly similar to the tutorial as well: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-image-tutorial/
It looks like you're not defining the stage properly.. When I tried your code above I got an error about the container not being defined.. Try this instead..
var stage = new Kinetic.Stage({
container: "imgarea",
width: 250,
height: 256
});

Categories

Resources