I have a bizarre problem with canvas and Chrome 27.0:
After large amounts of drawing on a canvas, using the arc function draws solid squares in Chrome on OS X, but works fine in Safari, Firefox on the same OS X machine, and in IE10, Chrome and Firefox on Windows it's fine all the time.
The problem is not reproducible without running the giant wad of code beforehand, so I'm assuming it has something to do with what's being done beforehand, but here is some information, perhaps someone can point me in a direction I haven't thought of yet.
This is the code that fails:
ctx.beginPath();
ctx.strokeStyle = "rgba(255, 255, 255, 0.9)";
ctx.arc(cx*sfx, cy*sfy, width*sfy, 0, Math.PI * 2, false);
ctx.closePath();
ctx.stroke();
I can get it to draw the circle in Chrome by not doing the arc over 2pi, but 1.9999pi. This code works:
ctx.beginPath();
ctx.strokeStyle = "rgba(255, 255, 255, 0.9)";
ctx.arc(cx*sfx, cy*sfy, width*sfy, 0, Math.PI * 1.999, false);
ctx.closePath();
ctx.stroke();
What also works, is to remove the beginPath() statement. Then however, a line is drawn from where the last object was drawn on the canvas to the beginning point of the circle.
I've tried reordering, removing doubling the begin/end path statements, all to no effect apart from the described.
Any clues anyone?
Cheers
Balt
Had the same issue, I've used the same hack at first, but later I added a moveTo
ctx.moveTo(x + radius, y);
ctx.arc(x, y, radius, 0, Math.PI*2, true);
/*
Chrome suddenly started drawing a filled square (2013 May 26)
can't get the filled square though in jsfiddle
first try was changing it to
ctx.arc(x, y, radius, 0, Math.PI*1.999, false)
which worked, but then added the moveTo, which also made it work again
*/
Related
I've drawn some shapes to my transparent canvas.
Lots of animated circles to be precise.
I would like to fade the bottom edge of my canvas to fully transparent, from transparent (but with the shapes).
Edit
See the image below; I'm after the effect on the right, as opposed to what I currently have which is a cut in half circle using clearRect()
Anyone have an ideas?
You can create a gradient with alpha in it (using rgba() syntax) and apply it to the stroke. Something like:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0,"#f00");
gradient.addColorStop(0.75,"rgba(255, 0, 0, 0)");
ctx.strokeStyle = gradient;
ctx.lineWidth = 10;
ctx.beginPath();
ctx.arc(150, 150, 100, 0, Math.PI * 2);
ctx.stroke();
Here's a quick demo for it: http://codepen.io/codingcampbell/pen/wMeowa
Changing the 0.75 value in addColorStop is what would affect where the alpha part of the gradient comes in. Animating it might be tricky, I think you need to create a new gradient for each stop value because you can't modify existing stops (but you can keep those gradients in memory and share them with all your shapes)
The easiest way would be to make a small vertical gradient and apply it as an eraser on the full circle. To make the effect that it's being animated, just move it upwards on every frame (and start from below the circle).
Using GPS, I will know the latitude/longitude for 4 corners of a lot of land (I suppose it could be 5 or 6 so a polygon -- although will usually be a rectangle or parallelogram). Using DIV tags (with runat=server), I can mark the dots on an ASP.NET page pulling the data points from a database.
But, is there a way I can essentially turn these into shapes? I'm trying to map out a, for example, subdivision of plats on a web page. Ultimately, I'd like data to appear on mouseover, have unsold plats a different color, click on a plat and it navigates somewhere, etc).
But right now, I'm just trying to see if I can plot the shapes on a page.
Thanks very much for any guidance.
If you can count on your users having a modern browser, html5 <canvas> is probably what you want. You can just put a canvas on your page with
<canvas id="myCanvas" width="200" height="100"></canvas>
Then draw to it in javascript like so:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle = '#f00';
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, 100);
ctx.lineTo(50, 100);
ctx.lineTo(50, 0);
ctx.closePath();
ctx.fill();
Adjust or add corners as needed.
I have a canvas where I work with an image, move, rotate and scale. Everything is working fine until I try to combine all transformations. For example I'm moving the image based on the user mouse movement difference and it's ok but if I rotate the image first to let's say 180 degrees then the image movement is inverted relative to mouse movement. How can I fix that?
ctx.clearRect(0, 0, 320, 580);
ctx.save();
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.scale(scale, scale);
ctx.rotate(toRad(angle));
ctx.translate(-(canvas.width / 2), -(canvas.height / 2));
ctx.drawImage(image, tx, ty, image.width, image.height);
ctx.restore();
Need to post a bit more code if possible, but I believe the issue has to do with your translations. Heres a similiar example, although movement is not dependent on the mouse.
Live Demo
// save the context
ctx.save();
// translate it to the objects x and y, basically your taking the canvas and moving it to each object.
ctx.translate(box.x, box.y);
// now rotate it
ctx.rotate(box.angle);
// -5 is half of the box width and height 0,0 is the boxes location, im drawing it at half the width and height to set the rotation origin to the center of the box.
ctx.fillRect(-5,-5, 10,10);
// now restore
ctx.restore();
Your tx and ty Im assuming are from the mouse coords, well since you have rotated the canvas the tx and ty are now "rotated".
I have a drawn a Circle Shape in AS3. I want to render the Circle into a Bitmap with nice/antialiased Edges. Because I want it to work on Mobile Devices (Air Apps are limited to stagequality = low) I need a workaround. Any custom shape to bitmap renderer available?
Not sure this solution would work for Air Mobile Apps, but worth looking into.
Didier Brun # ByteArray.org posted an API used to draw primitive shapes (as BitmapData, not from Vector draw calls either), which might help you get your circles to draw the way you want.
http://www.bytearray.org/?p=67
Code Snippet (from that URL):
// create the BitmapData to work on
var pixels:Raster = new Raster(320, 240, true);
// draw stuff
pixels.drawRoundRect( new Rectangle ( 20, 20, 200, 100), 18, 0xFF00FFFF );
pixels.drawRect( new Rectangle ( 70, 70, 100, 100 ), 0xFF009900 );
pixels.filledTri( 40, 40, 80, 110, 50, 30, 0xFF998811 );
pixels.aaCircle(100, 100, 40, 0x77AA88 );
pixels.circle(40, 40, 30, 0xFF000000);
pixels.line(10, 10, 60, 80, 0xFF000000 );
// show it
addChild ( new Bitmap ( pixels ) );
Hopefully the library / source code is compatible for your project! :)
Have you consider using the drawWithQuality method?
The drawWithQuality() method works exactly like the draw() method, but instead of using the Stage.quality property to determine the quality of vector rendering, you specify the quality parameter to the drawWithQuality() method.
StageQuality.LOW is going to make your bitmap quality low if you're using draw() because the source will be of low quality whether it's on the DisplayList or not.
I don't think there's a way around this.. You'll have to load in circle graphics or import images to use.
If it is only something simple as circle, you can synthesize smooth image pixel by pixel. Create BitmapData of sufficient size and loop on pixels. On every pixel, compute distance from center - if it less than circle radius - half of pixel diagonal, set pixel to circle color. If it greater than circle radius + half of pixel diagonal, call setPixel32(x, y, 0).
Pixels that won't pass both conditions are near the edge - to do exact antialiasing, you must compute how much of pixel is covered by circle. Maybe you can find some convincing simple approximation. Good luck!
Update:
OK, I think I can remember simpler approach... You can draw your circle or any shapes two times bigger than they should be, then draw that bitmap into another with scale 0.5 (set through matrix) and smoothing on. That would be supersampling 4x. If stage quality doesn't affect bitmap smoothing, it should work.
In ActionScript 3 bitmap is created from BitmapData, so you need to create if first with
_bitmapData = new BitmapData(..
BitmapData has method draw, passing DisplayObject instance (Sprite, MovieClip or other) to it as parameter, will draw it's content into BitmapData.
Example:
var c:Sprite = new Sprite();
c.graphics.clear();
c.graphics.beginFill(0x00FF00, 0.5);
c.graphics.lineStyle(2.0);
c.graphics.drawRectangle(0, 0, 100, 100);
c.graphics.endFill();
var bd:BitmapData = new BitmapData(100, 100);
bd.draw(c);
var bitmap:Bitmap = new Bitmap(bd);
If you try the following code:
g.beginFill(0xFF0000);
g.drawRect(0, 0, 50, 50);
g.drawRect(25, 25, 50, 50);
g.endFill();
You would think that it would draw 2 overlapping red squares. However, it doesn't - it draws two red squares except for the overlapping area which is now completely transparent.
Any idea how to get around this?
Post-Accepted-Answer:
Thanks Christophe Herreman! Changing the code to:
g.beginFill(0xFF0000);
g.drawRect(0, 0, 50, 50);
g.endFill();
g.beginFill(0xFF0000);
g.drawRect(25, 25, 50, 50);
g.endFill();
Worked just as intended! I'd be interested to know if this was "intended behaviour" or an actual bug though!
All calls prior to endFill() will just store the points of the polygon you want to draw and connect them once endFill() is called. Since the code in your example has an overlapping part, it will be filtered out when the actual lines of the polygon are drawn. I actually don't know if this is intended behavior of the Flash player or a bug.
To solve this, just add a new call to beginFill() before drawing the new rectangle.
g.beginFill(0xFF0000);
g.drawRect(0, 0, 50, 50);
g.beginFill(0xFF0000);
g.drawRect(25, 25, 50, 50);
g.endFill();
Wouldn't you need to create a second graphic object to apply the second fill to? I bet you really have one strangely shaped graphic object instead of two intersecting rectangles.