I'm trying to rotate a canvas element AFTER it's been appended to the DOM.
Canvas is 600x50 and this is the code at hand:
var canvas = document.getElementsByTagName('canvas')[2];
var ctx = canvas.getContext('2d');
ctx.translate(300, 25); // rotate # center
ctx.rotate(angle * Math.PI/180);
which isn't accomplishing the task. Am I missing something?
Thanks
Dug around and found this working solution;
context.scale(1,-1); //flip vertically
context.translate(0,-height); //move beneath original position
works wonders!
Related
I made a double pendulum with canvas.
Here is the result: https://jsfiddle.net/zndo9vh4/
As you guys can see a trace is drawn everytime the second part of the pendulum moves, and my way of doing that is by appending each coordinate to a "trace" array.
var trace = []
trace.push([x2,y2]);
And then I draw the trace by joining each coordinate with the last one:
for (let i = 1; i < trace.length; i++) {
c.moveTo(trace[i][0], trace[i][1])
c.lineTo(trace[i-1][0], trace[i-1][1])
}
I want to improve it. What i've tried so far is only adding coordinates that aren't already in the array, but it's not a big improvent because the lines are drawn every loop
var trace = []
if(trace.includes([x2, y2]) != true){
trace.push([x2,y2]);
}
The way I think could be a good improvement is by having 2 canvas (I don't know if its possible) and then draw each point but only in that canvas so I doesnt have to be redrawn. But I dont know how to implement that.
Thanks in advice
Your improvement idea is great. You can indeed have two canvases!
There are two ways to go about it.
Offscreen canvas
Using what's called an offscreen canvas (a canvas that is created in JavaScript but not added to the DOM), you can draw all the points onto it and then using drawImage (which can accept a canvas element) pass the canvas to the main context.
var offscreenCanvas = document.createElement('canvas');
var offscreenC = offscreenCanvas.getContext('2d');
offscreenCanvas.width = canvas.width;
offscreenCanvas.height = canvas.height;
// in animate function, draw points onto the offscreen canvas instead
// of the regular canvas as they are added
if(trace.includes([x2, y2]) != true){
trace.push([x2,y2]);
var i = trace.length-1;
if (i > 1) {
offscreenC.strokeStyle = 'white'
offscreenC.beginPath();
offscreenC.moveTo(trace[i][0], trace[i][1])
offscreenC.lineTo(trace[i-1][0], trace[i-1][1])
offscreenC.stroke();
}
}
c.drawImage(offscreenCanvas, 0, 0);
Layered Canvases
One of the downsides to the offscreen canvas approach is that you have to draw it to the main canvas every frame. You can further improve the approach by layering two canvases on top of one another, where the top one is just the pendulum and the bottom one the trace.
This way, you never have to redraw the offscreen canvas onto the main canvas, and save yourself some rendering time.
Updated jsfiddle
I'm trying to use a canvas image as background here: http://www.cphrecmedia.dk/musikdk/stage/prelisten.php
The code is as below:
window.onload=function(){
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
stackBoxBlurImage('coverbgblur', 'canvas', 19, false, 2);
}
Beside the layout stuff that needs to be fixed, I need to darken the image a little bit, so the text will always be visible, also if I use a white album-cover. Can I somehow in the code above add a line or 2 that will darken the image? I know I can use CSS3, but its seems unsmart to create an extra layer of processing instead of doing it right the first time.
I'm quite new with canvas, so every kind of help is hugely appreciated!
You can make the canvas appear darker by drawing a semi-transparent dark rectangle over the image when after you draw the image
context.fillStyle = "rgba(0, 0, 0, 0.4)";
context.fillRect(0, 0, 700, 500);
Here is an example jsFiddle
You may also be able to use context.globalAlpha or context.globalCompositeOperation = "lighter"; as described in this SO post
Hi i am building a windows store app with html5 and javascript in my app i am trying to implement an eraser tool but this is problematic because if the user moves an image or another layer to where they've previously erased, they see the white drawing where they erased.
i have been trying to do the eraser tool from different ways for example i have changed the default globalCompositeOperation to "destination-out" like this code
//Here is the error.
if (clickTool[j] == "eraser") {
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = 'rgba(255,0,0,0.5);';
ctx.strokeStyle = 'rgba(255,0,0,0.5);';
}
else {
ctx.globalCompositeOperation = "source-over";
ctx.strokeStyle = clickColor[j];
}
but unfortunately it doesn´t work for me. i have uploaded all my code to this link:
My code
Please i would like to somebody could help me.
Thanks and i'm sorry for my speech , i'm mexican.
Use multiple layers. Have one canvas for the background image and another for the drawing; that why you never erase any of the background image.
If you need to, you can have multiple layers as they don't generally impact performance.
And of course if you can combine layers, say the last drawn squiggle to the background layer, if you deem a drawing to be "permanent".
Maintain a array of mid points. Use the globalCompositeOperation as 'destination-out' first and 'source-over' later to make a transparent eraser trail .
Following is the code that you need to use with a mouse move function
var handleMouseMove = function (event) {
midPt = new createjs.Point(oldPt.x + stage.mouseX>>1, oldPt.y+stage.mouseY>>1);
if(curTool.type=="eraser"){
var tempcanvas = document.getElementById('drawcanvas');
var tempctx=tempcanvas.getContext("2d");
tempctx.beginPath();
tempctx.globalCompositeOperation = "destination-out";
tempctx.arc(midPt.x, midPt.y, 20, 0, Math.PI * 2, false);
tempctx.fill();
tempctx.closePath();
tempctx.globalCompositeOperation = "source-over";
drawingCanvas.graphics.clear();
// keep updating the array for points
arrMidPtx.push(midPt.x);
arrMidPty.push(midPt.y);
stage.addChild(drawingCanvas);
stage.update();
}
};
I use this code to make a eraser that behaves like pen and fills up transparent color instead of white
I have to draw a graph with 3 different lines. A line graph.
I tried doing this:
function draw()
{
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.lineWidth=10;
ctx.strokeStyle="teal";
ctx.moveTo(10,CompanyA[0]);
ctx.lineTo(110,CompanyA[1]);
ctx.lineTo(210,CompanyA[2]);
ctx.stroke();
ctx.strokeStyle="green";
ctx.moveTo(10,CompanyB[0]);
ctx.lineTo(110,CompanyB[1]);
ctx.lineTo(210,CompanyB[2]);
ctx.stroke();
ctx.strokeStyle="yellow";
ctx.moveTo(10,CompanyC[0]);
ctx.lineTo(110,CompanyC[1]);
ctx.lineTo(210,CompanyC[2]);
ctx.stroke();
}
But apparently, the last stroke draws for all the lines. So I get 3 yellow lines, instead of a Teal, a Green and a Yellow one.
I tried creating three different Context (ctx1, ctx2 and ctx3), but for some reason, all were drawn with the "ctx3.stroke()" call.
What would be the correct way to do this?
Add a ctx.beginPath() call before every line, and also a ctx.closePath() after every ctx.stroke()
If you don't, every time you call the stroke() method, not only the new line will be drawn but also all the previous lines will be drawn again (with the new strokeStyle), since it's the same line path that is still open.
Although there is a functional answer here, I'd just like to add this.
var ctx1 = canvas.getContext("2d");
var ctx2 = canvas.getContext("2d");
var ctx3 = canvas.getContext("2d");
They all refer to the same object. It does not create a new context, it uses the one that's already attached to the canvas element. Delta is totally right in saying that it strokes yellow over the entire path because you did not begin a new path. ctx.beginPath() will solve your troubles.
I'm looking for an elegant way to generate a thumbnail for use with the FileAPI. Currently I get a DataURL representing an image. Problem is, if the image is very large, than moving it around and rerendering it becomes CPU intensive. I can see 2 options to get around this.
Generate a thumbnail on the client
Generate a thumbnail on the server, send the thumbnail back to the client (AJAX).
With HTML5 we have a canvas element? Does anyone know how to use it to generate thumbnails from pictures? They don't have to be perfect -- sampling quality is acceptable. Is there a jQuery plugin that will do this for me? Are there any other way to speed up the clientside use of large images?
I'm using HTML5, and Firefox 3.6+: there is no need to support anything other than Firefox 3.6+, please don't provide suggestions for IE 6.0
Here’s what you can do:
function getThumbnail(original, scale) {
var canvas = document.createElement("canvas");
canvas.width = original.width * scale;
canvas.height = original.height * scale;
canvas.getContext("2d").drawImage(original, 0, 0, canvas.width, canvas.height);
return canvas
}
Now, to create thumbnails, you simply do the equivalent of this:
var image = document.getElementsByTagName("img")[0];
var thumbnail = getThumbnail(image, 1/5);
document.body.appendChild(thumbnail);
Note: Remember to make sure that the image is loaded (using onload) before trying to make a thumbnail of it.
Okay, the way I can see this working is drawing the image to the canvas at a smaller size, then exporting the canvas. Say you want a 64px thumbnail:
var thumbSize = 64;
var canvas = document.getElementById("canvas");
canvas.width = thumbSize;
canvas.height = thumbSize;
var c = canvas.getContext("2d");
var img = new Image();
img.onload = function(e) {
c.drawImage(this, 0, 0, thumbSize, thumbSize);
document.getElementById("thumb").src = canvas.toDataURL("image/png");
};
img.src = fileDataURL;
With this code, an image element with the id "thumb" is used as the thumbnail element. fileDataURL is the data URL that you got from the file API.
More information on drawing images to the canvas: http://diveintohtml5.info/canvas.html#images
And on exporting canvas data: http://msdn.microsoft.com/en-us/library/ie/ff975241(v=vs.85).aspx