Toggle Onclick Issue in Javascript - javascript

Simply put, I'm trying to toggle a button to make a line bold (or not). I read a few questions here similar to this problem, but the solutions haven't helped me. Here's my code:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="DrawLineDiv">
<canvas id="DrawLineCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('DrawLineCanvas');
var context = canvas.getContext('2d');
// Use beginPath() to declare that a new path is to be drawn
context.beginPath();
// Place the drawing cursor at the desired point
context.moveTo(100, 150);
// Determine where to stop drawing
context.lineTo(450,50);
//Draw the line
context.stroke();
</script>
</div>
<script>
var canvas = document.getElementById("DrawLineCanvas");
//var context = canvas.getContext('2d');
function toggleLineBold(button) {
var button;
if (button == "BoldNow") {
context.lineWidth = 15;
context.stroke();
document.getElementById("BoldLineButton").onclick = function(){
toggleLineBold('Regular');
};
} else {
context.lineWidth = 1;
context.stroke();
document.getElementById("BoldLineButton").onclick = function(){
toggleLineBold('BoldNow');
};
return;
};
};
</script>
<div id="BoldLineButton" style="height:50px; width:120px; border:2px solid #6495ed; background-color:#bcd2ee; border-radius:10px; margin-left: 5px; text-align:center" onclick="toggleLineBold('BoldNow')">
<br/>Toggle Bold Line<br/>
</div>
</body>
</html>
The line changes to bold, but triggers an error in the javascript at the line trying to change the onclick event. I know I've got something wrong, I'm just not sure what.
Thank's in advance for your assistance.

LIVE DEMO
HTML:
<canvas id="DrawLineCanvas" width="578" height="200"></canvas>
<button id="BoldLineButton">Line size: <b>1</b></button>
JS:
var doc = document,
canvas = doc.querySelector('#DrawLineCanvas'),
boldBtn = doc.querySelector('#BoldLineButton'),
ctx = canvas.getContext('2d'),
size = [1, 3, 5, 10, 15], // use only [1, 15] if you want
currSize = 0; // size[0] = 1 // Index pointer to get the value out of the
// size Array
function draw(){
canvas.width = canvas.width;
ctx.beginPath();
ctx.moveTo(100, 150);
ctx.lineTo(450,50);
ctx.lineWidth = size[currSize]; // Use currSize Array index
ctx.stroke();
}
draw();
function toggleLineBold() {
++currSize; // Increase size and
currSize %= size.length; // loop if needed.
boldBtn.getElementsByTagName('b')[0].innerHTML = size[currSize];
draw();
}
boldBtn.addEventListener("click", toggleLineBold);

Related

Fabric.js remnants of old canvas remain

I want to display the content of a canvas as the background of another canvas and draw a bunch of rectangles on there. I need to dynamically change:
the canvas from which to load the background image for my finalcanvas
which rectangles to draw
It's easiest if I start this process from scratch. I have imitated starting from scratch with a simple button. However, after redrawing my canvas, previous information from fabric.js remains present after dragging an item of a canvas a bit. This means that the old canvas was not cleared properly. I tried playing around with .clear() and .depose(), but to no avail.
In case the description is vague, here an image:
And an small reproducible example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello</title>
</head>
<body>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js" type="text/javascript"></script>
<script>
function load_plane_onto_active_canvas() {
var c = document.getElementById('backgroundcanvas');
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
var canvas = new fabric.Canvas('finalcanvas', {
width: 333,
height: 333
});
canvas.setBackgroundImage(bg, canvas.renderAll.bind(canvas));
canvas.on("mouse:over", function(e) {
console.log(e.target)
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: 'green',
})
canvas.add(rect);
}
}
}
window.onload = function() {
// fill the background canvas with red
(function() {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
}())
load_plane_onto_active_canvas()
}
</script>
<button onclick="load_plane_onto_active_canvas()">click me</button>
</body>
</html>
I hope someone can help me!
Notice that you're creating a new instance of fabric.Canvas in your load_plane_onto_active_canvas() function. So when you're clicking the button, the existing canvases stay intact, and you're actually calling clear() on your freshly created canvas. The DOM becomes messed up at this point, with several nested canvases inside of each other - you can take a peek at the DOM inspector to see that.
What you can do instead is create the canvas instance just once, then work with a reference to it later in your other functions.
const finalCanvas = new fabric.Canvas("finalcanvas", {
width: 333,
height: 333
});
// finalCanvas now exists in the global (window) scope
function load_plane_onto_active_canvas() {
var c = document.getElementById("backgroundcanvas");
var ctx = c.getContext("2d");
var bg = c.toDataURL("image/png");
finalCanvas.clear();
finalCanvas.setBackgroundImage(bg, finalCanvas.renderAll.bind(finalCanvas));
finalCanvas.on("mouse:over", function (e) {
// console.log(e.target);
});
// add 100 rectangles
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
rect = new fabric.Rect({
width: 10,
height: 10,
left: j * 15,
top: i * 15,
fill: "green"
});
finalCanvas.add(rect);
}
}
}
window.onload = function () {
// fill the background canvas with red
(function () {
var canvas = document.getElementById("backgroundcanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
})();
load_plane_onto_active_canvas();
};
document.querySelector("#b1").onclick = () => load_plane_onto_active_canvas();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.js"></script>
<canvas id="finalcanvas"></canvas>
<canvas id="backgroundcanvas" width="200" height="100"></canvas>
<button id="b1">start from scratch</button>

Javascript how to make object appear over a background image

Hello I am trying to create a guitar hero sort of program with red circles appearing over a violin image when the corresponding key presses are pressed but I can't seem to be able to make them appear over the image even if I write the code after the canvas code. Can someone help me with this? I would also like to make the circles disappear after a while but timeout won't do the trick here because the image is not one color only for example changing the red circles to the background color after a while. How would i do this?
<html>
<head>
<title>Violin Hero</title>
<canvas id="myCanvas" width="1024" height="768"></canvas>
<style>
body {
background-image: url("violin.jpg");
background-size: 2500px 1300px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="1024" height="768"></canvas>
<img id="bow" src="bow.jpg" style="display:none;" />
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
window.addEventListener("keydown", soundPlay);
function fillRed() {
ctx.fillStyle = "red";
ctx.fill();
}
function keyQ(){
ctx.beginPath();
ctx.arc(1200, 300, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyW(){
ctx.beginPath();
ctx.arc(300, 300, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyE(){
ctx.beginPath();
ctx.arc(900, 500, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyR(){
ctx.beginPath();
ctx.arc(950, 100, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
//var x = event.keyCode;
//<input type="text" onkeydown="pressedKey(event)">
function soundPlay(event) {
var x = event.keyCode;
if (x == 27) { // 27 is the ESC key
alert ("You pressed the Escape key!");
}
else if (x == 81) {
keyQ();
var sound = new Audio('1.mp3');
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 87) {
keyW();
var sound = new Audio("2.mp3");
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 69) {
keyE();
var sound = new Audio("3.mp3");
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 82) {
keyR();
var sound = new Audio("4.mp3");
sound.play();
setTimeout(fillRed, 200);
}
}
</script>
</body>
</html>
To bring something in front of images/To bring something always behind elements, one should use z-index.
Make a css for background image like this:
#backgroundImg{
position: absolute;
left: 0px;
top: 0px;
z-index: -1;
}
In this way, the background image will always be behind. Please check this or this for more details.
For your second question, I suggest you should make another post and keep this question focused on one issue only.
I've created a simple Plunkr example for you on how to achieve this kind of functionality in JS.
Click s, a or any other to show a red dot.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body id='mybody'>
<img id='violin' src='http://cdn.shopify.com/s/files/1/0704/3831/products/Antoni_Debut_Violin_Outfit_3677b25a-7618-46f7-9313-6080c2a51e27_grande.jpg?v=1444483336'>
<script>
document.addEventListener('keydown', (event) => {
console.log(event);
if (event.key.toLowerCase() === 's') {
showRedDot(110, 420);
} else if (event.key.toLowerCase() === 'a') {
showRedDot(150, 350);
} else {
showRedDot(200, 300);
}
});
var showRedDot = (top, left) => {
var oldDot = document.getElementById('redDot');
if (oldDot) {
oldDot.remove();
}
var dot = document.createElement('DIV');
dot.id = 'redDot';
dot.style.width = '10px';
dot.style.height = '10px';
dot.style.position = 'absolute';
dot.style.borderRadius = '100%';
dot.style.background = 'red';
dot.style.top = top + 'px';
dot.style.left = left + 'px';
document.getElementById('mybody').appendChild(dot);
};
</script>
</body>
</html>
Here's a working Plunkr

How can I check if an attractor is strange?

Lately I learned a bit about strange attractors, and I created the following programm in JS:
var ctx, clock, width, height, pixSize;
var x,y,a,b,c,d;
window.onload = function(){
start();
};
function start(random=true){
window.cancelAnimationFrame(clock);
if(random){
a = 6*Math.random()-3;
b = 6*Math.random()-3;
c = 2*Math.random()-0.5;
d = 2*Math.random()-0.5;
}
canvasSetup();
clearCanvas();
x = Math.random()-Math.random();
y = Math.random()-Math.random();
clock = requestAnimationFrame(main);
}
function save(){
var text = JSON.stringify({
a:a,
b:b,
c:c,
d:d
});
window.prompt("Copy to clipboard: Ctrl+C", text);
}
function load(){
var input = JSON.parse(window.prompt("Import Save:"));
a = input.a;
b = input.b;
c = input.c;
d = input.d;
start(false);
}
function canvasSetup(){
canvas = document.getElementById('canvas');
width = window.innerWidth-5;
height = window.innerHeight-5;
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
var min = Math.min(width,height);
var scale = min/4;
ctx.translate(width/2, height/2);
ctx.scale(scale, scale);
pixSize = 1/scale/2;
ctx.globalCompositeOperation = "lighter";
}
function clearCanvas(){
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0,0,width,height);
ctx.restore();
}
function main(){
for(var i=0;i<10000;i++){
var xnew = Math.sin(y*b)+c*Math.sin(x*b);
var ynew = Math.sin(x*a)+d*Math.sin(y*a);
x = xnew;
y = ynew;
plot(x,y,"rgb(50,5,1)");
}
clock = requestAnimationFrame(main);
}
function plot(x,y,color="white"){
ctx.fillStyle = color;
ctx.fillRect(x,-y,pixSize,pixSize);
}
body {
background-color: black;
color: white;
font-family: Consolas;
font-size: 13px;
margin: 0;
padding: 0;
}
#buttons{
position: absolute;
top: 0;
left: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Strange Attractor</title>
<link rel="stylesheet" href="style.css">
<script src="rules.js"></script>
<script src="script.js"></script>
</head>
<body>
<div align="center">
<canvas id="canvas"></canvas>
</div>
<div id="buttons">
<button onclick="start()">New Attractor</button><br>
<button onclick="save()">Save</button><br>
<button onclick="load()">Load</button>
</div>
</body>
</html>
It's taking 4 random Parameters (a,b,c,d) and uses the formular
var xnew = Math.sin(y*b)+c*Math.sin(x*b);
var ynew = Math.sin(x*a)+d*Math.sin(y*a);
x = xnew;
y = ynew;
for the new point. In some cases this indeed creates a fancy strange sttractor:
But in other cases I only get a single line or a few points. Is there a simple way to look at the parameters and find out, if the attrator they create will be strange?
I know, that I could save a bunch of values, compare them with each other and test in that way, if the picture might be intresting, but I'd love a different solution...
I hope you can help :)
EDIT:
To look at speccific values you can simply use the save and load buttons in the js sketch above...

Cell of a minesweeper board does not appear Html&CSS&JS

I am trying to creat a minesweeper board in Javascript, but first i tried to creat only one cell. this is my code. It was suppose to draw a cell from the 30px width and 30px height picture that i created ( cell.png ) but when i run the code i only see the canvas. What am i doing wrong?
<!DOCTYPE html>
<html>
<head>
<script>
var s = {
rows: 10,
col: 10,
width: 30,
height: 30,
};
var c;
window.onload = function(){
var canvas = document.getElementById("myCanvas");
c = canvas.getContext("2d");
// c.fillRect(50,50,300,300);
init();
}
var box;
function init(){
box = new Image();
box.src = "cell.png";
draw();
}
function draw(){
c.clearRect(0,0,400,400);
c.drawImage(box,10,10);
}
</script>
</head>
<body>
<div id="controls">
</div>
<div id="game">
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
</canvas>
</div>
</body>
</html>
The problem you are experiencing is because your code is not waiting for the image to load before trying to draw it. You need to wait till it is loaded then call the drawing code, this can be done from the image's onload event
var s = {
rows: 10,
col: 10,
width: 30,
height: 30,
};
var c;
window.onload = function(){
var canvas = document.getElementById("myCanvas");
c = canvas.getContext("2d");
init();
}
var box;
function init(){
box = new Image();
//onload will be called once the image has loaded
box.onload = function(){
//Here you call draw.
draw();
};
box.src = "http://placehold.it/30x30"; //"cell.png";
}
function draw(){
c.clearRect(0,0,400,400);
c.drawImage(box,10,10);
}
<canvas width="200" height="200" id="myCanvas"></canvas>

canvas based color picker on another canvas element

i have made a canvas having width and height of the window.i also made a color picker based on canvas which has a onmousemove event to get pixel information so that i can use that color to draw on my main canvas.individually the onmousemove for picker works but as soon as i put it on the corner side and gave it a fixed position accroding to my main drawing canvas, it's mouse event doesnt work.even i can draw beneath the color picker.i tried to set a z-index property for the color picker ,though it did'nt work.how can i solve this problem and make my picker work fine
hope i make my problem clear :(
if you run my code i hope you will understand the problem
<html>
<head>
<title>a drawing board</title>
</head>
<body style="margin:0;">
<script>
var radius=10;
var colorit="";
var lines;
var x,y;
var cna=false;
var i=0;
function canvloder(){
var canvas=document.getElementById("mycanvas");
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
canvas.style.backgroundColor="yellow";
}
function nowdraw(e){
cna=true;
}
function drawit(e){
if(cna){
var ctx=document.getElementById("mycanvas").getContext("2d");
x=e.clientX;
y=e.clientY;
if(i==0){
ctx.lineWidth=2*radius;
ctx.lineTo(x,y);
ctx.stroke();
}
if(i>0){
ctx.fillStyle=colorit;
ctx.beginPath();
ctx.arc(x,y,radius,0,2*Math.PI);
ctx.fill();
i=0;
}
ctx.fillStyle=colorit;
ctx.beginPath();
ctx.arc(x,y,radius,0,2*Math.PI);
ctx.fill();
ctx.lineWidth=2*radius;
ctx.strokeStyle=colorit;
ctx.beginPath();
ctx.moveTo(x,y);
}
}
function cannotdraw(){
cna=false;
i++;
}
window.onmousedown=nowdraw;
window.onmousemove=drawit;
window.onmouseup=cannotdraw;
function pencolor( colname){
colorit=colname;
}
function therad(capture){
if(capture=="increase"){
radius++;
}
if(capture=="decrease"){
radius--;
}
}
function gotClicked(val){
radius=val;
}
function itsmycanvas(){
var newCanvas = document.createElement('canvas');
var k=0,j=0,a=255,r=0;g=0;
newCanvas.width = 256;
newCanvas.height = 256;
newCanvas.style.position="fixed";
newCanvas.style.top="30px";
newCanvas.style.right="0px";
newCanvas.style.border ='2px solid black';
newCanvas.style.zIndex="2000";
for(r=0;r<256;r++){
for(g=0;g<256;g++){
var context = newCanvas.getContext('2d');
context.beginPath();
context.moveTo(k,j);
context.strokeStyle = 'rgb(' + r + ', ' + g + ','+a+')';
context.lineTo(k+90,j);
context.stroke();
context.closePath();
j++;
if(j==256){
if(k<=256-90){
k=k+90;
}
j=0;
}
a--;
if(a==0){a=150;}
}
}
var d=document.body.appendChild(newCanvas);
d.addEventListener("mouseover",myfunc,false);
}
function myfunc(e) {
var imageData = context.getImageData(e.clientX, e.clientY, 1, 1);
var red = imageData.data[0];
var green = imageData.data[1];
var blue = imageData.data[2];
var alpha = imageData.data[3];
alert(red+" "+green+" "+blue);
}
window.onload=canvloder;
</script>
<canvas id="mycanvas"></canvas>
<div style="position:fixed;top:0px;background-color:grey;display:block;width:100%;">
<div style="float:right;left:50px;">Radius <span title="increase width"style="background-color:white;padding:5px;margin-right:5px;" onCLick="therad('increase');"> + </span><span title="decrease width" style="padding:5px;background-color:white;margin-right:5px;" onClick="therad('decrease');"> - </span></div>
<div title="red" style="background-color:red;width:30px;height:30px;border-radius:30px;float:left;" onClick="pencolor('red');"></div>
<div title="black"style="background-color:black;width:30px;height:30px;border-radius:40px;float:left;" onClick="pencolor('black');"></div>
<div title="pink"style="background-color:pink;width:30px;height:30px;border-radius:40px;float:left;" onClick="pencolor('pink');"></div>
<div title="green"style="background-color:green;width:30px;height:30px;border-radius:40px;float:left;" onClick="pencolor('green');"></div>
<div title="eraser"style="background-color:white;width:30px;height:30px;border-radius:40px;float:left;text-align:centre;" onClick="pencolor('yellow');">clr</div>
<div title="blue"style="background-color:blue;width:30px;height:30px;border-radius:40px;float:left;" onClick="pencolor('blue');"></div>
</div>
<select style="position:fixed;top:0px;left:300px;">radius
<option onClick="gotClicked(15);">15px</option>
<option onClick="gotClicked(10);" selected>10px</option>
<option onClick="gotClicked(6);">8px</option>
<option onClick="gotClicked(5);">5px</option>
<option onClick="gotClicked(3);">3px</option>
</select>
<input type="button" onClick="itsmycanvas();" value="SHOW CANVAS" style="position:fixed;top:400px;right:0px;">
</body>
</html>
jsfiddle
(fiddle not working as it should be :\don't know what's wrong )
I removed the body tag from html and add the option no warp in body(option of fiddle)
it seems working
jsfiddle

Categories