The program includes a rectangle with a given color based on a button clicked in the HTML passing the color into the method. There is also another text field and button to add text to this rectangle but the color of the text isn't staying independent from the rectangle color. This means the rectangle always gets set to whatever color the text is. What I am trying to do is have the color of the bag selectable and then have the text on the bag selectable whilst keeping the color of the bag the same. I thought the context.beginPath() is supposed to allow these to be seperate but it doesnt seem to be doing that. Any help on what I should be doing instead?
JavaScript File
function drawCanvas(color) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var logoText = document.getElementById("logoText").value;
//Draws the bag and sets the color
context.beginPath()
context.fillStyle = color;
context.fillRect(10,30,200,200);
//Draws the border outline of the bag
context.beginPath();
context.lineWidth = "2";
context.rect(10,30,200,200);
context.stroke()
//Draws the handle
context.beginPath();
context.lineWidth = "2";
context.rect(85,5,50,25);
context.stroke();
context.save();
context.restore();
context.beginPath();
context.font = "24px Times";
context.fillStyle = "black";
context.textAlign = "center";
context.fillText(logoText, canvas.width/2, canvas.width/2);
}
window.onload = drawCanvas;
HTML File
<!DOCTYPE html>
<html lang = "en">
<head>
<title>mas00266 - Plastic Bag Inc. - Order Page</title>
<link rel = "stylesheet" href = "stylesheet.css" />
<script type = "text/javascript" src = "script.js"></script>
<meta charset = "UTF-8">
</head>
<body>
<div class = "flex-container">
<div class = "box">
<h1 id = "left"> The Bag Company </h1>
</div>
<div class = "box">
<h3 style = "text-align: right; padding: 15px"> Welcome to our orders page! </h3>
</div>
</div>
<nav>
<ul class = "navStyle">
<li>Home</li>
<li class = "active">Order</li>
<li>Contact</li>
<li>Login</li>
</ul>
</nav>
<br>
<br>
<canvas id = "myCanvas" width = "220" height = "240"></canvas>
<br>
<br>
<h4>Choose your bag color:</h4>
<button type = "button" onclick = "drawCanvas('black')">Black</button>
<button type = "button" onclick = "drawCanvas('white')">White</button>
<button type = "button" onclick = "drawCanvas('red')">Red</button>
<button type = "button" onclick = "drawCanvas('blue')">Blue</button>
<button type = "button" onclick = "drawCanvas('green')">Green</button>
<br>
<h4>Enter text on the bag:</h4>
<input id = "logoText" type = "text" name = "textInputField" size = "12">
<button type = "button" onclick = "drawCanvas()">Add Text</button>
</body>
</html>
MDN has this to say on .beginPath(), .save(), and .restore():
The CanvasRenderingContext2D.beginPath() method of the Canvas 2D API starts a new path by emptying the list of sub-paths. Call this method when you want to create a new path.
The CanvasRenderingContext2D.save() method of the Canvas 2D API saves the entire state of the canvas by pushing the current state onto a stack.
The CanvasRenderingContext2D.restore() method of the Canvas 2D API restores the most recently saved canvas state by popping the top entry in the drawing state stack. If there is no saved state, this method does nothing.
As you can see, .beginPath() doesn't have anything to do with drawing context other than setting up for a new path. Instead, you would use .save() to create a kind of save point for the current context (which includes all the current drawing parameters such colors, patterns, and transforms), make and use your changes to that context, then use .restore() to recover from those changes by reverting to the previous save point.
Based on that, and your goal, your code should look something like:
function drawCanvas(color) {
// onload doesn't call this with an argument so make sure we have a default
color = color || "blue";
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var logoText = document.getElementById("logoText").value;
//Set various base styles in our drawing context
context.fillStyle = "black";
context.font = "24px Times";
context.textAlign = "center";
context.lineWidth = "2";
//Draws the bag and sets the color
context.save(); // save current drawing context state to the stack
context.fillStyle = color;
context.fillRect(10,30,200,200);
content.restore(); // recover to previous saved state and remove it from the stack
//Draws the border outline of the bag
context.rect(10,30,200,200);
context.stroke()
//Draws the handle
context.rect(85,5,50,25);
context.stroke();
context.fillText(logoText, canvas.width/2, canvas.width/2);
}
window.onload = drawCanvas;
Related
Suppose I have an image and a div whose position is absolute and is above that image (z-index of div more than z-index of image).Something like this :
I want to take screenshot of what is visible through the div using JavaScript. At first I thought of changing the div to a canvas and then I wrote this code:
<div class="utility-btn">
<button class="enquiry-btn" onclick="openEnquiry()">?</button>
</div>
<div id="enquiry">
<button id="close" onclick="closeEnquiry()">X</button>
<div class="cover">
<canvas id="capture"></canvas>
<button class="btn" onclick="takeScreenshot()">
Click to enquiry
</button>
</div>
</div>
Function to take screenshot:
function takeScreenshot() {
var canvas = document.getElementById('capture');
ctx = canvas.getContext('2d');
var backCanvas = document.createElement('canvas');
backCanvas.width = canvas.width;
backCanvas.height = canvas.height;
var backCtx = backCanvas.getContext('2d');
backCtx.drawImage(canvas, 0, 0);
ctx.drawImage(backCanvas, 0, 0);
var dataURL = backCanvas.toDataURL();
console.log(dataURL);
}
But the image of dataURL was not what I expected it was just a blank image:
How can I implement this feature. How can I do it without using any external library?
There are two problems:
#1
If we look at your bit of code responsible for actually taking the screenshot
function takeScreenshot() {
var canvas = document.getElementById('capture');
ctx = canvas.getContext('2d');
var backCanvas = document.createElement('canvas');
backCanvas.width = canvas.width;
backCanvas.height = canvas.height;
var backCtx = backCanvas.getContext('2d');
backCtx.drawImage(canvas, 0, 0);
ctx.drawImage(backCanvas, 0, 0);
var dataURL = backCanvas.toDataURL();
console.log(dataURL);
}
we can see that canvas is the element you want to have the screenshot taken onto. Later on you're creating an empty new canvas backCanvas and make it the size of the first canvas. Afterwards you're drawing the empty first canvas on the second and finally the empty second canvas back to the first.
So that does not make too much sense.
Instead you need to take the actual canvas generated by threeJS. These lines of your code append a <canvas> element to the container <div>, threeJS is using:
const container = document.getElementById('container');
container.appendChild(renderer.domElement);
We can reference it using:
document.getElementById("container").children[0]
#2
As threeJS uses WebGL to draw stuff, it's rendering context is not the regular and for performance reasons the browser is clearing the drawing buffer after something has been drawn onto - so your screenshot would come up empty all the time. There is an option you need to pass to the THREE.WebGLRenderer constructor to keep the drawingbuffer called preserveDrawingBuffer.
So change this line:
renderer = new THREE.WebGLRenderer();
to this
renderer = new THREE.WebGLRenderer({preserveDrawingBuffer: true});
and your screenshot function to this:
function takeScreenshot() {
var canvas = document.getElementById('capture');
ctx = canvas.getContext('2d');
ctx.drawImage(document.getElementById("container").children[0], 0, 0);
var dataURL = canvas.toDataURL();
console.log(dataURL);
}
Would like to ask if there's a way for transferring <canvas> contents to another <div>. So that after putting the signature, it will be previewed on the inside of the <div> it was transferred to.
I've used this library https://github.com/szimek/signature_pad on our previous project and the signature looks real, like it was written by a pen.
This library can save the signature to a file, so what I did on our previous project is once I submit the form, the signature will be saved and it will be previewed by attaching the source file to an <img> element.
What I would like to do is I have a <button> that will show a modal that contains a signature pad and once the modal is closed, the signature will be transferred to another <div> wherein its size will shrink depending on the div's size without having to save the signature on a file.
Thanks.
Take a look at HTMLCanvasElement.toDataURL. This will give you an image of the canvas as a Data URI, which you can then add to your page as an image.
Here's a simple example:
let canvas = document.querySelector('canvas'),
ctx = canvas.getContext('2d');
// Draw something
ctx.fillStyle = "lightgray";
ctx.fillRect(0, 0, 200, 100);
ctx.fillStyle = 'orange';
ctx.fillRect(20, 20, 160, 60);
ctx.fillStyle = 'black';
ctx.font = "50px monospace";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("image", 100, 50);
// Make the image and put it in the output
let uri = canvas.toDataURL('image/png'),
outdiv = document.querySelector('#out'),
outimg = new Image();
outimg.src = uri;
outdiv.appendChild(outimg);
<div style="display: inline-block;">
<h6>Canvas with border</h6>
<canvas width="200" height="100"
style="border: 1px solid black;">
</canvas>
</div>
<div style="display: inline-block;">
<h6>Output image in a <code>div</code></h6>
<div id="out"></div>
</div>
I am building this drawing app with HTML5 and Javascript.
I've made it possible to be able to draw on the canvas, however when it comes to being able to select the different colors that I have and use it as a way to draw on the canvas, I feel stuck.
Here's my current JS:
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var radius = 10;
var dragging = false;
context.lineWidth = radius * 2;
var putPoint = function(e){
if(dragging){
context.lineTo(e.offsetX, e.offsetY);
context.stroke();
context.beginPath();
context.arc(e.offsetX, e.offsetY, radius, 0, Math.PI*2);
context.fill();
context.beginPath();
context.moveTo(e.offsetX, e.offsetY);
}
}
var engage = function(e){
dragging = true;
putPoint(e);
}
var disengage = function(){
dragging = false;
}
canvas.addEventListener('mousedown', engage);
canvas.addEventListener('mousemove', putPoint);
canvas.addEventListener('mouseup', disengage);
/////////////////////
Here's the link to the codepen to get a clear idea of where I am at :
https://codepen.io/teenicarus/pen/oGVwdB
How do I make it possible to click on the different divs so I can use their color ?
I appreciate all answers.
The first thing you need to do is create a color variable at the top of your code to hold the value of the current color the user is using:
var color = "black"; // Initial, default color
Now you need to get all your html color elements and apply the click eventListener to each of your DOM (html element) objects.
To get all the color elements you can do this:
var colors = document.getElementsByClassName("color");
Then you can loop through each of your color elements and add the click event listener to it by doing this:
for (var i = 0; i < colors.length; i++) {
colors[i].addEventListener('click', changeColor, false); // Adds the click event listener to each color element
}
The above code says that once a color element is clicked, it will call the changeColor function. Thus, we can write a function that gets the color of the element we clicked and to change the value of color to the color we clicked on (the color defined by the elements data-color attribute
var changeColor = function(e) {
color = this.getAttribute("data-color"); // Change the color to what is defined in "data-color"
}
Now, everytime you click on your color html elements, the changeColor function will be called, and thus change the value of color to the value you have defined in data-color for that particular element.
Now all you need to do is apply the color to your draw method (in your putPoint function) so it shows on the canvas. You can do this by using:
context.strokeStyle = color;
context.fillStyle = color;
This will change the stroke color and the inside/fill color.
A working example can be found here: https://codepen.io/clapynick/pen/pWYrPj?editors=1010
You might want to use a color input. This solution gives you ALL the colors.
Add this input element to your HTML file:
<input type="color" class="color" />
The user will now be able to pick a color.
Next, target the input element or its class to get the value (the user's selection). You can use a function:
function getColor() {
return document.querySelector(".color").value;
}
Finally, set strokeStyle to call getColor():
context.strokeStyle = getColor();
Alternatively, store the input value in a variable (name it color or userColor) and set strokeStyle to that variable.
I hope this helps.
Visit my CodePen to see this in action.
currently i have an image converted to greyscale, it does this on the click of a button. I need to be able to remove this function either by using the same button or another button. I thought this would be possible by using an if statement although im not sure how to do this.
<html>
<body>
<script>
function greyscale(){
//get canvas
var canvas = document.getElementById("canvas");
//get the context property
var ctx = canvas.getContext('2d');
//get image
var image = document.getElementById("imgSrc");
//draw image to canvas
ctx.drawImage(image,0,0);
//get the image data
var imageData = ctx.getImageData(0,0,130,130);
//get the pixel data
var px = imageData.data;
//get entire length of pixel data
var length = px.length;
//loop and manipulate the pixels
for(var i=0;i<length;i+=4){
var redPx = px[i];
var greenPx = px[i+1];
var bluePx = px[i+2];
var alphaPx = px[i+3];
//create greyscale sub pixel
var greyscale = redPx*.3 + greenPx * .59 + bluePx * .11;
//store each subpixel as that greyscale subpixel
px[i] = greyscale;
px[i+1] = greyscale;
px[i+2] = greyscale;
}
//put the manipulated image data back into the canvas
ctx.putImageData(imageData,0,0);
}
</script><img src="flower.jpg" id="imgSrc"/>
<canvas id="canvas" width="130" height="130"></canvas>
<br>
</script>
<input id="btngreyscale" type="button" value="Greyscale" onclick="greyscale();" />
<input id="btngreyscaleoff" type="button" value="Greyscale Off" onclick="loadImage();" />
<br>
<input type="radio" name="zing" id="on" checked/>on
<input type="radio" name="zing" id="off"/>off
<script type="text/javascript">
if (document.getElementById('btngreyscale').checked) {
alert('on');
} else {
(document.getElementById('btngreyscaleoff').checked)
alert('off');
}
</script>
</body>
</html>
As Roman hocke already said, you are not able to use the greyscale to turn it back to a colorful image, since you threw some information away. To go back to a colorful image you just have to redraw the first image.
so in your code this would be:
(document.getElementById('btngreyscaleoff').checked)
alert('off');
ctx.drawImage(image,0,0);
}
This can be done that easily because you have already saved the image object in the DOM.
I have a HTML5 canvas with a several line segments on it. I want to add a jQuery color picker so I can let users change the stroke color of those segments. How do I get the value from the colorpicker to apply to a specific line segment?
edit...okay i have gotten it this far lol, but I can't figure out how to get the line to pick up the new myPicker
<script type="text/javascript" src="jscolor.js"></script>
<script type="text/javascript">
var myPicker = new jscolor.color(document.getElementById('myField1'), {})
</script>
<script type="application/javascript" language="javascript">
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var myStroke = "#ff0000";
context.moveTo(100, 150);
context.lineTo(450, 150);
context.lineWidth = 10;
context.strokeStyle = myStroke;
context.stroke();
};
</script>
Haven't tested it, but this should work:
$('#yourColorpickerField').ColorPicker({
onChange: function(hsb, hex, rgb, el) {
var newColor = $(el).val(hex);
var context = canvas.getContext('yourCanvasName');
context.fillStyle = newColor;
// here, you can draw your line again, or if you're already doing it on an interval, it should be fine for the next time you call it
}
});
That assumes your lines are all the same color. I see that you want this to apply to only a "specific line segment," in which case you'll need to modify the above code. It'll depend heavily upon what your existing code looks like, but basically, instead of setting context.fillStyle to the new color, you'll want to store the new color value in another variable that you can read later when it comes time to draw that particular line segment (at which point you'll set context.filleStyle to the color immediately before drawing the line).