I am making a Drawing/Canvas App on a webpage. I wanted to change the colours via buttons but the variables are not updating the colour. I debugged the code and noticed that it does update but the colour itself has not changed when drawing on the canvas.
HTML:
<div id="sketch">
<canvas id="paint"></canvas>
</div>
<button onClick="changecolour('blue')">Blue</button>
<button onClick="test()">DEBUG</button>
JavaScript:
var canvas = document.querySelector('#paint');
var ctx = canvas.getContext('2d');
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var mouse = {x: 0, y: 0};
canvas.addEventListener('mousemove', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
var colour = "black";
function changecolour(choice){
colour = choice;
}
function test(click){
alert("You choose " + colour);
}
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = colour;
canvas.addEventListener('mousedown', function(e) {
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
You need to change the variable strokeStyle again.
function changecolour(choice){
colour = choice;
ctx.strokeStyle = colour;
}
You should affect the ctx.strokeStyle itself. When you first set his value, colour = 'black', which means you set it to black. It then stays black even tho you change the "colour" value. So in that case, you just have to do this:
function changecolour(choice){
ctx.strokeStyle = choice;
}
Hope that helps
Related
i have some canvases in my code. All of these are like a blackboard, this canvases let me draw on an image, but when i try to draw in a device nothing happens. This is all of my code:
let configureCanvas = canvas => {
let ctx = canvas.getContext("2d");
let painting = canvas.parentNode;
let paintStyle = getComputedStyle(painting);
if(canvas == document.getElementById("pizarra-musculos")) {
var x = window.matchMedia("(max-width: 700px)")
myFunction(x) // Call listener function at run time
x.addListener(myFunction) // Attach listener function on state changes
function myFunction(x) {
if (x.matches) { // If media query matches
canvas.width = "350";
canvas.height = "350";
} else {
canvas.width = "500";
canvas.height = "500";
}
}
}else{
canvas.width = "350";
canvas.height = "350";
}
let mouse = {
x: 0,
y: 0
};
canvas.ontouchstart = function(e){
var touches = e.touches || [];
var touch = touches[0] || {};
}
canvas.addEventListener('mousemove', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop
}, false);
if(canvas == document.getElementById("pizarra-musculos")) {
//Rojo Claro
ctx.lineWidth = 12;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'rgba(255, 8, 53, 0.02)';
document.getElementById("btnRojoClaro").addEventListener("click", ()=>{
//Rojo Claro
ctx.lineWidth = 12;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'rgba(255, 8, 53, 0.02)';
});
document.getElementById("btnVerde").addEventListener("click", ()=>{
//Rojo Claro
ctx.lineWidth = 4;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = '#249120';
});
document.getElementById("btnRojo").addEventListener("click", ()=>{
//Rojo Claro
ctx.lineWidth = 4;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = '#ff0000';
});
document.getElementById("btnNegro").addEventListener("click", ()=>{
//Negro
ctx.lineWidth = 4;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = '#000000';
});
document.getElementById("btnAzul").addEventListener("click", ()=>{
//Azul
ctx.lineWidth = 4;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = '#1e5085';
});
}else{
ctx.lineWidth = 3;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = '#e34f54';
};
canvas.addEventListener('mousedown', function(e) {
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false)
}, false);
var onPaint = function() {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
canvas.nextElementSibling.addEventListener('click', function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
}
PD: i learned about the touchscreens on mozila developers but i can't do functionally this canvas on device... Thanks for learning my question.
In javascript, you can add listenner! That means that something will be listenned and a code will be executed when the listenner will be activated !
For instance, if you declare in html <button id="mybutton"></button> in js, you can retrieve this button with document.getElementById("mybutton"), thus, you can manipulate the element itself, value, return, action, etc...,
Let's store this element var button = document.getElementById("mybutton")
now console.log(button) will sort of display this element, cool right ?
On this button you can add listenner, onClick for example that will execute a function when the button is clicked
button.addEvenListenner("onClick", my_function)
So now when you will click on your button you will execute my_function (you need to create my_function of course)
But in your case your want to get the eventListenner of a mouse mouve or when someone use finger on their phone!
You already made it, with 'mousemove' for example ! or 'mouseup' etc...
The thing desktop is a phone and vice versa!
You don't have a mouse on your phone you have your finger, so need to have a listenner when someone touch de screen!
That's where 'touchstart' event listenner is here for, when you touch the screen, you can call a function to do whatever you want with this !
Those four listenner will be enough for your project, why you may ask ?
'touchstart' tells when you touch the screen
'touchend' tells when you remove your finger from the screen
'touchmove' tells when you drag your finger on the screen (touchstart and touchmove are not the same thing !)
'touchcancel' tells when you cancel (Honestly I don't know, you don't need it I guess)
now you need to add your listenner to your canvas
var canvas = document.getElementById("pizarra-musculos")
then you add your listenner
canvas.addEventListener("touchstart", handleStart);
canvas.addEventListener("touchend", handleEnd);
canvas.addEventListener("touchmove", handleMove);
Now when one of those 3 listenner will be used, the function next to them will be called !
Thus, you can execute whatever you want in those function
function handleMove(e) {
// Cache the client X/Y coordinates
var clientX = e.touches[0].clientX;
var clientY = e.touches[0].clientY;
}
With this bit of code you are able to keep track of the x and y of your finger of your screen, try every listenner to know when they are called etc.. put some console.log to print out value, you will do it it's not hard hope it helped you
I am using this simple script to enable users to enter their signatures. Unfortunately, this does not work on mobile devices.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var container = document.getElementById('container');
var container_style = getComputedStyle(container);
canvas.width = 400;
canvas.height = 300;
var mouse = {x: 0, y: 0};
canvas.addEventListener('mousemove', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = "black";
function getSize(size){ctx.lineWidth = size;}
canvas.addEventListener('mousedown', function(e) {
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
#canvas {
border: 1px solid rgba(0,0,0,.5);
}
<div id="container">
<canvas id="canvas"></canvas>
</div>
Is there an easy way to add touch support to this script?
Make these changes to your code:
Use pointer events (instead of mouse events): pointerdown, pointerup, and pointermove. Pointer events work for both mouse and touch interactions.
Add touch-action: none to your canvas CSS. This prevents the dragging of your finger from triggering the device's panning action (which stops your drawing).
Set your "mouse" coordinates upon pointerdown. This will stop previous lines from being connected to new ones.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var container = document.getElementById('container');
canvas.width = 400;
canvas.height = 300;
var mouse = {x: 0, y: 0};
canvas.addEventListener('pointermove', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('pointerdown', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('pointermove', onPaint, false);
}, false);
canvas.addEventListener('pointerup', function() {
canvas.removeEventListener('pointermove', onPaint, false);
}, false);
var onPaint = function() {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
#canvas {
border: 1px solid rgba(0,0,0,.5);
touch-action: none;
}
<div id="container">
<canvas id="canvas"></canvas>
</div>
I have code which draws a line as I move my mouse while clicking the mouse (mousedown event and mousemove event).
I also want a straight line to be drawn from the beginning of the point (where I first clicked the point, mousedown event) to the end (where I lift the mouse event, mouseup event).
(function() {
var canvas = document.querySelector('#paint');
var ctx = canvas.getContext('2d');
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var mouse = {
x: 0,
y: 0
};
var last_mouse = {
x: 0,
y: 0
};
/* Mouse Capturing Work */
canvas.addEventListener('mousemove', function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
/* Drawing on Paint App */
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', function(e) {
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.beginPath();
ctx.moveTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.closePath();
ctx.stroke();
};
}());
#sketch{
width: 100%;
height: 200px;
background-color: #CCCCCC;
}
<div id="sketch">
<canvas id="paint">
</canvas>
</div>
You want to store the coordinates of the mouseDown event and then use them to draw a single line to the coordinates of the mouseUp event. I modified your code to show a way that can be done:
(function() {
var canvas = document.querySelector('#paint');
var ctx = canvas.getContext('2d');
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var mouse = {
x: 0,
y: 0
};
var last_mouse = {
x: 0,
y: 0
};
/* Mouse Capturing Work */
canvas.addEventListener('mousemove', function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
/* Drawing on Paint App */
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', function(e) {
initialPoint = {x:mouse.x, y:mouse.y}
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
drawStraightLine()
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.beginPath();
ctx.moveTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.strokeStyle = "#000000";
ctx.closePath();
ctx.stroke();
};
let initialPoint
const drawStraightLine = function() {
ctx.beginPath();
ctx.moveTo(initialPoint.x, initialPoint.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.strokeStyle = "#FF000077";
ctx.stroke();
}
}());
#sketch{
width: 100%;
height: 180px;
background-color: #DDDDDD;
}
<div id="sketch">
<canvas id="paint" />
</div>
initialPoint is the mouse position when the button is pressed and drawStarightLine() is the method executed when said button is released. Also added different colors to the lines to make it obvious.
Just add another position object eg
const mouseDownAt = {x: 0, y: 0};
Then when the mouse down event happens record that position
canvas.addEventListener('mousedown', function(e) {
mouseDownAt.x = e.pageX - this.offsetLeft;
mouseDownAt.y = e.pageY - this.offsetTop;
canvas.addEventListener('mousemove', onPaint, false);
}, false);
On the mouse up event draw the closing line
canvas.addEventListener('mouseup', function() {
lastMouse.x = mouse.x;
lastMouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
// if mouse has moved?? draw the last little bit
if (mouse.x !== last_mouse.x || mouse.y !== last_mouse.y) {
onPaint();
}
// set the end position
lastMouse.x = mouse.x;
lastMouse.y = mouse.y;
// use the mouse down at pos as the new position
mouse.x = mouseDownAt.x;
mouse.y = mouseDownAt.y;
// draw the line
onPaint();
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
BTW I am not sure if you know that using closePath as you do will render the path segment twice and will reduce the quality of the line (too strong alphas on the anti aliasing) . closePath is like lineTo (draws a line segment) and not related to ctx.beginPath
function onPaint () {
ctx.beginPath();
ctx.lineTo(lastMouse.x, lastMouse.y); // after beginPath lineTo is the same
// moveTo
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
i want to draw pattern on a image with canvas on click you can understand more with the provided images
here is what end result i want
http://i.imgur.com/wnH2Vxu.png
But i am having this blurred line
http://i.imgur.com/HXF1rTv.png
i am using following code
(
function() {
var canvas = document.querySelector('#canvas');
var ctx = canvas.getContext('2d');
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var mouse = {x: 0, y: 0};
var last_mouse = {x: 0, y: 0};
/* Mouse Capturing Work */
canvas.addEventListener('mousemove', function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
var texture = document.getElementById("texture");
pFill = ctx.createPattern(texture, "repeat");
ctx.strokeStyle = pFill;
/* Drawing on Paint App */
ctx.lineWidth = 12;
ctx.lineJoin = 'square';
ctx.lineCap = 'square';
canvas.addEventListener('mousedown', function(e) {
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.beginPath();
ctx.moveTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.closePath();
ctx.stroke();
};
}()
);
$( document ).ready(function() {
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var img = document.getElementById("scream");
ctx.drawImage(img,10,10);
});
Method with stroke pattern will not work here. Because this pattern position is fixed. So when your line is not exactly horizontal or vertical you will have a distorted image instead of a chain of accurate balls.
Well I think the whole approach should be reconsidered.
User should create a path like in photoshop, which is visible as a temporary line. At first it can easily be a polyline, where vertices are pointed by clicks. And when the path is confirmed (by double click for example) you should remove the temporary line and put the balls along the path with a given step. In this case you can handle all turns and regularity distortions.
This is quite a bunch of work, but the task is in reality much more complex than it seems to be.
As a quick workaround you can try a simple approach. Drop a ball each time distance from the previous drop is more than double radius (for example) of the ball..
var lastBall = {x: null, y : null};
function drawBall(center){
ctx.beginPath();
ctx.arc(center.x, center.y, 10, 0, 2 * Math.PI, false);
ctx.fillStyle = 'orange';
ctx.fill();
}
function distance(a, b){
return Math.sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
}
var onPaint = function() {
if(!lastBall.x || distance(lastBall, mouse) > 25 ){
drawBall(mouse);
lastBall.x = mouse.x;
lastBall.y = mouse.y;
}
The code is rough you should define proper variables for color and radius, or perhaps replace it with your pattern, but you can get the idea
Fiddle
When i call writeTextToCanvas method before clearCanvas method, it works perfectly,
if i call clearCanvas method first than writeTextToCanvas, it doesn't works, drawing functions etc. all works after clearCanvas but fillText doesn't work and also clears all canvas when i call fillText
when i set context.globalAlpha = 0.5 before fillText, i can barely see text on the canvas but anything in canvas erased somehow
var canvas;
var context;
var selectedRole = DRAW_TOOLS.PENCIL;
function initDrawingCanvas(index) {
var question = document.getElementsByClassName('question').item(index);
canvas = question.getElementsByClassName('questionDrawingCanvas').item(0);
context = canvas.getContext("2d");
canvasWidth = canvas.width;
canvasHeight = canvas.height;
compositeOperation = context.globalCompositeOperation;
canvas.addEventListener("touchmove", onCanvasTouchMove, false);
canvas.addEventListener("touchstart", onCanvasTouchStart, false);
canvas.addEventListener("touchstop", onCanvasTouchStop, false);
}
var startX = 0;
var startY = 0;
var endX = 0;
var endY = 0;
var compositeOperation;
function onCanvasTouchMove(event){
endX = event.changedTouches[0].clientX - $(canvas).offset().left;
endY = event.changedTouches[0].clientY - $(canvas).offset().top;
if(selectedRole == DRAW_TOOLS.PENCIL){
context.beginPath();
context.moveTo(startX, startY);
context.lineTo(endX, endY);
context.strokeStyle = $('.colorPicker').css('background-color');
context.lineWidth = parseInt($('#pencilSize').attr("data-size"));
context.stroke();
}else if(selectedRole == DRAW_TOOLS.ERASER){
context.save();
context.globalCompositeOperation = "destination-out";
context.arc(endX,endY,25,0,Math.PI*2,false);
context.fill();
context.restore();
}
startX = endX;
startY = endY;
}
function onCanvasTouchStart(event){
$("#colorPicker").css("display", "none");
$("#pencilSize").css("display", "none");
$("#textColorPicker").css("display", "none");
$("#canvas_textSize").css("display", "none");
startX = event.changedTouches[0].pageX - $(canvas).offset().left;
startY = event.changedTouches[0].pageY - $(canvas).offset().top;
if(selectedRole == DRAW_TOOLS.TEXT){
showConfirmDialog('<textarea id="canvasTextArea" class="canvasTextArea"></textarea>', RESOURCES.CANVAS_TEXT_TITLE, {positiveButton: RESOURCES.OKAY, negativeButton: RESOURCES.CANCEL}, function(){
var text = $("#canvasTextArea").val();
if(isNullOrUndefined(text)) return;
writeTextToCanvas(text);
hideDialog();
}, function(){
hideDialog();
});
$("#canvasTextArea").focus();
$("#canvasTextArea").css("font-size", $('#textSizePicker').attr("data-size") + "px");
$("#canvasTextArea").css("color", $('.textColorPicker').css("background-color"));
}
}
function onCanvasTouchStop(event){
console.log(event);
}
function clearCanvas(){
context.clearRect(0, 0, canvas.width, canvas.height);
}
function getCanvasContent(){
return canvas.toDataURL();
}
function writeTextToCanvas(text) {
context.globalCompositeOperation = "source-over";
context.textBaseline = "top";
context.font = $('#textSizePicker').attr("data-size") + 'px sans-serif';
context.fillStyle = $('.textColorPicker').css("background-color");
context.fillText(text, startX, startY);
}
What should i use to clear canvas or clear some parts like eraser then i can fillText normally?
Your call to clearRect() is stopping the entire script because it throws an error (check the console). You're not passing in a rectangle to the call.
It needs to be called like:
context.clearRect(0, 0, canvas.width, canvas.height);
Here's a working example: http://jsfiddle.net/pe19L15m