HTML5 Canvas why fillText() method clears everything after clearRect() - javascript

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

Related

Clear canvas after ctx.arc was clicked

So the objective is to place a circle randomly on the screen, and if the circle was clicked, remove this old circle and make a new circle.
I'm having a problem with removing the old point and making a new one. Instead of removing the old one, it keeps it, makes a new circle and eventually does whatever this is after a bit of clicking:
This is how my code looks like:
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.cursor = "crosshair";
function randSpot() {
var X = Math.floor(Math.random() * canvas.width) + 10;
var Y = Math.floor(Math.random() * canvas.height) + 10;
ctx.arc(X, Y, 5.5, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
document.body.addEventListener('click', function(e) {
if (ctx.isPointInPath(e.clientX, e.clientY)) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
randSpot()
}
});
}
randSpot()
What am I doing wrong and how can I fix it?
You forgot to begin a new path
ctx.beginPath();
I had to modify the code to make it run in the snippet
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.cursor = "crosshair";
function randSpot() {
var X = Math.floor(Math.random() * canvas.width) + 10;
var Y = Math.floor(Math.random() * canvas.height) + 10;
ctx.beginPath();
ctx.arc(X, Y, 5.5, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
}
randSpot()
document.body.addEventListener('click', function(e) {
// I had to remove the following condition
// ctx.isPointInPath(e.clientX, e.clientY)
// because the code didn't wanted to work with the snippet
// but it's unrelated to the problem
ctx.clearRect(0, 0, canvas.width, canvas.height);
randSpot()
});

Canvas Linear Gradient

I wanna add my linear gradient on my cubic Curve while changing its position while moving my mouse. But somehow it won't work. If i stop changing its position and fix it on my screen it works.
document.addEventListener("DOMContentLoaded", function() {
var canvas = document.querySelector("canvas");
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
ctx = canvas.getContext("2d");
ctx.fillStyle = "#CCC";
ctx.fillRect(0, 0, canvas.width, canvas.height);
//var prev = {};
var mouse = {};
window.addEventListener("mousemove", function(e) {
//prev.x = mouse.x;
//prev.y = mouse.y;
mouse.x = e.pageX;
mouse.y = e.pageY;
});
function draw() {
ctx.fillStyle = "#CCC";
ctx.fillRect(0, 0, canvas.width, canvas.height);
var grad = ctx.createLinearGradient(50, 50, 150, 150);
grad.addColorStop(0, "yellow");
grad.addColorStop(0.5, "white");
grad.addColorStop(1, "orange");
ctx.lineWidth = 10;
ctx.lineJoin = "round";
ctx.strokeStyle = grad;
ctx.beginPath();
ctx.moveTo((canvas.width / 2), (canvas.height / 2));
ctx.quadraticCurveTo(((canvas.width / 2) - 100), (canvas.height / 2 + 100), (mouse.x), (mouse.y));
ctx.stroke()
};
window.addEventListener("mousemove", draw);
});
When I remove it from the DOMContentLoaded event function it works fine in this jsfiddle : https://jsfiddle.net/wboq6bsk/
var canvas = document.querySelector("canvas");
canvas.id= 'test'
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
ctx = canvas.getContext("2d");
ctx.fillStyle = "#CCC";
ctx.fillRect(0, 0, canvas.width, canvas.height);
var mouse = {};
window.addEventListener("mousemove", function(e){
mouse.x = e.pageX;
mouse.y = e.pageY;
});
function draw(){
console.log('dra');
ctx.fillStyle = "#CCC";
ctx.fillRect(0, 0, canvas.width, canvas.height);
var grad = ctx.createLinearGradient(50, 50, 150, 150);
grad.addColorStop(0, "yellow");
grad.addColorStop(0.5, "white");
grad.addColorStop(1, "orange");
ctx.lineWidth = 10;
ctx.lineJoin = "round";
ctx.strokeStyle = grad;
ctx.beginPath();
ctx.moveTo((canvas.width/2), (canvas.height/2));
ctx.quadraticCurveTo(((canvas.width/2)-100), (canvas.height/2+100), (mouse.x), (mouse.y));
ctx.stroke()
}
window.addEventListener("mousemove", draw);
Unless you mean your gradient it not moving with the curve, but right now this has normal behavior. You can probably get the gradient to move too by passing in mouse positions while creating the gradient on each draw.

Blur part of the image with Javascript/Jquery

I'm trying to blur a part of the photo. My code is as follows:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var imageObj = null;
function init() {
imageObj = new Image();
imageObj.onload = function () { ctx.drawImage(imageObj, 0, 0); };
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
}
function mouseDown(e) {
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
drag = true;
}
function mouseUp() { drag = false; }
function mouseMove(e) {
if (drag) {
ctx.clearRect(0, 0, 500, 500);
ctx.drawImage(imageObj, 0, 0);
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
ctx.strokeStyle = 'blue';
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
ctx.filter = 'blur(5px)';
}
}
//
init();
<canvas id="canvas" width="500" height="500"></canvas>
I draw a rectangle but I want to apply the blur filter only on that rectangle not to the whole image as it is now. Any idea how to do that?
Here is the fiddle
It is possible by using HTML5 Canvas
I have made a fiddle to blur the part 350 from image.
Fiddle Link: https://jsfiddle.net/k6aaqdx6/3/
Edit:
updated according to your fiddle: https://jsfiddle.net/tbjLk6eu/2
Code that I added:
imgData=ctx.getImageData(rect.startX, rect.startY, rect.w, rect.h);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.filter = 'none';
ctx.drawImage(imageObj, 0, 0);
ctx.putImageData(imgData,rw, rh);
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
working jsfiddle: https://jsfiddle.net/zoh5o9p5/
If you use a base64 image and do some changes it will work as you expected
made some changes in mouseMove function.
function mouseMove(e) {
if (drag) {
ctx.filter = 'blur(5px)';
ctx.drawImage(imageObj, 0, 0);
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
ctx.strokeStyle = 'blue';
if(rect.w>0 && rect.h>0)
{
imgDrow=ctx.getImageData(rect.startX, rect.startY, rect.w, rect.h);
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.filter = 'none';
ctx.drawImage(imageObj, 0, 0);
w=rect.w<0?rect.startX+rect.w:rect.startX;
h=rect.h<0?rect.startY+rect.h:rect.startY;
if(imgDrow)
{
ctx.putImageData(imgDrow,w, h);
}
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
}
working jsfiddle: https://jsfiddle.net/zoh5o9p5/
we can use fabric.js library. Here you can draw a rectangle and move it and resize it. The original fiddle was having some console error and scaling was not working. I have resolved them all in the bellow jsfiddle.
Here we first copy the original image and create a copy canvas and make the full image blur. Then on move or scaling of the rectangle just showing actual crop to show the proper blur section.
function blurSelection(left=0, top=0, img=null) {
if (img) {
img.cropX = left;
img.cropY = top;
fabricCanvas.renderAll();
} else {
const image = fabric.Image.fromURL(blurredCanvas.toDataURL(), function (img) {
img.cropX = left;
img.cropY = top;
img.width = 200; // Default
img.height = 100; // Default
img.objectCaching = false;
fabricCanvas.add(img);
img.bringToFront();
img.on('moving', function (options) {
const newLeft = options.target.left;
const newTop = options.target.top;
blurSelection(newLeft, newTop, img=options.target);
});
img.on('scaling', function (options) {
const newLeft = options.target.left;
const newTop = options.target.top;
const newWidth = options.target.width * options.target.scaleX;
const newHeight = options.target.height * options.target.scaleY;
//console.log("scaleX",options.target.scaleX,'scaleY',options.target.scaleX,"newWidth",newWidth,"newHeight",newHeight)
options.target.scaleX=1;
options.target.scaleY=1;
options.target.width=newWidth;
options.target.height=newHeight;
})
});
}
}
function copyCanvas() {
const objects = fabricCanvas.getObjects();
const copiedCanvas = fabricCanvas.toCanvasElement();
const blurredImage = new fabric.Image(copiedCanvas);
const filter = new fabric.Image.filters.Blur({
blur: 0.8
});
blurredImage.filters.push(filter);
blurredImage.applyFilters();
blurredCanvas = new fabric.Canvas(copiedCanvas);
window.blurredCanvas = blurredCanvas;
blurredCanvas.add(blurredImage);
blurredCanvas.renderAll();
// Just for the inspection of the blurred image
document.getElementById('asd').src = copiedCanvas.toDataURL();
}
https://jsfiddle.net/debchy/ajbpefk4/7/

Flip image and the line drawed in HTML5 canvas

I am using canvas loading an image. draw some lines on the image. Then I want to click a "flip" button to flip the image and the lines I just draw. The code is here on jsfiddle.
My current problem is:
The lines I draw won't get flipped but the image is flipped after I
click the "flip" button.
The lines wont' show up immediately after I
click the "flip" button. The lines will show when I start to draw
again.
Any help will be appreciated.
Thanks,
var context;
var canvas;
var imageObj = new Image();
var flipH = true;
var flipV = true;
var scaleH = 1,
scaleV = 1;
var posX = 0,
posY = 0;
var isDrawingFreeDraw;
canvas = document.getElementById('myCanvas');
context = canvas.getContext('2d');
context.strokeStyle = "#FFFF00";
//context.save();
canvas.addEventListener('mousedown', MouseDown, true);
canvas.addEventListener('mouseup', MouseUp, true);
canvas.addEventListener('mousemove', MouseMove, true);
imageObj.src = 'http://upload.wikimedia.org/wikipedia/commons/1/1a/Image_upload_test.jpg';
imageObj.onload = function () {
context.drawImage(imageObj, posX, posY, canvas.height * imageObj.width / imageObj.height, canvas.height);
};
console.log(context);
$(document).on('click', '#FlipH', function () {
console.log("Flip Me");
// context.restore();
context.save();
//canvas.width = 100;
scaleH = flipH ? -1 : 1;
context.scale(scaleH, scaleV);
posX = flipH ? (canvas.height * imageObj.width / imageObj.height) * -1 : 0;
context.drawImage(imageObj, posX, posY, canvas.height * imageObj.width / imageObj.height, canvas.height);
flipH = !flipH;
context.scale(1, 1);
//console.log(context);
context.restore();
});
function MouseUp(e) {
isDrawingFreeDraw = false;
context.save();
}
function MouseDown(e) {
context.save();
isDrawingFreeDraw = true;
console.log(e);
context.moveTo(e.pageX, e.pageY);
context.restore();
}
function MouseMove(e) {
if (isDrawingFreeDraw) {
context.save();
context.lineTo(e.pageX, e.pageY);
context.stroke();
context.restore();
}
}
To flip both the image and your drawings, you can use the canvas itself as a source for drawImage.
// draw the canvas to itself
ctx.drawImage(canvas,0,0);
A Demo: http://jsfiddle.net/m1erickson/Y9SLQ/
Example code:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.onload=start;
img.src="http://upload.wikimedia.org/wikipedia/commons/1/1a/Image_upload_test.jpg";
function start(){
canvas.width=img.width;
canvas.height=img.height;
ctx.drawImage(img,0,0);
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineTo(50,300);
ctx.lineTo(250,300);
ctx.lineWidth=8;
ctx.stroke();
}
$("#flipbutton").click(function(){
ctx.save();
ctx.translate(canvas.width,0);
ctx.scale(-1,1);
ctx.drawImage(canvas,0,0);
ctx.restore();
});

Drawing a filled circle in a canvas on mouseclick

I want to draw a filled (or not filled) circle in a canvas on mouseclick, but I can't get my code to work properly, I've tried pretty much everything!
This is my HTML:
<div id="images"></div>
<canvas style="margin:0;padding:0;position:relative;left:50px;top:50px;" id="imgCanvas" width="250" height="250" onclick="draw(e)"></canvas>
and my current script:
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
function createImageOnCanvas(imageId) {
canvas.style.display = "block";
document.getElementById("images").style.overflowY = "hidden";
var img = new Image(300, 300);
img.src = document.getElementById(imageId).src;
context.drawImage(img, (0), (0)); //onload....
}
function draw(e) {
var pos = getMousePos(canvas, e);
posx = pos.x;
posy = pos.y;
context.fillStyle = "#000000";
context.arc(posx, posy, 50, 0, 2 * Math.PI);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
The code works just fine if and only if I remove the "use strict";, but in this assignment I have to make a code that works even with it, which is my problem.
Here is the jsFiddle
Solved it myself.
function draw(e) {
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
var rect = canvas.getBoundingClientRect();
var posx = e.clientX - rect.left;
var posy = e.clientY - rect.top;
context.fillStyle = "#000000";
context.beginPath();
context.arc(posx, posy, 50, 0, 2 * Math.PI);
context.fill();
}
This script works fine for me.

Categories

Resources