I'm looking for a solution to freehand draw a line with a gradient in canvas like this:
I already found this, but the gradient seems to be 'locked' on the background and is not following the line.
window.addEventListener('load', ()=>{
resize(); // Resizes the canvas once the window loads
document.addEventListener('mousedown', startPainting);
document.addEventListener('mouseup', stopPainting);
document.addEventListener('mousemove', sketch);
window.addEventListener('resize', resize);
});
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
function resize(){
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
}
let coord = {x:0 , y:0};
let paint = false;
function getPosition(event){
coord.x = event.clientX - canvas.offsetLeft;
coord.y = event.clientY - canvas.offsetTop;
}
function startPainting(event){
paint = true;
getPosition(event);
}
function stopPainting(){
paint = false;
}
function sketch(event){
if (!paint) return;
ctx.beginPath();
ctx.lineWidth = 5;
ctx.lineCap = 'round';
var gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0.00, 'grey');
gradient.addColorStop(1 / 2, 'white');
gradient.addColorStop(1.00, 'grey');
ctx.strokeStyle = gradient;
ctx.moveTo(coord.x, coord.y);
getPosition(event);
ctx.lineTo(coord.x , coord.y);
ctx.stroke();
}
Can somebody help me please?
I found a way to do it:
var context = canvas.getContext("2d");
context.strokeStyle = '#000000';
context.fillStyle = '#000000';
context.beginPath();
context.moveTo(10, 10);
context.lineTo(50, 10);
context.lineWidth = 2;
context.stroke();
context.beginPath();
context.lineWidth = 15;
context.moveTo(10, 30);
context.lineTo(50, 30);
context.stroke();
context.beginPath();
context.moveTo(10, 50);
context.lineTo(50, 50);
context.lineWidth = 2;
context.stroke();
Where I reconstructed the gradient with multiple lines and a blur on those lines.
I'm programming on JavaScript and basically what I'm supposed to do is to draw a face on a canvas and those faces have certain effects.
One of the effects I'm supposed to do is to click on the nose and it will change the face to an angry face. I have created objects for all the face parts (nose, eyes, etc.) and what I'm trying to do is that I want the function "angryFace" to be called when the nose is clicked. The nose is already an object.
Been stuck for a long time on this. Would appreciate it if someone could help! Uploaded the whole code down here. Thanks guys!
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>COM1008 Assignment 2</title>
<link rel="stylesheet" href="main1.css">
</head>
<main>
<h1>COM 1008 Assignment 2</h1>
<p>By Samuel Fung Chi Lun</p>
</main>
<body>
<canvas id="canvasFrame" width="600" height="600"></canvas>
<p>
<button name="sadbutton" id="sadFace">Sad</button>
<button name="angrybutton" id="angryFace">Angry</button>
<button name="surprisedbutton" id="surprisedFace">Surprised</button>
<button name="neutralbutton" id="neutralFace">Neutral</button>
</p>
<script>
var canvas = document.getElementById('canvasFrame');
var context = canvas.getContext('2d');
//Function to obtain x and y coordinates of mouse positions - Obtained from 20/11/2017 lecture slides
function getMouseXY(e) {
var boundingRect = canvas.getBoundingClientRect();
var offsetX = boundingRect.left;
var offsetY = boundingRect.top;
var w = (boundingRect.width - canvas.width);
var h = (boundingRect.height - canvas.height);
offsetX += w;
offsetY += h;
var mx = Math.round(e.clientX - offsetX);
var my = Math.round(e.clientY - offsetY);
return { x: mx, y: my };
}
const BROWS_UP = 190;
const BROWS_DOWN = 170;
//Creating an object for left eye brow
var leftEyeB = {
draw: function (x1,brows_direction1,x2,brows_direction2) {
context.beginPath();
context.lineWidth = 18;
context.moveTo(x1, brows_direction1);
context.lineTo(x2, brows_direction2)
context.stroke();
}
};
//Creating an object for right eye brow
var rightEyeB = {
draw: function (x1,brows_direction1,x2,brows_direction2) {
context.beginPath();
context.lineWidth = 18;
context.moveTo(x1, brows_direction1);
context.lineTo(x2, brows_direction2)
context.stroke();
}
};
//Creating an object for the head
var faceShape = {
draw: function() {
context.beginPath();
context.fillStyle = "rgb(255,255,0)"
context.lineWidth = 3;
context.arc(300, 300, 200, 0, Math.PI * 2, true);
context.fill();
context.stroke();
}
}
//Creating an object for the eyes
var eyes = {
draw: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.moveTo(255, 250); //LeftEye
context.arc(220, 250, 40, 0, Math.PI * 2, true);
context.moveTo(415, 250);//Right Eye
context.arc(380, 250, 40, 0, Math.PI * 2, true);
context.fill();
context.fill();
context.stroke();
context.beginPath();
context.fillStyle = "rgb(255,255,255)";
context.moveTo(240, 250); //LeftPupil
context.arc(220, 250, 15, 0, Math.PI * 2, true);
context.moveTo(400, 250); //Right Pupil
context.arc(380, 250, 15, 0, Math.PI * 2, true);
context.fill();
context.stroke();
}
}
//Creating an object for the nose
var nose = {
draw: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.moveTo(300, 275);
context.lineTo(275, 325);
context.lineTo(325, 325);
context.fill();
context.closePath();
context.stroke();
}
}
//Creating an object for the mouth
var mouth = {
frown: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.moveTo(305, 427);//Mouth
context.arc(305, 427, 80, 0, Math.PI, true);
context.fill();
context.closePath();
context.stroke();
},
circle: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.arc(300, 400, 50, 0, Math.PI * 2, true);
context.fill();
context.stroke();
},
straight: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.rect(225, 390, 150, 20);//Mouth
context.fill();
context.stroke();
}
}
//Drawing the sad face
function sadFace() {
faceShape.draw();
eyes.draw();
nose.draw();
mouth.frown();
leftEyeB.draw(175,BROWS_DOWN,265,BROWS_DOWN);
rightEyeB.draw(335,BROWS_DOWN,425,BROWS_DOWN);
}
//Drawing the angry face
function angryFace() {
faceShape.draw();
eyes.draw();
nose.draw();
mouth.frown();
leftEyeB.draw(175,BROWS_DOWN,265,BROWS_UP);
rightEyeB.draw(335,BROWS_UP,425,BROWS_DOWN);
}
//Drawing the surprised face
function surprisedFace() {
faceShape.draw();
eyes.draw();
nose.draw();
mouth.circle();
leftEyeB.draw(175,BROWS_UP,265,BROWS_DOWN);
rightEyeB.draw(335,BROWS_DOWN,425,BROWS_UP);
}
//Drawing the neutral face
function neutralFace() {
faceShape.draw();
eyes.draw();
nose.draw();
mouth.circle();
leftEyeB.draw(175,BROWS_DOWN,265,BROWS_DOWN);
rightEyeB.draw(335,BROWS_DOWN,425,BROWS_DOWN);
}
//Not sure how to properly do the bottom part. It does not work at all for the eyebrows one so please help!
function effects() {
//Click on the eyebrows to raise them
if (mousePosition.x > x1 && mousePosition.x < x2 && mousePosition.y < BROWS_UP && mousePosition.y > BROWS_DOWN) {
BROWS_UP += 20;
}
//Click on eye to show angry face
if (mousePosition = on coordinates of the eye) {
angryFace();
}
//Click on nose to show happy face
if (mousePosition = on coordinates of the nose) {
smileFace();
}
}
canvas.addEventListener('click', function(evt) {
effects(evt);
});
neutralFace();
//Linking the face functions to the buttons
var angryButton = document.getElementById("angryFace");
var sadButton = document.getElementById("sadFace");
var surprisedButton = document.getElementById("surprisedFace");
var neutralButton = document.getElementById("neutralFace");
sadButton.addEventListener("click", sadFace);
angryButton.addEventListener("click", angryFace);
surprisedButton.addEventListener("click", surprisedFace);
neutralButton.addEventListener("click", neutralFace);
</script>
</body>
</html>
When you make face, for you, there are different objects(say nose, eyes etc). For DOM, there is only 1 object i.e. Canvas. So when you click, you are clicking on canvas and not nose.
So to achieve this, you will have to play with coordinates. You have to assume the position of every container and on click of canvas, check the coordinates. If the coordinates are within range of some object, fire necessary function.
canvas.addEventListener('click', function(event){
var x = event.clientX, y = event.clientY;
if(x> 280 && x <335 && y > 280 && y <335) {
// nose is clicked.
angryFace();
}
else {
neutralFace();
}
})
Following is a partial sample:
var canvas = document.getElementById('canvasFrame');
var context = canvas.getContext('2d');
//Function to obtain x and y coordinates of mouse positions - Obtained from 20/11/2017 lecture slides
function getMouseXY(e) {
var boundingRect = canvas.getBoundingClientRect();
var offsetX = boundingRect.left;
var offsetY = boundingRect.top;
var w = (boundingRect.width - canvas.width);
var h = (boundingRect.height - canvas.height);
offsetX += w;
offsetY += h;
var mx = Math.round(e.clientX - offsetX);
var my = Math.round(e.clientY - offsetY);
return {
x: mx,
y: my
};
}
const BROWS_UP = 190;
const BROWS_DOWN = 170;
//Creating an object for left eye brow
var leftEyeB = {
draw: function(x1, brows_direction1, x2, brows_direction2) {
context.beginPath();
context.lineWidth = 18;
context.moveTo(x1, brows_direction1);
context.lineTo(x2, brows_direction2)
context.stroke();
}
};
//Creating an object for right eye brow
var rightEyeB = {
draw: function(x1, brows_direction1, x2, brows_direction2) {
context.beginPath();
context.lineWidth = 18;
context.moveTo(x1, brows_direction1);
context.lineTo(x2, brows_direction2)
context.stroke();
}
};
//Creating an object for the head
var faceShape = {
draw: function() {
context.beginPath();
context.fillStyle = "rgb(255,255,0)"
context.lineWidth = 3;
context.arc(300, 300, 200, 0, Math.PI * 2, true);
context.fill();
context.stroke();
}
}
//Creating an object for the eyes
var eyes = {
draw: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.moveTo(255, 250); //LeftEye
context.arc(220, 250, 40, 0, Math.PI * 2, true);
context.moveTo(415, 250); //Right Eye
context.arc(380, 250, 40, 0, Math.PI * 2, true);
context.fill();
context.fill();
context.stroke();
context.beginPath();
context.fillStyle = "rgb(255,255,255)";
context.moveTo(240, 250); //LeftPupil
context.arc(220, 250, 15, 0, Math.PI * 2, true);
context.moveTo(400, 250); //Right Pupil
context.arc(380, 250, 15, 0, Math.PI * 2, true);
context.fill();
context.stroke();
}
}
//Creating an object for the nose
var nose = {
draw: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.moveTo(300, 275);
context.lineTo(275, 325);
context.lineTo(325, 325);
context.fill();
context.closePath();
context.stroke();
}
}
//Creating an object for the mouth
var mouth = {
frown: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.moveTo(305, 427); //Mouth
context.arc(305, 427, 80, 0, Math.PI, true);
context.fill();
context.closePath();
context.stroke();
},
circle: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.arc(300, 400, 50, 0, Math.PI * 2, true);
context.fill();
context.stroke();
},
straight: function() {
context.beginPath();
context.fillStyle = "rgb(0,0,0)";
context.rect(225, 390, 150, 20); //Mouth
context.fill();
context.stroke();
}
}
//Drawing the sad face
function sadFace() {
faceShape.draw();
eyes.draw();
nose.draw();
mouth.frown();
leftEyeB.draw(175, BROWS_DOWN, 265, BROWS_DOWN);
rightEyeB.draw(335, BROWS_DOWN, 425, BROWS_DOWN);
}
//Drawing the angry face
function angryFace() {
faceShape.draw();
eyes.draw();
nose.draw();
mouth.frown();
leftEyeB.draw(175, BROWS_DOWN, 265, BROWS_UP);
rightEyeB.draw(335, BROWS_UP, 425, BROWS_DOWN);
}
//Drawing the surprised face
function surprisedFace() {
faceShape.draw();
eyes.draw();
nose.draw();
mouth.circle();
leftEyeB.draw(175, BROWS_UP, 265, BROWS_DOWN);
rightEyeB.draw(335, BROWS_DOWN, 425, BROWS_UP);
}
//Drawing the neutral face
function neutralFace() {
faceShape.draw();
eyes.draw();
nose.draw();
mouth.circle();
leftEyeB.draw(175, BROWS_DOWN, 265, BROWS_DOWN);
rightEyeB.draw(335, BROWS_DOWN, 425, BROWS_DOWN);
}
function effects() {
mousePosition = getMouseXY(e);
console.log(mousePosition);
}
neutralFace();
canvas.addEventListener('click', function(event){
var x = event.clientX, y = event.clientY;
if(x> 280 && x <335 && y > 280 && y <335) {
// nose is clicked.
angryFace();
}
else {
neutralFace();
}
})
//Linking the face functions to the buttons
var angryButton = document.getElementById("angryFace");
var sadButton = document.getElementById("sadFace");
var surprisedButton = document.getElementById("surprisedFace");
var neutralButton = document.getElementById("neutralFace");
sadButton.addEventListener("click", sadFace);
angryButton.addEventListener("click", angryFace);
surprisedButton.addEventListener("click", surprisedFace);
neutralButton.addEventListener("click", neutralFace);
<!-- This is not the original markup. This is a part of an edit to make the code executable. -->
<canvas id='canvasFrame' width=600 height=600></canvas>
<div>
<button id="angryFace">Angry Face</button>
<button id="sadFace">Sad Face</button>
<button id="surprisedFace">Surprised Face</button>
<button id="neutralFace">Neutral Face</button>
</div>
I have been trying to get an image to appear on my canvas that I have drawn shapes onto but I haven't been able to get it to work. There was a similar question on here but I tried doing it that way and it didn't work for me. I don't really care where on the canvas the picture appears as long as I can actually get it to. Also when I tried to get the image on the canvas, it turned the whole canvas yellow? I'm not sure why but the pedals on my flowers are yellow and I did nothing to change that part of my code.
window.onload = function() {
drawStar(100,100,5,30,15);
TruckParts();
Flower();
colorDrop();
Test1();
};
function drawStar(cx,cy,spikes,outerRadius,innerRadius){
// Get referene to canvas object
var canvas = document.getElementById("myCanvas");
// Get reference to canvas drawing context
var context = canvas.getContext("2d");
var rot=Math.PI/2*3;
var x=cx;
var y=cy;
var step=Math.PI/spikes;
context.beginPath();
context.moveTo(cx,cy-outerRadius)
for(i=0;i<spikes;i++){
x=cx+Math.cos(rot)*outerRadius;
y=cy+Math.sin(rot)*outerRadius;
context.lineTo(x,y)
rot+=step
x=cx+Math.cos(rot)*innerRadius;
y=cy+Math.sin(rot)*innerRadius;
context.lineTo(x,y)
rot+=step
}
context.lineTo(cx,cy-outerRadius);
context.closePath();
context.lineWidth=5;
context.strokeStyle='lightblue';
context.stroke();
context.fillStyle='grey';
context.fill();
}
function TruckParts(){
// Get referene to canvas object
var canvas = document.getElementById("myCanvas");
// Get reference to canvas drawing context
var context = canvas.getContext("2d");
// Draw truck body
context.beginPath();
context.moveTo(125, 450);
context.lineTo(200, 450);
context.lineTo(250, 500);
context.lineTo(290, 500);
context.lineTo(290, 550);
context.lineTo(25, 550);
context.lineTo(25, 500);
context.lineTo(250, 500);
context.lineTo(110, 550);
context.lineTo(200, 500);
context.lineTo(125, 500);
context.closePath();
context.strokeStyle = "darkred";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "red";
context.fill();
//Draw truck tire1
context.beginPath();
context.arc(100,560,30,0,2*Math.PI);
context.strokeStyle = "white";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "black";
context.fill();
//Draw truck tire 2
context.beginPath();
context.arc(230,560,30,0,2*Math.PI);
context.strokeStyle = "white";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "black";
context.fill();
};
//Draw Flower
function Flower(){
// Get referene to canvas object
var canvas = document.getElementById("myCanvas");
// Get reference to canvas drawing context
var context = canvas.getContext("2d");
//stem
context.beginPath();
context.moveTo(449, 500);
context.lineTo(449, 590);
context.lineTo(453, 590);
context.closePath();
context.fillStyle = "green";
context.fill();
//top left pedal
context.beginPath();
context.arc(436,490,20,0,2*Math.PI);
context.strokeStyle = "pink";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "yellow";
context.fill();
//bottom right pedal
context.beginPath();
context.arc(465,512,20,0,2*Math.PI);
context.strokeStyle = "pink";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "yellow";
context.fill();
//top right pedal
context.beginPath();
context.arc(465,490,20,0,2*Math.PI);
context.strokeStyle = "pink";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "yellow";
context.fill();
//bottom left pedal
context.beginPath();
context.arc(436,512,20,0,2*Math.PI);
context.strokeStyle = "pink";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "yellow";
context.fill();
//center
context.beginPath();
context.arc(450,500,17,0,2*Math.PI);
context.strokeStyle = "yellow";
context.lineWidth = 1;
context.stroke();
context.fillStyle = "pink";
context.fill();
};
//colors array
let colors = [
{colorname: "Red", color: "red" },
{colorname: "Blue", color: "blue"},
{colorname: "Green", color: "green"},
{colorname: "Purple", color: "purple"},
{colorname: "Pink", color: "pink"},
];
function colorDrop () {
let locaRef = document.querySelector("#colorDrop");
let option1 = document.createElement("option");
option1.value = 0;
option1.text = colors[0].colorname;
let option2 = document.createElement("option");
option2.value = 1;
option2.text = colors[1].colorname;
let option3 = document.createElement("option");
option3.value = 2;
option3.text = colors[2].colorname;
let option4 = document.createElement("option");
option4.value = 3;
option4.text = colors[3].colorname;
let option5 = document.createElement("option");
option5.value = 4;
option5.text = colors[4].colorname;
locaRef.appendChild(option1);
locaRef.appendChild(option2);
locaRef.appendChild(option3);
locaRef.appendChild(option4);
locaRef.appendChild(option5);
}
function handleDropdown(){
//convert index to number
let index = document.getElementById("colorDrop").value;
let setColor = colors[index].color;
};
//similar function that does not work for me
function Test1() {
let context = document.getElementById('test1');
if (context.getContext) {
context = context.getContext('2d');
//Loading of the home test image - img1
let img1 = new Image();
//drawing of the test image - img1
img1.onload = function () {
//draw background image
context.drawImage(img1, 0, 0);
//draw a box over the top
context.fillStyle = "rgba(200, 0, 0, 0.5)";
context.fillRect(0, 0, 500, 500);
};
img1.src = "puppy.jpg";
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel= 'stylesheet' href="p3.css">
<script src="p3.js"> </script>
<style>canvas { border: 1px solid black; }</style>
</header>
<body>
<canvas width= "1000" height= "600" id= "myCanvas">
</canvas>
</body>
</html>
<header>
</header>
<nav>
</nav>
<main>
Enter text:
<input type="text">
<button type= "button">Press Button</button>
<select id="colorDrop" onchange="handleDropdown()">
<option value="">Select a Color</option>
</select>
</main>
<footer>
</footer>
</body>
</html>
The following line in the Test1 function is preventing your code from working...
let context = document.getElementById('test1');
Needs to be changed of course to...
let context = document.getElementById('myCanvas');
When I make this change your code works, the image I specify for img1.src is displayed top-left of the canvas, and a filled rectangle of 50% alpha also appears.
I am having trouble displaying pictures on my canvas, especially when using Chrome.
I have a method that is called to draw a portrait (name, img, borders), but context.drawImage() doesn't seem to be working in Chrome. Any solutions?
Portrait.prototype.draw = function (context, x, y, tX, tY) {
context.save();
context.translate( tX, tY );
context.fillStyle = 'blue';
context.strokeStyle = 'black';
context.strokeRect(x, y, 160, 200);
context.fillRect(x, y, 160, 200);
context.stroke();
// adding the image
context.beginPath();
var img = new Image();
var link = this.getImageUrl();
img.src = link;
//context.drawImage(img,x+5,y+5); //works mozzila
img.onload = function () { context.drawImage(img,x+5,y+5); }
// partial work chrome but on refresh displays e.g two different portrait images in turn in a random portrait (if multiple portraits on canvas)
// text box
context.beginPath();
context.fillStyle = '#ffffff';
context.fillRect(x+5,y + 165,150,30);
// text
context.beginPath();
context.fillStyle = 'black';
var n = this.getName();
context.font = "25px Aerial";
context.fillText(n,x+5,y+190); // should give the name
context.restore();
};
You're passing img.onload a function which will be executed asynchronously, meaning the other lines of code will proceed before it's done. Wrap the entire "draw" in your image.onload function.
Portrait.prototype.draw = function (context, x, y, tX, tY) {
var img = new Image();
var link = this.getImageUrl();
img.src = link;
img.onload = function () {
context.save();
context.translate( tX, tY );
context.fillStyle = 'blue';
context.strokeStyle = 'black';
context.strokeRect(x, y, 160, 200);
context.fillRect(x, y, 160, 200);
context.stroke();
context.drawImage(img,x+5,y+5);
//...
}
};