Canvas Animation Kit Experiment... ...how to clear the canvas? - javascript

I can make a obj to use the canvas to draw like this:
MyObj.myDiv = new Canvas($("effectDiv"), Setting.width, Setting.height);
Then, I use this to draw a rectangle on the canvas:
var c = new Rectangle(80, 80,
{
fill: [220, 40, 90]
}
);
var move = new Timeline;
move.addKeyframe(0,
{
x: 0,
y: 0
}
);
c.addTimeline(move);
MyObj.myDiv.append(c);
But after I draw the rectangle, I want clear the canvas, but I don't know which method and how to do this... ...
O...one more thing:
it is the CAKE's web site:
Link

Clearing the canvas:
canvas.clear = true; // makes the canvas clear itself on every frame
canvas.fill = somecolor; // fills the canvas with some color on every frame
// with canvas.clear = false and low-opacity fill, fancy motion blur effect
Removing the rectangle from the canvas:
rectangle.removeSelf();
or
canvas.removeChild(rectangle);

You can try this method:
MyObj.myDiv.clearRect(0, 0, canvas.width, canvas.height);
Which effectively colours the entire canvas in the background colour.

Easiest way is:
MyObj.myDiv.width = MyObj.myDiv.width;

I found that resizing the canvas works like magic, even if you're not really changing the size:
canvas.width = canvas.width

Related

javascript canvas only drawing second image if the browser window is resized

i am using react, I have a canvas with a green square in the middle and a red rectangle drawn to the left of it. The problem is only the first rectangle is being drawn, if I resize the browser the other one gets drawn.
const Canvas = props => {
useEffect(() =>{
var player1 = { x: playerX, y: playerY, draggable: gameStatus }
var enemy1 = { x: enemy1X, y: enemy1Y, width: enemy1Width, height: enemy1Height}
const drawFun = () => {
context.clearRect(0,0, canvasWidth, canvasHeight)
context.beginPath();
context.fillStyle = '#00f4cc'
context.fillRect(player1.x, player1.y, playerWidth, playerHeight)
context.beginPath();
context.fillStyle = 'red'
context.fillRect(enemy1.x, enemy1.y, enemy1Width, enemy1Height)
requestAnimationFrame(drawFun);
}
drawFun();
The second red square gets drawn where it should be, I just need to resize the browser window to confirm it. Im not sure why resizing window helps,any help appreciated!
I would guess that the coordinates of where you are trying to draw the rectangles are out of the browser window (or the dimensions defined by the canvas). However, this if this is being solved by resizing the browser window then this is probably not the case because the canvas would always start at (0,0).
I would suggest printing out the enemy.x
console.log(enemy.x);
If the value is negative, then the rectangle is being cut off.
I'm not sure if this is the actual cause, but hope it helps

How to move ellipse filled with an image to mask similar background?

I am a super early user of coding from Italy.
I came up with an idea to promote a company logo on their website and I almost reached the goal so I am sharing this problem.
The idea is to obtain a sort of clipping mask effect when the mouse/cursor move on the image
I've made so far a code that does the work with a still ellipse.
When I set the position parameters of the ellipse as mouseX and mouseY the effect does not work if not just a bit of a glitch at the start.
How can I make it work as intended?
Here you can find the link of what I have now:
https://editor.p5js.org/francesco.ficini.designer/full/FLBuhggW-
Here the code:
let img;
let imgbg2;
let maskImage;
function preload() {
img = loadImage("NeroP.jpg");
imgbg2 = loadImage("RossoP.jpg");
}
function setup() {
createCanvas(400, 225);
img.mask(img);
}
function draw() {
background(imgbg2, 0, 0);
//Immages
image(imgbg2, 0, 0);
image(img,0,0);
// Ellipse Mask
maskImage = createGraphics(400, 225);
maskImage.ellipse(200, 100, 50, 50);
imgbg2.mask(maskImage);
image(imgbg2, 0, 0);
}
The thing about the p5.Image.mask function is that it modifies the image that is being masked. Which means that any pixels that are cleared by the mask are gone for good. So if you want to dynamically change the mask you will need to make a copy of the original and re-apply the modified mask any time it changes.
Additionally you will want to avoid creating images and graphics objects in your draw() function because this can result in excessive memory allocation. Instead create a single set of graphics/images and re-use them.
let img;
let imgbg2;
let maskImage;
let maskResult;
function preload() {
img = loadImage("https://www.paulwheeler.us/files/NeroP.jpeg");
imgbg2 = loadImage("https://www.paulwheeler.us/files/RossoP.jpeg");
}
function setup() {
createCanvas(400, 225);
// Create graphics and image buffers in setup
maskImage = createGraphics(imgbg2.width, imgbg2.height);
maskResult = createImage(imgbg2.width, imgbg2.height);
}
function mouseMoved() {
if (maskResult) {
maskImage.clear();
// Ellipse
maskImage.ellipse(mouseX, mouseY, 50, 50);
// Copy the original imgbg2 to the maskResult image
maskResult.copy(
imgbg2,
0, 0, imgbg2.width, imgbg2.height,
0, 0, imgbg2.width, imgbg2.height
);
// apply the mask to maskResult
maskResult.mask(maskImage);
}
}
function draw() {
//Immagini
image(img, 0, 0);
// draw the masked version of the image
image(maskResult, 0, 0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

Replace a color on canvas

I'm using html5 canvas to make a game. I made a spritefont system to be able to draw text from a texture. Namely
.
Now I'd like to be able to change the white part of the text to any color I want. My guess is that I'll need to render the texture to a temporary canvas change the color and get the new texture and draw that instead.
However, I don't know how I can replace a color using the canvas's functions.
And I don't even know if this is the best way to do this. What should I do?
Since your spritefont is monochrome, you can use CanvasRenderingContext2D's 'multiply' globalCompositeOperation to apply color to the white part. But multiplying by a solid rectangle of color will wipe out the transparency, so you'll need to redraw the transparent parts with 'destination-atop'.
const FONT_COLOR = '#39f';
// Load up your spritefont
const spritefont = new Image();
spritefont.src = 'https://i.stack.imgur.com/mDvum.png';
// While waiting for the image to load,
// create a canvas to do the coloring work on
const fontCanvas = document.createElement('canvas');
const fontContext = fontCanvas.getContext('2d');
// Once the spritefont is loaded,
spritefont.addEventListener('load', function () {
// Resize the canvas to match the image's dimensions
fontCanvas.width = spritefont.width;
fontCanvas.height = spritefont.height;
// Draw your image on the canvas with a black background
// Without the background, you'll get tinting at the partially-transparent edges
fontContext.fillStyle = 'black';
fontContext.fillRect(0, 0, fontCanvas.width, fontCanvas.height);
fontContext.drawImage(spritefont, 0, 0);
// Multiply by the font color
// white * color = color, black * color = black
fontContext.globalCompositeOperation = 'multiply';
fontContext.fillStyle = FONT_COLOR;
fontContext.fillRect(0, 0, fontCanvas.width, fontCanvas.height);
// Restore the transparency
fontContext.globalCompositeOperation = 'destination-atop';
fontContext.drawImage(spritefont, 0, 0);
});
// Display the canvas in the snippet
document.body.append(fontCanvas);
/* just to prove that alpha is preserved */
canvas {background:0 0/32px 32px linear-gradient(45deg,#ccc 25%,transparent 25%,transparent 75%,#ccc 75%,#ccc),16px 16px/32px 32px linear-gradient(45deg,#ccc 25%,#999 25%,#999 75%,#ccc 75%,#ccc);}
If you plan to put the color-changing functionality in a function and reuse the canvas (which you should), make sure to set the context's globalCompositeOperation back to the default, 'source-over'.
HTML5 canvases follows draw and forget strategy. If you want any change (be it font color or change of shapes or text or lines etc) in what had been drawn earlier, you need to re-draw everything.
Mostly upto to my use of canvases, the whole re-drawing process is pretty fast and works without any lag or delay.
EDIT
context.fillStyle = 'red';
context.strokeStyle = 'black';
context.font = '20pt Verdana';
context.fillText('Some text', 50, 50);
context.strokeText('Some text', 50, 50);
context.fill();
context.stroke();

Changing Pen Color on Canvas after draw

I'm trying to change the color of the contents of the canvas after it is drawn. So if you start drawing a green circle, you could then decide later to make your previously drawn circle into a red a circle.
I'm using the signaturePad plugin here:
https://github.com/szimek/signature_pad
I have some of the functionality built, but the pen color change doesn't change previously drawn elements. Here's a fiddle:
http://jsfiddle.net/Z6g5Z/
Thanks for your help! The fiddle is prob. the best way to see the issue, but the JS and markup are below.
var canvas = $("#can")[0];
var signaturePad = new SignaturePad(canvas, {
minWidth: 2,
maxWidth: 5,
penColor: "rgb(66, 133, 244)"
});
$('#clear').click(function(){
signaturePad.clear();
});
$('.global-color li').click(function(){
$('.on').removeClass('on');
var $t = $(this);
$t.addClass('on');
var selectedColor = $t.data('color');
signaturePad.penColor = hexToRgb(selectedColor);
});
<ul class="global-color">
<li class="yellow-pick" data-color="#f8c90d">yellow</li>
<li class="green-pick" data-color="#3dae49">green</li>
<li class="orange-pick" data-color="#e87425">orange</li>
<li class="blue-pick on" data-color="#009cc5">blue</li>
</ul>
<div>
<input id="clear" type="button" value="clear" />
</div>
<canvas id="can" width="200px" height="200px"></canvas>
In your color change handler, have all canvas change its (non-transparent) pixels to the new color.
For this, most simple is to use globalComposite operation mode 'source-in', and fill over the canvas with the new color :
// set all pixels of the image to this color
function setCurrentColor(canvas, color) {
var context = canvas.getContext('2d');
context.save();
context.fillStyle = color;
context.globalCompositeOperation = 'source-in';
context.fillRect(0,0,canvas.width, canvas.height);
context.restore();
}
i updated your demo :
http://jsfiddle.net/gamealchemist/Z6g5Z/3/
You can by changing composite mode and fill in the color you want on the existing content.
With a library like this you have no guarantee of the inner workings of it so it may work today and may not work tomorrow - if the author decides to change the way it behaves internally.
So with that disclaimer you can use the following code to change the color of the existing drawing - this works in general with all canvas drawings and changes non-transparent pixels to what you draw on top:
function changeColor() {
ctx.save();
ctx.globalCompositeOperation = 'source-atop';
ctx.fillStyle = selectedColor;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.restore();
}
However, since we are going to tap into the library there are at least one other limitation here. The library seem to use a second canvas on top where it registers the mouse. When pen is up it transfer that drawing to the main canvas. The drawback with this, for us, is that the pen change won't happen until we draw something new; we can't change the pen color visually just by using the above function - for that you would have to patch the library to add for example a method which did all the steps needed internally.
But we do get close by adding the following setting:
var signaturePad = new SignaturePad(canvas, {
minWidth: 2,
maxWidth: 5,
penColor: "rgb(66, 133, 244)",
onBegin: changeColor /// add callback here
});
Live demo here
Hope this helps!

How to destroy / reload the canvas in html 5?

I am working on an ebook application, I draw each page on canvas using PDF.js , the problem is , when I click on the button and turn to other page, I tried simply render on the same canvas again , but the canvas seems move to a wrong location or wrong size .
function renderPage(url) {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
//clearCanvasGrid('canvas');
PDFJS.getDocument(url).then(function (pdf) {
// Using promise to fetch the page
pdf.getPage(1).then(function(page) {
var viewport = page.getViewport(5); //scale 5
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
page.render(renderContext).then(function() {
initialZoomPage(viewport.height,viewport.width);
});
});
});
}
So, are there any necessary step I need to do before redraw the page? Also , how can I destroy it if I would like to close the page? Thanks
Update:
function clearCanvasGrid(canvasID){
canvas = document.getElementById(canvasID); //because we are looping //each location has its own canvas ID
context = canvas.getContext('2d');
//context.beginPath();
// Store the current transformation matrix
context.save();
// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);
// Restore the transform
context.restore(); //CLEARS THE SPECIFIC CANVAS COMPLETELY FOR NEW DRAWING
}
I found a function to clear the canvas but it has .save , .setTransform and .restore besides clearRect, are they necessary? thanks
One way is to clear out the canvas using context.clearRect(0,0, width, height) (Reference).
Alternatively, you can append a new canvas element (and possibly remove the old one, depending on whether you will want to display it again) each time you want a new page. Something like this should do it:
var oldcanv = document.getElementById('canvas');
document.removeChild(oldcanv)
var canv = document.createElement('canvas');
canv.id = 'canvas';
document.body.appendChild(canv);
Just note that if you plan to keep more than one, each one must have a unique id instead of just id="canvas" (perhaps based on the page number - something like canvas-1).
Answer to updated question:
The save, setTransform, and restore are only necessary if you are doing (or somehow allowing users to do) transformation. I don't know if the PDF.js library does any transformation behind the scenes, so it may be best to leave it there.
try using clearRect(), like:
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
In Lightning Aura components, a different approach is required:
The chart object, once created, is stored in an attribute.
<aura:attribute name="chartObject" type="Object"/>
<canvas id="chartId" aura:id="chartCanvas" </canvas>
let theChart = component.get("v.chartObject");
if (theChart != undefined) {
//alternative
//let chartStatus = Chart.getChart("chartId");
//if (chartStatus != undefined) {
//update data if necessary
//theChart.data.datasets[0].data[i] = etc
theChart.update();
}
else{
var ctx = component.find("chartCanvas").getElement();
var chart = new Chart(ctx, {
type: 'line',
data: myData,
options: {
tension: 0.25,
responsive: false,
maintainAspectRatio :false,
fill: true,
}
});
component.set("v.chartObject", chart);
}//endif chart exists

Categories

Resources