I have a problem with the HTML5 Canvas. I use jCanvas to add layers to an canvas but I have a problem with the sizes.
I have 2 rectangles a green one and a red one.
Now I want the red box touch the green left top corner.
Using the coordinate system I start green at coordinates 200, 200
then red has to start at 0,0 and the width and height has to be 200 and 200.
But that doesn't work
Check this example
Why doesnt this work??
When I use 100x100 dimensions it does work
All depends on the origin of your layer. By default it is the center of the layer.
So to have the results you expect there are two solutions (exemples with layer 100*100) :
First in your case you have to calculate correct position from top left canvas origin to the middle of your object :
$('canvas')
.addLayer({
type: 'rectangle',
name: 'redBox',
fillStyle: '#c33',
x: 50, y: 50,//canvas origin to center (100/2)
width: 100, height: 100
})
.addLayer({
type: 'rectangle',
name: 'greenBox',
fillStyle: '#585',
x: 150, y: 150,//canvas origin to center (100 of red layer + 100/2)
width: 100, height: 100
})
.drawLayers();
Or you can set origin to top left corner by disable fromCenter property:
$('canvas')
.addLayer({
type: 'rectangle',
name: 'redBox',
fillStyle: '#c33',
fromCenter: false,
x: 0, y: 0,
width: 100, height: 100
})
.addLayer({
type: 'rectangle',
name: 'greenBox',
fillStyle: '#585',
fromCenter: false,
x: 100, y: 100,
width: 100, height: 100
})
.drawLayers();
Hope this help
Related
I rotate a node (with a green image sprite for easy viewing) containing child nodes (called Dot, with red color, collider2D and rigidbody2D). I change the Rotation property and all Dots also change. I want to do so in code, however only the blue part rotates.
I rotated both ways:
tween(new Vec3(0, 0, 0))
.to(3, new Vec3(0, 0, 360), {
easing: "cubicIn",
onUpdate(target?: any) {
wheelDot.eulerAngles = target;
},
})
.start();
and
tween(this.wheelDot)
.to(
3,
{
angle: this.wheelDot.angle + 360,
},
{
easing: "cubicIn",
}
)
.start();
Both of the above codes just rotate the green part and the red dots stay in place.
Edit: I found out if I dropped RigidBody2D, the red dots moved. How can I still use RigidBody2D and still rotate?
I have a big issue, but I don't know how to solve it.
I have a json file, which contains elements and their positions in a grid.
All elements possible have childrens, and the childrens are re-indexed from zero (0,0).
I need to convert relative positions to 'absolute' position.
An example json file:
{
label: 'item 1',
position: {x: 0, y: 0},
childrens: [
{
label: 'item 1 children 1'
position: {x: 1, y: 0}
},
{
label: 'item 1 children 2',
position: {x: 2, y: 0}
}
]
},
{
label: 'item 2',
position: {x: 1, y: 0},
childrens: [
{
label: 'item 2 children 1',
position : {x: 0, y: 2}
}
]
}
Keep an absolute offset.
Start with offset (0,0) for the root node. Then when you reach a child compute the absolute coordinates for the top-left corner and call the recursive function with the computed coordinates as the new absolute offset.
For regular items add the absolute offset to the item coordinates to get the absolute coordinates.
In your example, you start with offset (0,0). Then you reach the child rectangle. You compute that the top-left corner should be at position (2,0) and send that as the offset into the recursive call. When you reach the first block inside the child you compute the absolute coordinates as child relative coordinates: (0,0) + absolute coordinate: (2,0) to get (2,0).
I created a Cesium label, using the following code:
var label: Cesium.LabelGraphics = new Cesium.LabelGraphics({
text : lab,
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
font: '15px Helvetica',
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL,
pixelOffset: new Cesium.Cartesian2(20, 20)
});
But it is blurred...
I would like to have a clearer label. Is this image you can see inside the red rectangle the real label. In the blue rectangle is the label with a zoom In. In the green rectangle is how I would like it to be.
Is there some way to make the label clearer?
Thanks!
In Bllboard.js or Cesium.js change
gl_Position = czm_viewportOrthographic * vec4(positionWC.xy,-positionWC.z, 1.0);
to
gl_Position = czm_viewportOrthographic * vec4(floor(positionWC.xy + 0.5), -positionWC.z, 1.0);
It will makethe billboards snap to a pixel, instead of get blurred.
also disable the FXAA (antialias) in your viewer initialization
viewer.scene.fxaa = false
it will make the billboards and labels much more crispy !
Before
.
After
A trick I sometimes use is to combine a larger font size with a scale setting on the label to scale the large font down using WebGL. This is a slightly different scaling than simply picking a smaller font size, because WebGL's texture scaling system comes into play to scale the rasterized font images. This works because Cesium labels are not anchored to an integer pixel position, they can be placed at coordinates with sub-pixel precision. So, the extra resolution in the label texture comes in handy as the label moves around. Of course this method costs a little bit more texture memory, but is usually worth it to get the cleaner edges.
Here's an example, showing the difference between normal (no scaling), double (0.5 scaling), and triple (roughly, 0.3 scaling).
var viewer = new Cesium.Viewer('cesiumContainer', {
navigationHelpButton: false, animation: false, timeline: false
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
label : {
text : 'Label == || normal',
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
font: '15px Helvetica', // NOTE: Standard size, no scaling here.
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL,
pixelOffset: new Cesium.Cartesian2(20, -10)
}
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
label : {
text : 'Label == || double',
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
font: '31px Helvetica',
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL,
pixelOffset: new Cesium.Cartesian2(20, 20),
scale: 0.5
}
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
label : {
text : 'Label == || triple',
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
font: '57px Helvetica', // NOTE: Large font size here
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL,
pixelOffset: new Cesium.Cartesian2(20, 50),
scale: 0.3 // NOTE: Large font images scaled down via WebGL texturing.
}
});
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
<link href="http://cesiumjs.org/Cesium/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/Cesium/Build/Cesium/Cesium.js"></script>
<div id="cesiumContainer"></div>
I'm trying to build a web tool to generate an image composed of a stack of shapes. Each shape element is derived from one original shape; the derivation is basically created by expanding by x pixels, then rotating it by y degrees, then placing it at the "end" of the stack. In the picture below, the original shape is a white heptagon, with slightly curved sides. The pink derivation was created by the following steps:
Copy the white heptagon and enlarge it by 10 pixels.
Rotate it by +/- 8 degrees.
Place it behind the white heptagon.
My question is what web technology will be suitable (and the simplest) to do this task? HTML5 canvas, SVG, or WebGL? I am leaning towards the canvas but it only supports one primitive shape i.e. rectangle.
For the curvy sides, I don't think there is a library that does this automatically. I might need to resort to doing it manually e.g. using arcs() in canvas.
Here's code to draw a stack of concentric rotated poly-arc shapes
This code lets you define the number of sides in your polygon as well as the inset size of your arcs.
This code just stacks the shapes from bottom-to-top, but you can always use ctx.globalCompositeOperation="destinationover" to draw behind the current shapes.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/KkteA/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
drawArcInsetPolygon(7,100,.8,200,150,2,"gray","pink",-90);
drawArcInsetPolygon(7,100,.8,200,150,2,"gray","white",45);
function drawArcInsetPolygon(sideCount,size,arcInset,centerX,centerY,strokeWidth,strokeColor,fillColor,rotationDegrees){
var radians=rotationDegrees*Math.PI/180;
ctx.save();
ctx.translate(centerX,centerY);
ctx.rotate(radians);
ctx.beginPath();
ctx.moveTo (size * Math.cos(0), size * Math.sin(0));
for (var i = 1; i <= sideCount;i += 1) {
var cpX= (size*arcInset) * Math.cos((i-.5) * 2 * Math.PI / sideCount);
var cpY=( size*arcInset) * Math.sin((i-.5) * 2 * Math.PI / sideCount);
var endX= size * Math.cos(i * 2 * Math.PI / sideCount);
var endY= size * Math.sin(i * 2 * Math.PI / sideCount);
ctx.quadraticCurveTo(cpX, cpY, endX,endY);
}
ctx.fillStyle=fillColor;
ctx.strokeStyle = strokeColor;
ctx.lineWidth = strokeWidth;
ctx.stroke();
ctx.fill();
ctx.restore();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=300></canvas>
</body>
</html>
Canvas should be very capable of allowing you to easily clone, alter and redraw elements behind your drawings :).
For something simple, as of Mar 2013, I'd recommend using Kinetic JS
Blobs would get you arched sided polygons easily like this:
new Kinetic.Blob({
x: 200,
y: 200,
scale: 2,
offset: [50, 50],
points: [{
x: 36,
y: 0
}, {
x: 81,
y: 10
}, {
x: 100,
y: 50
}, {
x: 81,
y: 90
}, {
x: 36,
y: 100
}, {
x: 0,
y: 73
}, {
x: 0,
y: 27
}],
fill: '#AAFFDD',
strokeWidth:0.2,
tension: 1.1
});
(Link for historical purposes only, It no longer works)
Check It in a fiddle~ jsfiddle.net/jaibuu/VUzKP/
I'm currently playing with Kinetic.JS. I have drawn a rather crude UFO-like shape in two parts, a hull (red) and a disc (grey).
Demo - JSBin
Question: how come when I later arrange the shape ordering so the hull is above the disc, the disc bizarrely goes from grey to the hull's red?
Uncomment the moveToTop() line at the bottom of my JSBin to see what I mean. Here's the pertinent (condensed) code.
//ship hull
var hull = new Kinetic.Shape({
drawFunc: function(ctx) {
ctx.arc(game_dims.w / 2, game_dims.h * 0.6, game_dims.h * 0.45, 0, Math.PI, true);
this.fill(ctx);
},
fill: 'red'
});
//ship disc
var disc = new Kinetic.Circle({
x: game_dims.w / 2,
y: game_dims.h * 0.6,
radius: {x: game_dims.w * 0.45, y: 30},
fill: '#888'
});
//draw
layer.add(hull);
layer.add(disc);
stage.add(layer);
//post-production
hull.moveToTop(); // <-- weirdness - changes disc colour!?
layer.draw();
I am aware I could draw the two shapes in reverse order to get the desired order, but that is not what I want with this question - I'm interested in rearrangement of order after drawing.
Thanks in advance
Your draw function of the hull needs to tell the context it's drawing a new path:
function(ctx) {
ctx.beginPath();
ctx.arc(...);
this.fill(ctx);
}
By adding the beginPath() command you are telling the context that you are not in fact adding to the previous path, but drawing a new one instead. This is also what makes this.fill() fill the previous shape with red, because in your example the context is still referring to the disc when it attempts to fill it