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.
Related
const canvas = document.getElementById("canvas");
canvas.width = window.innerWidth = 750;
canvas.height = 600;
var context = canvas.getContext("2d");
context.fillStyle = "white";
context.fillReact(0, 0, canvas.width, canvas.height);
let draw_color = "black";
let draw_width = "2";
let is_drawing = false;
canvas.addEventListener("touchstart", start, false);
canvas.addEventListener("touchmove", draw, false);
canvas.addEventListener("mousedown", start, false);
canvas.addEventListener("mousemove", draw, false);
function start(event) {
is_drawing = true;
context.beginPath();
context.moveTo(event.clientX = canvas.offsetLeft, event.clientY = canvas.offsetTop);
event.preventDefault();
}
function draw(event) {
if (is_drawing) {
context.beginPath();
context.moveTo(event.clientX = canvas.offsetLeft, event.clientY = canvas.offsetTop);
context.strokeStyle = draw_color;
context.lineWidth = draw_width;
context.lineCap = "round";
context.lineJoin = "round";
context.stroke();
}
}
I did everything right yet it is showing context.fillReact is not a function, it should have draw a line on moving the cursor but it is not doing anything just showing the error.
As far as I know, canvas element's context object does not have any fillReact method in it. Maybe you mean fillRect?
I have tried a few solutions on SO but they didn't work for my setup. For some reason the mouse position is off on my canvas. I have pasted my HTML and JS below for reference.
The mouse works fine when the canvas size matches the window size, but I need it to work well when it is smaller or bigger too. How can I do this?
HTML
<canvas id="canvas"></canvas>
JS
window.addEventListener('load', () => {
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
// canvas.height = window.innerHeight;
// canvas.width = window.innerWidth;
canvas.height = 540;
canvas.width = 960;
// canvas.height = canvas.offsetHeight;
// canvas.width = canvas.offsetWidth;
let painting = false;
var gradient = ctx.createLinearGradient(0, 0, 170, 0);
gradient.addColorStop("0", "magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
function windowSize() {
// canvas.height = window.innerHeight;
// canvas.width = window.innerWidth;
// canvas.height = 540;
// canvas.width = 960;
// canvas.height = canvas.offsetHeight;
// canvas.width = canvas.offsetWidth;
}
function startPosition(e) {
painting = true;
draw(e);
}
function finishedPosition() {
painting = false;
ctx.beginPath();
}
function draw(e) {
if(!painting) return;
ctx.lineWidth = lineSize;
ctx.lineCap = "round";
ctx.strokeStyle = color;
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX, e.clientY);
}
var lineSize = 5;
var color = "Black";
// Event Listeners
canvas.addEventListener('mousedown', startPosition);
canvas.addEventListener('mouseup', finishedPosition);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('touchstart', startPosition);
canvas.addEventListener('touchend', finishedPosition);
canvas.addEventListener('touchmove', draw);
// window.addEventListener('resize', windowSize);
});
The accepted solution here solved my problem. I hope this helps someone else in the future, as it did not appear high in search results.
Real mouse position in canvas
When I load the page, the canvas loads and fills the background as white. But, when I click and drag in the canvas, it wont draw for me.
window.addEventListener("load", () => {
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
canvas.height = 200;
canvas.width = window.innerWidth;
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
let painting = false;
function startPosition(e) {
painting = true;
draw(e);
}
function endPosition() {
painting = false;
ctx.beginPath();
}
function draw(e) {
if (!painting) return;
ctx.lineWidth = 7;
ctx.lineCap = "round";
ctx.strokeStyle = "black";
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX, e.clientY);
}
//Event Listeners
canvas.addEventListener("mousedown", startPosition);
canvas.addEventListener("mouseup", endPosition);
canvas.addEventListener("mousemove", draw);
})
<canvas id='canvas'></canvas>
I want to draw one circle and a character with shadow on a canvas in a HTML page while loading the page and recreate the image on a button click. I am using this code:
window.onload = function() {
draw();
};
function draw(){
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, c.width, c.height);
var width = c.width;
var height = c.height;
//DRAW A CIRCLE
var centerX = Math.floor((Math.random() * width));
var centerY = Math.floor((Math.random() * height));
var radius = Math.floor(Math.random() * 50);
var color = '#f11';
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
//DRAW A CHARACTER WITH SHADOW
var c = "S";
ctx.font = "300% Verdana";
ctx.shadowBlur = 20;
ctx.shadowColor = "black";
ctx.shadowOffsetX = 20;
ctx.shadowOffsetY = 20;
ctx.fillStyle = "#111";
ctx.fillText(c, 10, 90);
}
In HTML I am calling draw function onclick() event of a button named Refresh.
For the first time it is giving desired output by drawing one circle and a character with shadow. As I click on the Refresh button it is drawing both the objects with shadow. I dont want to draw shadow of the circle. Can anyone please tell me the mistake I'm doing here.
You may want to use the CanvasRenderingContext2D.save() method :
window.onload = function() {
draw();
};
document.getElementById("canvas").addEventListener('click', draw);
function draw(){
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, c.width, c.height);
var width = c.width;
var height = c.height;
//DRAW A CIRCLE
var centerX = Math.floor((Math.random() * width));
var centerY = Math.floor((Math.random() * height));
var radius = Math.floor(Math.random() * 50);
var color = '#f11';
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
//DRAW A CHARACTER WITH SHADOW
//save the actual context
ctx.save();
var c = "S";
ctx.font = "300% Verdana";
ctx.shadowBlur = 20;
ctx.shadowColor = "black";
ctx.shadowOffsetX = 20;
ctx.shadowOffsetY = 20;
ctx.fillStyle = "#111";
ctx.fillText(c, 10, 90);
//restore it
ctx.restore();
}
canvas{border:1px solid;}
<canvas id="canvas" width="400" height="200"></canvas>
What my task is, is to draw a house then use a loop (at the bottom) to fill the canvas with the houses instead of manually placing each one.
Well I'm trying to work how to make every other house's door green. I've been trying to hack away at code for awhile now but I cannot figure it out.
I know all my house pieces should be in functions and what not but that is a later task for the work I am doing! Here's my code:
//Check to see if the browser supports
//the addEventListener function
if(window.addEventListener)
{
window.addEventListener
(
'load', //this is the load event
onLoad, //this is the evemnt handler we going to write
false //useCapture boolen value
);
}
//the window load event handler
function onLoad()
{
var canvas;
var context;
//this function will intialise our variables
function initialise()
{
// Fune the canvas element using its id attribute.
canvas = document.getElementById('canvas');
//if it couldn't be found
if (!canvas)
{
//make a message bok appear with an error message
alert('Error: i cannot find this "canvas" of which you speak. Please re-evaluate your life choices.');
return;
}
//check if there is any getContext function
if(!canvas.getContext)
{
alert('Error no cavnas.getContext could be found');
return;
}
//get the 2D canvas context.
context = canvas.getContext('2d');
if(!context)
{
alert('Error failed to getCOntext');
return;
}
canvas.addEventListener("mousedown", getPosition, false);
}
// this is a little help tool for me as i'm awful at working out co-ordinates
function getPosition(e)
{
var x = e.x;
var y = e.y;
x -=canvas.offsetLeft;
y -=canvas.offsetTop;
alert("x:" +x+ "y:"+y);
}
//this function will draw on the canvas for me!
function draw()
{
context.fillStyle = 'grey';
context.fillRect(0, 0, canvas.width, canvas.height);
}
// pX and pY are the parameters are going to be used so that the inside of the house body becomes the drawing canvas.
function drawHouse(pX ,pY)
{
//body
context.beginPath();
context.fillStyle = '#ffffff';
context.strokeStyle = "black";
context.lineWidth = "5";
context.rect(pX,pY, 160,110);
context.closePath();
context.fill();
context.stroke();
//roof
context.beginPath();
context.fillStyle = "red";
context.moveTo(pX,pY-1);;
context.lineTo(pX+80, pY-95);
context.lineTo(pX+160, pY-1);
context.closePath();
context.fill();
context.stroke();
//door
context.beginPath();
context.fillStyle = "green";
context.fillSStyle = "red";
context.strokeStyle = "black";
context.rect(pX+55,pY+30, 50, 80);
context.fill();
context.stroke();
//handle
var radius = 5;
context.beginPath();
context.arc(pX+93, pY+75, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'purple';
context.fill();
context.lineWidth = 3;
context.strokeStyle = 'black';
context.stroke();
//window Left
context.beginPath();
context.fillStyle = 'blue';
context.strokeStyle = "black";
context.rect(pX+12,pY+30, 30, 60);
context.fill();
context.stroke();
//window Filler left vertically
context.beginPath();
context.moveTo(pX+26.5,pY+30);
context.lineTo(pX+26.5, pY+90);
context.fill();
context.stroke();
//Window filler left horizontally
context.beginPath();
context.moveTo(pX+41, pY+60);
context.lineTo(pX+11,pY+60);
context.fill();
context.stroke();
//Window Right
context.beginPath();
context.fillStyle = 'blue';
context.strokeStyle = "black";
context.rect(pX+117,pY+30, 30, 60);
context.fill();
context.stroke();
//window filler right vertically
context.beginPath();
context.moveTo(pX+131.5,pY+30);
context.lineTo(pX+131.5, pY+90);
context.fill();
context.stroke();
//window Filler right horizontally
context.beginPath();
context.moveTo(pX+147, pY+60);
context.lineTo(pX+117,pY+60);
context.fill();
context.stroke();
}
initialise();
draw();
for(var i=0; i < 5; i++)
{
var pX=0+160*i;
for(var b=0; b < 5; b++)
{
var pY=100+210*b;
drawHouse(pX,pY);
}
}
}
Add a parameter to drawHouse:
function drawHouse(pX, pY, drawGreen) {
// ...
if (drawGreen)
context.fillStyle = "green";
else
context.fillSStyle = "red";
// ...
}
And then, pass it accordingly. For example:
// before your loop
var paintGreen = false;
// In the inner for
var pY=100+210*b;
drawHouse(pX,pY,paintGreen);
paintGreen = !paintGreen; // alternate