im creating a boardgame, with a hexagon shaped tilebased map. i used konva to create the hexagons/polygons. the way i went about it was to just create a variable for each polygon, but this ended up as a 1000+ lines of code (as the map has about 50 hexagontiles) so im wondering if there is a more efficient way since its hard to keep track of so many lines of code.
this is how 1 polygon looks. (im intending to place a sprite, where the player will be able to move the sprite such as in chess, moving from one tile to another by clicking the mouse etc.)
var polyA = new Konva.RegularPolygon({
x: 600,
y: 400,
sides: 6,
radius: 400,
rotation: 90,
stroke: "black",
strokeWidth: 5
});
and here is the code for loading the tiles. as you can see its very long.
board.add(polyA, polyB, polyC, polyD, polyE, polyF, polyG, polyCr, polyDr, polyEr, polyFr, polyGr, polyA1, polyB1, polyC1, polyD1, polyE1, polyF1, polyCr1, polyDr1, polyEr1, polyFr1, polyGr1, polyB2, polyC2, polyD2, polyE2, polyF2, polyG2, polyCr2, polyDr2, polyEr2, polyB3, polyC3, polyD3, polyE3, polyCr3, polyDr3, polyEr3, polyFr3, polyB4, polyC4, polyD4, polyE4, polyCr4, polyDr4, polyEr4, polyB5, polyC5, polyD5, polyCr5, polyDr5, polyEr5, polyB1u, polyC1u, polyD1u, polyE1u, polyF1u, polyCr1u, polyDr1u, polyEr1u, polyFr1u, polyGr1u, polyB2u, polyC2u, polyD2u, polyE2u, polyF2u, polyG2u, polyCr2u, polyDr2u, polyEr2u, polyB3u, polyC3u, polyD3u, polyE3u, polyCr3u, polyDr3u, polyEr3u, polyFr3u, polyB4u, polyC4u, polyD4u, polyE4u, polyCr4u, polyDr4u, polyEr4u, polyB5u, polyC5u, polyD5u, polyCr5u, polyDr5u, polyEr5u);
stage.add(board);
Related
I am trying to do an application with canvas and which have multiple objects with events binded to them like, mouse down and mouse up e.t.c.,
I am using kinetic js.
Well My doubt is if I have to draw two circles on canvas using kinetic js. I can use objects directly. But if I have to place 500 circles in the division, Its too difficult to have 500 circle objects to create manually. So, is there any other alternative to implement this one?
I use these events for every circle object I use
var circle = new Kinetic.Circle({
x: 100,
y: 100,
radius: 5,
fill: 'red',
stroke: 'black',
strokeWidth: 1
});
circle.setAttr('fact','Kinetic JS is Awesome')
circle.on('mouseover', function() {
document.body.style.cursor = 'pointer'
});
circle.on('mouseout', function() {
document.body.style.cursor = 'default'
});
circle.on('mousedown', function() {
var fill = this.getFill() == 'red' ? '#00d00f' : 'red';
this.setFill(fill);
alert(this.getAttr('fact'));// I do some stuff here
layer.draw();
});
I recommend also that you check the tutorials of KineticJS, this one is about a stress test: 1000 shapes + their respective tooltips.
http://www.html5canvastutorials.com/labs/html5-canvas-10000-shape-stress-test-with-kineticjs
PS: You just have to copy paste the code and update the KineticJS version here.
My problem started with the version 5 of KineticJS, before that it was not a problem. Native KineticJS shapes such as squares and circles can be saved to an image file using the stage.toDataURL function. But it doesn't work for non-Kinetic shapes drawn with normal canvas methods such as beginPath(); and canvas.fill(); (version 4 did this fine). The following code draws two rectangles, one red and one blue. The red is custom, the blue is a native kinetic rectangle.
<body>
<div id="container"></div>
<button id="save">
Save as image
</button>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.2.min.js"> </script>
<script>
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var box = new Kinetic.Rect({
x: 400,
y: 80,
width: 100,
height: 50,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
layer.add(box);
stage.add(layer);
var canvas = layer.getCanvas().getContext('2d');
canvas.beginPath();
canvas.setAttr('strokeStyle', 'black');
canvas.setAttr('fillStyle', '#FF2222');
canvas.setAttr('lineWidth', 8);
canvas.rect(50,80,100,50);
canvas.stroke();
canvas.fill();
document.getElementById('save').addEventListener('click', function() {
stage.toDataURL({
callback: function(dataUrl) {
window.location.href = dataUrl;
}
});
}, false);
</script>
</body>
Both shapes appear, but only the blue rectangle appears in the image generated by the toDataURL function. The way they are drawn has changed in KineticJS 5, where you set attributes for fillStyle etc. so I'm thinking that may have something to do with it, or maybe the fact that the custom shape is added after the layer is added to the stage...
You are correct, between recent versions much has changed, and this has probably broken something in your drawing function.
You should consult the official docs on each item, but basically a custom shape has slightly updated properties... first of all "StrokeStyle" is no longer a valid property. Just use 'stroke'. Same thing with FillStyle.
Also -- 'dashArray' is no longer valid, now it's just 'dash' -- so I'm sure there are more things that changed that I'm not recalling... right, such as 'lineWidth' is now 'strokeWidth'...
Also -- the way you show or don't show strokes and fills has changed... yep, pretty much most of the way you used to do it has been changed slightly. 'drawFunc' is now 'sceneFunc' also...
var ctx = layer.getContext();
var customShape01 = new Kinetic.Shape({
sceneFunc: function(ctx) {
ctx.beginPath();
ctx.moveTo(162.1, 213.8);
ctx.bezierCurveTo(162.1, 213.8, 180.7, 215.3, 193.5, 214.5);
ctx.bezierCurveTo(205.8, 213.7, 221.8, 212.3, 222.8, 221.4);
ctx.bezierCurveTo(222.9, 221.7, 222.9, 222.0, 222.9, 222.3);
ctx.bezierCurveTo(222.9, 232.4, 204.6, 232.7, 192.0, 227.1);
ctx.bezierCurveTo(179.4, 221.5, 163.1, 213.8, 162.1, 213.8);
ctx.closePath();
ctx.fillStrokeShape(this);
},
id: 'customShape01',
fill: 'rgb(255, 0, 255)',
stroke: 'black',
strokeWidth: 2,
lineJoin: 'round',
dash: [5,5],
dashEnabled: 'true',
strokeEnabled: 'true'
});
check out a full working sample (you'll have to allow popups).
http://jsfiddle.net/axVXN/1/
I need some assistance changing the opacity of a shape using KineticJS (5.0.0.).
In an mouse event, I want to change the opacity of the shape, which triggered the event. Whenever the shape is hovered, it gets visible ( opacity 1.0 ) and when it's left, it becomes invisible ( opacity 0.0 ). It works fine, whenever I redraw the whole Layer of the specified shape.
The point is, I can't redraw the whole Layer because it takes to much time ( ~300 shapes ). For that reason I changed some code, to just draw the shape.
jsFiddle:
http://jsfiddle.net/p39uH/2/ ( see lines 25 and 30 of HTML )
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var pentagon = new Kinetic.RegularPolygon({
x: stage.width()/2,
y: stage.height()/2,
sides: 5,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
opacity: 0.1
});
pentagon.on('mouseover', function() {
this.opacity(0.3);
this.draw(); // instead of layer.draw();
});
pentagon.on('mouseout', function() {
this.opacity(0.0);
this.draw(); // instead of layer.draw();
});
// add the shape to the layer
layer.add(pentagon);
// add the layer to the stage
stage.add(layer);
( Code is based on this: http://www.html5canvastutorials.com/kineticjs/html5-canvas-set-alpha-with-kineticjs/ )
Even though I set the opacity of the shape to 0.0 when left, it's still visible as you can see. Every time it is hovered, it becomes more and more visible ( I guess the shape gets redrawn ).
Is there any way to (re)draw the shape with an opacity of 0.0 WITHOUT drawing the whole stage and/or layer ?
Thanks in advance.
Yes, a quick look indicates node.draw() might be broken in 5.0.1.
Workarounds:
Drop back to version 4.4.0
Use layer.drawScene() which saves redraw time by not redrawing the hit-canvas.
I'm new to Raphael and I'm trying to do two circles move in circular orbits related to the center of the canvas.
Here I made ellipses to illustrate the case. The black point is the center of the canvas.
http://jsfiddle.net/QCSb9/
I used set() to group the circles but when trying to rotate them, they rotate using their own centers individually, I thought that grouping the circles the new geometry of the group would change, becoming the black point the center of the group.
How can I rotate these circles continuously as one object.
Here is the code I'm using:
$().ready(function(){
var paper = Raphael("canvas", 640, 480);
paper.rect(0, 0, 640, 480, 10).attr({fill: "#fff", stroke: "none"});
paper.circle(320, 240, 1).attr({"fill":"#000000","stroke-width":0});
var circles = paper.set();
circles.push(
paper.ellipse(200, 240, 30, 25),
paper.ellipse(440, 240, 30, 25)
);
circles.attr({"fill":"#e00000","stroke-width":0});
var anim = Raphael.animation({"transform":"r360"},2000);
circles.animate(anim.repeat(Infinity));
});
Solved: It was a matter of specifying the center of rotation to "r360,320,240":
var anim = Raphael.animation({"transform":"r360,320,240"},2000);
rotate() is deprecated but explains the parameters admitted:
http://raphaeljs.com/reference.html#Element.rotate
Here the example corrected on jsfiddle.net
http://jsfiddle.net/SW3sP/1/
Im a beginner to Raphael. Can anyone show me how I can do a donut/radial chart, with animation, similar to these.
http://dribbble.com/shots/670348-Segment-Graphs
Im working at it now. So far Ive got this far. I will update as I make progress. My sumbling block right now is animating a change in color for the outer ring.
window.onload = function () {
// Creates canvas 320 × 200 at 10, 50
var paper = Raphael(10, 50, 320, 200);
// Creates circle at x = 50, y = 40, with radius 10
var circle1 = paper.circle(50, 40, 40);
var circle2 = paper.circle(50, 40, 20);
circle2.attr("fill", "#fff");
circle2.attr("stroke", "#fff");
circle1.attr("fill", "#336699");
circle1.attr("stroke", "#fff");
}
Credits:
On the raphael website there is an example that uses arcs. There is another question on stackoverflow with a similar topic: drawing centered arcs in raphael js. The accepted answer there has a simplified and commented version of the most important parts of the code, plus there is a jsfiddle link showing the code in action: http://jsfiddle.net/Bzdnm/2/
So what I did: I took the code from the linked question, combined it with eve, another javascript library made by the creator of RaphaelJS and what I got was this: http://jsfiddle.net/cristighenea/aP7MK/
At a glance:
1.after the arc is created we rotate it 180 degrees and begin animating it:
theArc.rotate(180, 100, 100).animate({
arc: [100, 100, amount, 100, 40]
}, 1900, function(){
//animation finish callback goes here
});
2.using eve we bind an event to *raphael.anim.frame.**
3.each time the event is fired we update the text in the middle with the new value of the arc
If you have any questions let me know