I want to draw a hexagon and show an image inside that using html5.
I have tried it out but I am not getting image as the result.
I want to use kineticjs only for this.
Here is the code:
function hexagon(){
var stage = new Kinetic.Stage({
container: "container"
});
var layer = new Kinetic.Layer();
var hexagon = new Kinetic.RegularPolygon({
x: 100,
y: 100,
sides: 6,
radius: 100,
fill: {image: "css/images/logo.png"},
stroke: "royalblue",
strokeWidth: 2
});
// add the shape to the layer
layer.add(hexagon);
// add the layer to the stage
stage.add(layer);
}
fill takes an image object. Try the following:
var layer = new Kinetic.Layer();
logo = new Image();
logo.src = "css/images/logo.png";
var hexagon = new Kinetic.RegularPolygon({
x: 100,
y: 100,
sides: 6,
radius: 100,
fill: {image: logo},
stroke: "royalblue",
strokeWidth: 2
});
// add the shape to the layer
layer.add(hexagon);
// add the layer to the stage
stage.add(layer);
}
The author of KinectJS has written some really great tutorials. In this one he draws an image in a pentagon, as well as a few other things. Should be enough to help you.
http://www.html5canvastutorials.com/kineticjs/html5-canvas-set-fill-with-kineticjs/
I have got the solution.
Posting it late (better late than never)
It should be:
fill: {image: "css/images/logo.png", offset: [0, 0]}
Related
I want to make free drawing on top of shapes at konvajs. like an exp; Can u give me advise about shapes attrs like zindex or smt.
https://ibb.co/jq9pUK
Your question is very broad and you are not showing what you have tried so far. You would get better help faster if you give a clear description and post cut-down sample code for your questions.
Konvajs works on top of the HTML5 canvas. When working with a konvajs you put shapes, lines, images and text on to layers. Layers have a z-order and shapes on a layer have a z-order.
To answer your question, I would follow the pattern:
- create the stage
- create the shape layer
- add the shapes to the shape layer - triangles, rectangles, circles, etc
- add another layer for the freehand drawing
- draw on this layer.
Because of the sequence of adding the components to the canvas the z-order will support what you ask for in your question. If you wanted the drawing to happen 'behind' the shapes you would create the layers in the opposite sequence.
The working snippet below shows how to do the steps that I have listed above, and how to listen for the events you need to make it operate. You can extend from this starter code to handle erasing, selecting line colour, thickness, and stroke style. See the Konvajs drawing tutorial for more information.
Good luck.
// Set up the canvas / stage
var s1 = new Konva.Stage({container: 'container1', width: 300, height: 200});
// Add a layer for the shapes
var layer1 = new Konva.Layer({draggable: false});
s1.add(layer1);
// draw a cirlce
var circle = new Konva.Circle({
x: 80,
y: s1.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
})
layer1.add(circle)
// draw a wedge.
var wedge = new Konva.Wedge({
x: 200,
y: s1.getHeight() / 2,
radius: 70,
angle: 60,
fill: 'gold',
stroke: 'black',
strokeWidth: 4,
rotation: -120
});
layer1.add(wedge)
// Now add a layer for freehand drawing
var layer2 = new Konva.Layer({draggable: false});
s1.add(layer2);
// Add a rectangle to layer2 to catch events. Make it semi-transparent
var r = new Konva.Rect({x:0, y: 0, width: 300, height: 200, fill: 'blue', opacity: 0.1})
layer2.add(r)
// Everything is ready so draw the canvas objects set up so far.
s1.draw()
var drawingLine = null; // handle to the line we are drawing
var isPaint = false; // flag to indicate we are painting
// Listen for mouse down on the rectangle. When we get one, get a new line and set the initial point
r.on('mousedown touchstart', function () {
isPaint = true;
var pos = s1.getPointerPosition();
drawingLine = newLine(pos.x, pos.y);
drawingLine.points(drawingLine.points().concat(pos.x,pos.y));
layer2.draw();
});
// Listen for mouse up ON THE STAGE, because the mouseup will not fire on the rect because the mouse is actually over the line point we just drew when it is released.
s1.on('mouseup touchend', function () {
isPaint = false;
drawingLine = null;
});
// when the mouse is moved, add the position to the line points and refresh the layer to see the effect.
r.on('mousemove touchmove', function () {
if (!isPaint) {
return;
}
var pos = s1.getPointerPosition();
drawingLine.points(drawingLine.points().concat(pos.x,pos.y));
layer2.draw();
})
// Function to add and return a line object. We will extend this line to give the appearance of drawing.
function newLine(x,y){
var line = new Konva.Line({
points: [x,y,x,y],
stroke: 'limegreen',
strokeWidth: 4,
lineCap: 'round',
lineJoin: 'round'
});
layer2.add(line)
return line;
}
p
{
padding: 4px;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.rawgit.com/konvajs/konva/1.6.5/konva.min.js"></script>
<p>Click & drag on the canvas to draw a line over the shapes.
</p>
<div id='container1' style="display: inline-block; width: 300px, height: 200px; background-color: silver; overflow: hidden; position: relative;"></div>
I am using the following to change the style of the cursor when the mouse is over the circle:
circle1.on('mouseover', function () {
document.body.style.cursor = 'pointer';
});
circle1.on('mouseout', function () {
document.body.style.cursor = 'default';
});
It works great if I draw the circle using:
var circle1 = new Kinetic.Circle({
x: 512,
y: 512,
radius: 140,
stroke: '#00ffff',
strokeWidth: 4,
opacity: 0.5
});
However if I use:
var circle1 = new Kinetic.Circle({
drawFunc: function (canvas) {
var context1 = canvas.getContext();
context1.beginPath();
context1.arc(512, 512, this.getRadius(), 0, 2 * Math.PI, false);
context1.lineWidth = this.getStrokeWidth();
context1.strokeStyle = this.getStroke();
context1.stroke();
},
radius: 140,
stroke: '#00ffff',
strokeWidth: 15,
opacity: 0.5
});
It does not work! The cursor does not change its style; can we just use radius for mouse over. I would appreciate your suggestions, thanks in advance.
As I know you also need to define "drawHitFunc":
circle1.setDrawHitFunc(function (canvas) {
var context2 = canvas.getContext();
context2.beginPath();
context2.arc(100, 100, this.getRadius(), 0, 2 * Math.PI, false);
context2.closePath();
canvas.fillStroke(this);
});
Example: http://jsfiddle.net/lavrton/4DJdU/1/
no, you just need to correctly structure the drawFunc when creating custom shapes. Here's an example:
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-shape-tutorial/
The problem is that you're using context.stroke(). You need to use canvas.stroke(this);
Anytime you actually render something, like strokes and fills, you need to use the canvas renderer object because it draws onto both the scene graph (what you see) and a specialized hit graph (used for event detection)
Docs:
http://kineticjs.com/docs/symbols/Kinetic.Canvas.php
Is it possible to change the background with an image fading in after a set time?
I am using the following code, but the image is not fading in. All I am achieving now is fading out the image with the transitionTo method, however I want it to fade in.
This is the code I am playing with:
var stage = new Kinetic.Stage({
container: 'container',
width: 1770,
height: 900
});
var layer = new Kinetic.Layer();
var imageObj = new Image();
imageObj.onload = function() {
var myBg = new Kinetic.Image({
x: 0,
y: 0,
image: imageObj,
width: 1770,
height: 900
});
// add the shape to the layer
layer.add(myBg);
// add the layer to the stage
stage.add(layer);
setTimeout(function() {
myBg.transitionTo({
opacity: 0,
duration: 4,
});
}, 3000);
};
imageObj.src = 'bg.png';
Can someone kindly shed some light?
It happens because you did not set initial opacity. What you were doing is setting opacity from 1 to 1, not from 0 to 1. please refer the following code.
var myBg = new Kinetic.Image({
x: 0,
y: 0,
image: imageObj,
opacity: 0,
width: 1770,
height: 900
});
myBg.transitionTo({
opacity: 1,
duration: 4,
})
I currently used KineticJS (version:4.2.0) to do something, but when I want to set corner radius for a kinetic image object, it seems it doesn't work at all. Do anyone have any ideas?
My code is like this:
var stage = new Kinetic.Stage({
container: 'container',
width: 901,
height: 532,
});
var bg = new Kinetic.Layer(); // slot's shell
var bgObj = new Image();
bgObj.onload = function() {
var item = new Kinetic.Image({
x: 0,
y: 0,
width: 901,
height: 532,
image: bgObj,
cornerRadius: 25
});
bg.add(item);
stage.add(bg);
};
bgObj.src = "background.png";
Thanks.
corner radius currently isn't implemented for Image. In fact there's an error with the documentation because only Rectangle supports rounded corners. Images will support rounded corners soon.
I have a problem an hope to find any solution for it.
I am using Kinetic.js to create a HMI solution with special look-and-feel. Therefor I have created a function that creates 3 layers for a stage: a background layer with a grid, a layer with static shapes for the base layout of the HMI-screen and the third layer for all interactive elements (like buttons, valuedisplays and so on...). Now I want to cache the grid and the static layer to improve performance, because this layers will never change until the whole HMI-screen will change...
As a test I started to code the caching for the grid layer using the following code:
// Create a grid layer if showGrid is set to TRUE...
console.log('Start to create background grid if required');
if (this.actualPageConfig.showGrid) {
var grid = new Kinetic.Layer();
for (var x=1; x <= this.cols; x++) {
var eLoc = LCARSElements.posToRealPos(x, 1, this.cols, this.rows);
if (x <= this.actualPageConfig.columns) {
grid.add(new Kinetic.Line({
points: [eLoc.x, eLoc.y, eLoc.x, eLoc.height],
stroke: "red",
strokeWidth: 1,
lineCap: "round",
lineJoin: "round"
}));
}
}
for (var y=1; y <= this.rows; y++) {
var eLoc = LCARSElements.posToRealPos(1, y, this.cols, this.rows);
if (y <= this.actualPageConfig.rows) {
grid.add(new Kinetic.Line({
points: [eLoc.x, eLoc.y, eLoc.width, eLoc.y],
stroke: "red",
strokeWidth: 1,
lineCap: "round",
lineJoin: "round"
}));
}
}
// Add grid layer to stage
//this.stage.add(grid); <-- to be replaced by cache image
// Convert grid into an image and add this to the stage
console.log('convert grid to image to increase performance');
grid.toImage({
width: displayManager.stage.getWidth(),
height: displayManager.stage.getHeight(),
callback: function(img) {
var cacheGrid = new Kinetic.Image({
image: img,
x: 0,
y: 0,
width: displayManager.stage.getWidth(),
height: displayManager.stage.getHeight()
});
console.log('insert grid-image to stage');
displayManager.stage.add(cacheGrid);
console.log('redraw stage...');
displayManager.stage.draw();
}
});
}
My problem is, that's not working. The grid is not visible any more and the console log shows the following error information:
Type error: layer.canvas is undefined
layer.canvas.setSize(this.attrs.width, this.attrs.height); kinetic.js (Zeile 3167)
As I already figured out the error rise when the code "displayManger.stage.add(cacheGrid) will be executed (displayManager is the outside-class where this code snipped reside).
Can anyone see where I made the mistake? When I directly add the layer grid anything works fine...
I have created a jsfiddle to demonstrate the problem: jsfiddle
In fiddle you can run both versions by changing one parameter. Hope this helps....
Thanks for help.
Best regards
Thorsten
Actually, the problem is simpler than you might think - after caching the layer into an image, you're trying to add an image object directly to the stage (you can't do that).
To fix the problem, you need to create a new layer, say cahcedLayer, add the image to cachedLayer, and then add cachedLayer to the stage.
Check out the KineticJS info page to learn more about Node nesting:
https://github.com/ericdrowell/KineticJS/wiki
http://rvillani.com/testes/layer-to-image/
I've made this test and it worked. First, I draw 1000 squares to a layer, add this layer to a hidden stage then make an image from this stage using stage.toDataURL(). When the callback returns, I just create an Image from the data and a Kinetic.Image from the Image. Then I add it to a layer on my main (visible) stage.
Code (be sure to have a div called 'invisible'):
window.onload = function()
{
var stage = new Kinetic.Stage({
width: 520,
height: 480,
container: 'container'
});
var outerStage = new Kinetic.Stage({
width: stage.getWidth(),
height: stage.getHeight(),
container: 'invisible'
});
var layerToCache = new Kinetic.Layer();
var layer = new Kinetic.Layer();
var group = new Kinetic.Group({offset: [stage.getWidth(), stage.getHeight()]});
var anim = new Kinetic.Animation(function(frame){
group.rotate(0.02);
}, layer);
var fills = ['red', 'green', 'blue', 'orange', 'purple', 'cyan',
'black', 'brown', 'forestgreen', 'gray', 'pink'];
for (var i = 0; i < 10000; ++i)
{
(function ()
{
var size = Math.random() * 60 + 20;
var square = new Kinetic.Rect({
width: size,
height: size,
fill: fills[i % fills.length],
x: Math.random() * stage.getWidth() - 20,
y: Math.random() * stage.getHeight() - 20
});
layerToCache.add(square);
})();
}
var squaresImg = new Kinetic.Image();
outerStage.add(layerToCache);
outerStage.toDataURL({
callback: function (dataURL){
outerStage.clear();
var img = new Image();
img.src = dataURL;
img.onload = function () {
squaresImg.setImage(img);
squaresImg.setX(squaresImg.getWidth() >> 1);
squaresImg.setY(squaresImg.getHeight() >> 1);
group.setX(stage.getWidth() >> 1);
group.setY(stage.getHeight() >> 1);
group.add(squaresImg);
layer.add(group);
layer.draw();
anim.start();
}
}
});
var div = document.getElementById('invisible');
div.parentNode.removeChild(div);
stage.add(layer);
}