Objects seem to be appearing behind my canvas - javascript

I'm adding objects to my canvas with the fabricjs library (1.7.21) however I am getting this odd behavior where objects are appearing to be behind the canvas. The text is either displayed as white or behind the canvas and I'm not sure why or how. What am I missing here?
var canvas = this.__canvas = new fabric.Canvas('canvas');
responsive();
window.addEventListener('resize', responsive);
function responsive() {
var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
var height = (window.innerHeight > 0) ? window.innerHeight : screen.height;
var widthn = width - 10;
var heightn = height - 10;
canvas.setDimensions({
width: widthn,
height: heightn
});
}
function clearcan() {
var txt;
if (confirm("Chuck this?")) {
console.log(canvas)
canvas.clear().renderAll();
newleft = 0;
}
}
// Add Text
function Addtext() {
var text = new fabric.IText("Tape & Type...", {
fontSize: 30,
top: 10,
left: 10,
width: 200,
height: 200,
textAlign: "center"
});
canvas.add(text);
canvas.setActiveObject(text);
text.enterEditing();
text.selectAll();
text.renderCursorOrSelection(); // or canvas.renderAll();
}
body {
background-color: #303030;
color: white;
}
canvas {
border-radius: 3px;
border: 1px solid #3030;
margin: 5px;
background-color: white;
}
.btn {
background-color: #3030;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.min.js"></script>
<div class="col d-flex justify-content-center">
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group mr-2" role="group" aria-label="First group">
<button onclick="clearcan();" type="button" class="btn btn-sm">Clear</button>
<button onclick="Addtext()"type="button" class="btn btn-sm"> Add Text</button>
</div>
</div>
</div>
<canvas id="canvas"></canvas>
Here's my JSFiddle.

Remove background-color from css which applies to both upper and lower canvas. use this
var canvas = this.__canvas = new fabric.Canvas('canvas',{
backgroundColor:'white'
});
It will make lower canvas background white.
DEMO
var canvas = this.__canvas = new fabric.Canvas('canvas',{
backgroundColor:'white'
});
responsive();
window.addEventListener('resize', responsive);
function responsive() {
var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
var height = (window.innerHeight > 0) ? window.innerHeight : screen.height;
var widthn = width - 10;
var heightn = height - 10;
canvas.setDimensions({
width: widthn,
height: heightn
});
}
function clearcan() {
var txt;
if (confirm("Chuck this?")) {
console.log(canvas)
canvas.clear().renderAll();
newleft = 0;
}
}
// Add Text
function Addtext() {
var text = new fabric.IText("Tape & Type...", {
fontSize: 30,
top: 10,
left: 10,
width: 200,
height: 200,
textAlign: "center"
});
canvas.add(text);
canvas.setActiveObject(text);
text.enterEditing();
text.selectAll();
text.renderCursorOrSelection(); // or canvas.renderAll();
}
body {
background-color: #303030;
color: white;
}
canvas {
border-radius: 3px;
border: 1px solid #3030;
margin: 5px;
//background-color: white;
}
.btn {
background-color: #3030;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.min.js"></script>
<div class="col d-flex justify-content-center">
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group mr-2" role="group" aria-label="First group">
<button onclick="clearcan();" type="button" class="btn btn-sm">Clear</button>
<button onclick="Addtext()"type="button" class="btn btn-sm"> Add Text</button>
</div>
</div>
</div>
<canvas id="canvas"></canvas>

Related

Javascript unable to capture the mouse position in dedicated variables, when I can easily print it out

So, I am getting back into javascript coding, and I am resuming an older project. I am attempting to capture the mouse position in dedicated variables (mouseX and mouseY), for ease of use.
I have successfully managed to print out the mouse coordinates in real time, but when I try to place those coordinates into dedicated variables for ease of use, the program fails.
I believe this is most likely a simple syntax error, but I don't know where else to look for what I'm doing wrong.
This code fragment works correctly:
document.addEventListener('mousemove', (event) => {
document.getElementById("fiddleText").innerHTML = (`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`);
})
However, when I try to store the mouse position in two variables, like so:
document.addEventListener('mousemove', (event) => {
mouseX = event.ClientX;
mouseY = event.ClientY;
document.getElementByID("fiddleText").innerHTML = (`Mouse X: `+ mouseX + `Mouse Y: ` + mouseY);
})
the program fails.
Note: I've updated the second code fragment to fix a syntax error that was brought to my attention, but it still doesn't work.
The original second fragment looked like this:
document.addEventListener('mousemove', (event) => {
mouseX = ${event.clientX};
mouseY = ${event.clientY};
document.getElementByID("fiddleText").innerHTML = (`Mouse X: `+ mouseX + `Mouse Y: ` + mouseY);
})
I'd like to imagine that my question can be answered using only the code shown above, but last time I believed that, I was mistaken. As such, I have pasted my full javascript program below.
Note: This program is a work-in-progress, and there is a comment header stating "this is the problem area"; ignore this for now, that is an unrelated issue. Right now, I'm just trying to get the mouse to work.
//canvas elements
var canvas = document.getElementById("SnekGamCanvas");
var ctx = canvas.getContext("2d");
canvas.addEventListener('click', function () { }, false);
/*
//some code from stack overflow: (https://stackoverflow.com/questions/9880279/how-do-i-add-a-simple-onclick-event-handler-to-a-canvas-element)
var elem = document.getElementById('canvas'),
elemLeft = elem.offsetLeft + elem.clientLeft,
elemTop = elem.offsetTop + elem.clientTop,
context = elem.getContext('2d'),
elements = [];
// Add event listener for `click` events.
elem.addEventListener('click', function (event) {
var x = event.pageX - elemLeft,
y = event.pageY - elemTop;
// Collision detection between clicked offset and element.
elements.forEach(function (element) {
if (y > element.top && y < element.top + element.height
&& x > element.left && x < element.left + element.width) {
alert('clicked an element');
}
});
}, false);
// Add element.
elements.push({
colour: '#05EFFF',
width: 150,
height: 100,
top: 20,
left: 15
});
// Render elements.
elements.forEach(function (element) {
context.fillStyle = element.colour;
context.fillRect(element.left, element.top, element.width, element.height);
});
*/
//End of code from stack overflow
//some important variables
var px = canvas.width / 2;
var py = canvas.height / 2;
var snekColor = "#EC942D";
var clock = 0;
var mouseX = 0.5;
var mouseY = 0.5;
//classes
class clickButton {
constructor(text, color, width, height, radius) {
this.text = text;
this.color = color;
this.width = width;
this.height = height;
this.radius = radius;
}
drawButton(xpos, ypos) {
ctx.strokeStyle = "#000000"
ctx.fillStyle = this.color;
roundRect(xpos, ypos, this.width, this.height, this.radius, true, true, this.color);
ctx.fillStyle = "#000000";
ctx.strokeStyle = "#000000";
ctx.font = '40px san-serif';
ctx.strokeText(this.text, xpos + 10, ypos + 40);
ctx.fillText(this.text, xpos + 10, ypos + 40);
//draw_Ball(303, 500, 50, snekColor);
}
clickOnButton() {
}
}
//buttons
var startButton = new clickButton("Start Game", "#74B5ED", 200, 50, 20);
//images
var seel = new Image();
seel.onload = function () {
ctx.drawImage(seel, 0, 0, canvas.width, canvas.height);
}
seel.src = "https://assets.pokemon.com/assets/cms2/img/pokedex/full/086.png"
var snek_title = new Image();
snek_title.onload = function () {
ctx.drawImage(snek_title, 0, 0, canvas.width, canvas.height);
}
snek_title.src = "https://globin347.com/images/Snake%20Title.png"
//stuff about mouse moving
document.addEventListener('mousemove', (event) => {
//document.getElementById("fiddleText").innerHTML = (`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`);
mouseX = event.ClientX;
mouseY = event.ClientY;
document.getElementByID("fiddleText").innerHTML = (`Mouse X: `+ mouseX + `Mouse Y: ` + mouseY);
})
//begin
var gameState = 0;
function draw() {
clock += 1;
ctx.clearRect(0, 0, canvas.width, canvas.height);
//document.getElementById("fiddleText").innerHTML = ("Clock: " + clock);
if (gameState == 0) {
//this hasn't been implemented yet
startMenu();
}
else if (gameState == 1) {
//this hasn't been implemented yet either
playGame();
}
else if (gameState == 2) {
//ditto
gameOver();
}
else {
//something's wrong
ctx.drawImage(seel, 0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#b30000";
ctx.strokeStyle = "#000000";
ctx.font = '140px san-serif';
ctx.fillText('OH NO', 120, 120);
ctx.strokeText('OH NO', 120, 120);
ctx.fillText('IT BLOKE', 200, 630);
ctx.strokeText('IT BLOKE', 200, 630);
}
}
setInterval(draw, 10);
function startMenu() {
ctx.drawImage(snek_title, 0, 0, canvas.width, canvas.height);
/***********************************************
*
*
* This is the problem area. When the next line, startButton.drawButton(100, 100) is commented out, the rest of the code workes normally.
* However, if the line is not commented out, draw_Ball doesn't run, indicating that the program crashed somewhere in the button code.
* I would like to reiterate that the button's functionality has not yet been implemented; I am only trying to get it to display.
*
*
**********************************************/
//startButton.drawButton((canvas.width / 2) - 100, (canvas.height * (4 / 5)));
//flashing lights
/*flashTime = timer % 100;
if (timer % 2) {
draw_Ball(200, 700, 50, snekColor);
}*/
draw_Ball(200, 700, 50, snekColor);
}
function playGame() {
draw_Ball(200, 700, 50, snekColor);
draw_Ball(400, 700, 50, snekColor);
draw_Ball(300, 500, 50, snekColor);
}
function gameOver() {
}
//this function was stolen from stack overflow
function showImage(width, height, image_source, alt_text) {
var img = document.createElement("img");
img.src = image_source;
img.width = width;
img.height = height;
img.alt = alt_text;
}
function draw_Ball(bx, by, size, ballColor) {
ctx.beginPath();
ctx.arc(bx, by, size, 0, (Math.PI * 2));
ctx.fillStyle = ballColor;
ctx.fill();
ctx.strokeStyle = "#000000";
ctx.stroke();
ctx.closePath();
}
//This next function was taken from stack overflow
function roundRect(x, y, width, height, radius, stroke, fill, color) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
if (stroke) {
ctx.stroke();
}
if (fill) {
ctx.fill();
}
ctx.closePath();
return;
}
And, for good measure, my HTML and CSS files:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - Portfolio</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body class="background_gradient">
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark dark-bg border-bottom box_shadow mb-0">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Portfolio</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<!--
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
-->
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Resume">Resume</a>
</li>
<!----
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Art3D">3D Art</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Art2D">2D Art</a>
</li>
<!---->
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Snake">Snake</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="CodeExamples">Code Examples</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Ballad">Ballad of the Masked Bandits</a>
</li>
<!--
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="DataBaseHub">Database Hub</a>
</li>
--->
<!--
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Unavailable">???</a>
</li>
-->
<!--Temporary Links-->
</ul>
</div>
</div>
</nav>
</header>
<div class="container-fluid" id="MainDiv">
<main role="main" class="pb-0" style="width:100%">
<!--Where the other code goes-->
#{
ViewData["Title"] = "Snake Game";
}
<div class="container-fluid purple_gradient text-center">
<h1>Snake Game</h1>
</div>
<div class="buffer"></div>
<div class="container">
<div class="fancy_text_box">
<div class="container buffer">
<div class="ghostly_text_box text-center">
<h1>By the power of Javascript, here is a playable snake game.</h1>
<div class="buffer"></div>
<h1 id="fiddleText">Give it a moment to load.</h1>
</div>
<div class="buffer"></div>
<div class="ghostly_text_box text-center">
<canvas onload="draw()" class="simple_text_box" id="SnekGamCanvas" width="1000" height="1000"></canvas>
</div>
</div>
</div>
<div class="text-center">
<div class="buffer"></div>
<a class="button glo_button big_r_button big_text" asp-area="" asp-controller="Home" asp-action="Index">Back to Home</a>
<div class="buffer"></div>
</div>
<!--The code be here but if you are reading this you probably already knew that-->
<script src="~/js/Snake.js"></script>
</div>
</main>
</div>
<footer class="border-top footer dark-bg text-light">
<div class="container">
© 2021 - Portfolio - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script src="../jsc3d-master/jsc3d/jsc3d.js"></script>
#RenderSection("Scripts", required: false)
</body>
</html>
...
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
}
/* Provide sufficient contrast against white background */
a {
color: #0366d6;
}
.btn-primary {
color: #fff;
background-image: linear-gradient(30deg, #b6e2dd, #2a5efe);
border-color: #1861ac;
}
/*Link colors*/
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
/* Sticky footer styles
-------------------------------------------------- */
html {
font-size: 14px;
}
#media (min-width: 768px) {
html {
font-size: 16px;
}
}
.border-top {
border-top: 1px solid #e5e5e5;
}
.border-bottom {
border-bottom: 1px solid #e5e5e5;
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}
button.accept-policy {
font-size: 1rem;
line-height: inherit;
}
/* Sticky footer styles
-------------------------------------------------- */
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 60px;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px; /* Vertically center the text there */
}
/* My Stuff
--------------------------------------------------------------------------
--------------------------------------------------------------------------
--------------------------------------------------------------------------
*/
/*This gives me more control over the exact dark background color*/
.dark-bg
{
background-color: #161631;
}
.purple_gradient
{
/*The image used*/
background-image: linear-gradient(#4b1ac4, #fff);
height:100%;
width:100%;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.test_box_blue
{
/* A container with a solid color and an outline */
background-color: #2d1eb2;
width: 100%;
height: 100%;
margin: 0px;
}
.test_box
{
border:solid #000000;
}
#MainDiv
{
padding:0;
margin:0;
left:0;
top:0;
width:100%;
height:100%;
}
.tundra_backround
{
background-image: url('../images/Tundra_Fixed.png');
width:100%;
height:100%;
}
.white_space_box
{
height:50 px;
}
.background_gradient
{
background-image:linear-gradient(320deg, #fff, #96cbde);
}
.glo_button
{
min-width: 30%;
height: 20%;
border-radius: 25px;
padding: 20px;
margin: 10px;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
transition-duration: 0.4s;
border: 4px solid #000;
}
.big_r_button {
background-color: #a10000;
color: #fff;
}
.big_r_button:hover {
color: #fff;
background-color: #4e0505;
}
.big_b_button {
background-color: #080e9f;
color: #fff;
}
.big_b_button:hover {
color: #fff;
background-color: #161631;
}
.big_g_button {
background-color: #0a7727;
color: #fff;
}
.big_g_button:hover {
color: #fff;
background-color: #07340e;
}
.big_p_button {
background-color: #6f1cbf;
color: #fff;
}
.big_p_button:hover {
color: #fff;
background-color: #2a073e;
}
.buffer
{
padding: 20px;
}
.big_text
{
font-size: 60px;
font-family:'Times New Roman', Times, serif;
text-shadow: 2px 2px rgb(12 14 39 / 0.67);
}
.fancy_text_box{
background-image: linear-gradient(300deg, #ece1c4, #c99e69);
border-radius: 25px;
border: 4px solid #5d3c08;
}
.simple_text_box{
background-color: #fff;
border: 2px solid #000;
}
.ghostly_text_box{
background-color: rgb(255 255 255 / 0.60);
border-radius: 25px;
padding: 10px;
border: 3px solid #000;
}
.thick_border{
border: 4px solid #000;
}
.black_and_white_gradient{
background-image: linear-gradient(310deg, #fff, #000);
}
.red_border{
padding: 0px;
margin: 0px;
border: 4px solid #8f0000;
}
.model_box{
border: 4px solid #000;
background-color: #fff;
border-radius: 25px;
}
.image_box{
border: 4px solid #000;
background-color: #fff;
}
.chain_image_box {
border-top: 4px solid #000;
border-left: 4px solid #000;
border-right: 4px solid #000;
border-bottom: 0px;
background-color: #fff;
}
.margin_setter {
margin: 20px;
padding: 20px;
}
#model_display_1{
}
I apologize for asking such a simple question, but I don't know where to look to find an existing answer.
So, as I suspected, it was a simple syntax error.
Specifically, I wrote "getElementByID" instead of "getElementById". a capitalization error. (I also capitalized "clientX" and "clientY", which also broke stuff.)
I couldn't see it because I was using Visual Studio, and I couldn't find the output for the javascript. By copying the code and pasting it into JS Fiddle, I was able to actually see the errors being generated by the Javascript.
I guess that means that until I find a way to see javascript errors when running HTML code via Visual Studio, I will need to do some debugging via JS Fiddle.

Drag'n'drop: Element not staying at its original position when I click on it

I am writing my own Drag'n'drop functionality for one of my projects and I am running into an issue. All my "draggable" elements are inside a container with display:flex. On mousedown event on one of this elements I set the position to absolute so I would be able to set the left and top properties of the element when I am dragging. Here is what I am doing:
let container = document.querySelector("#big-container")
var dragging = false;
var draggedObject;
let shiftX=0;
let shiftY=0;
document.querySelectorAll(".draggable").forEach((draggable,index) => {
draggable.style.order = index;
draggable.draggable =false;
draggable.ondragstart = ()=>{return false}
draggable.addEventListener("mousedown",ev =>{
draggedObject = draggable;
shiftX = ev.offsetX+5;
shiftY = ev.offsetY+5;
draggable.style.position = "absolute";
draggable.style.left = (ev.clientX - shiftX) + 'px';
draggable.style.top = (ev.clientY - shiftY) + 'px';
dragging = true;
let placeholder = document.createElement("div");
placeholder.id = "placeholder";
placeholder.style.order = draggable.style.order;
container.appendChild(placeholder);
})
})
document.addEventListener("mousemove", ev =>{
if(dragging){
draggedObject.style.left = ev.clientX - shiftX + 'px';
draggedObject.style.top = ev.clientY - shiftY + 'px';
}
})
document.addEventListener("mouseup",ev =>{
if(dragging){
draggedObject.style.position = 'static'
let placeholder = document.querySelector("#placeholder");
container.removeChild(placeholder);
dragging = false
}
})
/* the :not(:last-of-type(div)) is there so the console doesn't get affected */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: black;
}
.draggable {
width: 90px;
height: 120px;
margin: 5px;
}
#placeholder {
width: 90px;
height: 120px;
margin: 5px;
background-color: rgba(0, 0, 0, 0.3);
border: dashed grey 5px;
}
<body draggable="false" ondragstart="return false;">
<div id = "big-container" style ="display: flex; background-color: rgb(76, 104, 95); width: 500px; height: 500px;">
<div style="background-color: rgb(204, 125, 111);" class="draggable"></div>
<div style="background-color: rgb(170, 214, 120);" class="draggable"></div>
<div style="background-color: rgb(129, 212, 167);" class="draggable"></div>
<div style="background-color: rgb(162, 137, 196);" class="draggable"></div>
</div>
</body>
What I am trying to achieve is that on mousedown the element should stay where it was and after that when I move my mouse to move the element as well.(the anchor point should be where I clicked the element)
I am doing shiftX = ev.offsetX+5; because I need to account for the element's margin.
The issue is when I click on a element(and don't move my mouse at all), you can see a little shift in the element's position. It is very minor(maybe 1 or 2px) and is not happening in all places(some zones in the element do not introduce this position shift)
Do you guys have any idea what might be causing it?
You can use getBoundingClientRect() to get the actual position.
let container = document.querySelector("#big-container");
var dragging = false;
var draggedObject;
let shiftX = 0;
let shiftY = 0;
document.querySelectorAll(".draggable").forEach((draggable, index) => {
draggable.style.order = index;
draggable.draggable = false;
draggable.ondragstart = () => {
return false;
};
draggable.addEventListener("mousedown", (ev) => {
draggedObject = draggable;
var x = draggable.getBoundingClientRect().top - 5;
var y = draggable.getBoundingClientRect().left - 5;
shiftX = ev.offsetX + 5;
shiftY = ev.offsetY + 5;
draggable.style.position = "absolute";
draggable.style.left = y + "px";
draggable.style.top = x + "px";
dragging = true;
let placeholder = document.createElement("div");
placeholder.id = "placeholder";
placeholder.style.order = draggable.style.order;
container.appendChild(placeholder);
});
});
document.addEventListener("mousemove", (ev) => {
if (dragging) {
draggedObject.style.left = ev.clientX - shiftX + "px";
draggedObject.style.top = ev.clientY - shiftY + "px";
}
});
document.addEventListener("mouseup", (ev) => {
if (dragging) {
draggedObject.style.position = "static";
let placeholder = document.querySelector("#placeholder");
container.removeChild(placeholder);
dragging = false;
}
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: black;
}
#big-container {
width: 500px;
height: 500px;
}
.draggable {
width: 90px;
height: 120px;
margin: 5px;
}
#placeholder {
width: 90px;
height: 120px;
margin: 5px;
background-color: rgba(0, 0, 0, 0.3);
border: dashed grey 5px;
}
<body draggable="false" ondragstart="return false;">
<div
id="big-container"
style="display: flex; background-color: rgb(76, 104, 95);"
>
<div
style="background-color: rgb(204, 125, 111);"
class="draggable"
></div>
<div
style="background-color: rgb(170, 214, 120);"
class="draggable"
></div>
<div
style="background-color: rgb(129, 212, 167);"
class="draggable"
></div>
<div
style="background-color: rgb(162, 137, 196);"
class="draggable"
></div>
</div>
</body>

How can I add undo/redo functionalities in html canvas

I'm facing a problem with my HTML canvas project when I want to add undo/redo functionality, the idea is to merge this solution:
How to display a Canvas in a Bootstrap Modal
with this one:
https://codepen.io/abidibo/pen/rmGBc
this is my HTML code (bootstrap modal by the way)
<div id="bodyChartModal" class="modal fade bd-example-modal-xl" tabindex="-1" role="dialog" aria-labelledby="myExtraLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="myExtraLargeModalLabel">Extra Large</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
</button>
</div>
<div class="modal-body">
<div class="all-body-chart-buttons">
<div>
<button id="btnDraw" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-pencil-alt" style="font-size: 40px; color: black;"></i></button>
<button id="btnEraser" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-eraser" style="font-size: 40px; color: black;"></i></button>
</div>
<div>
<button id="btnLargeWithLine" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-circle" style="font-size: 40px; color: black;"></i></button>
<button id="btnMediumWithLine" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-circle" style="font-size: 20px; color: black;"></i></button>
</div>
<div>
<button id="btnSmallWithLine" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-circle" style="font-size: 10px; color: black;"></i></button>
<button id="btnBlackColor" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-square" style="font-size: 40px; color: black;"></i></button>
</div>
<div>
<button id="btnRedColor" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-square" style="font-size: 40px; color: #9f3631;"></i></button>
<button id="btnBlueColor" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-square" style="font-size: 40px; color: #00c1ca;"></i></button>
</div>
<div>
<button id="btnUndo" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-undo" style="font-size: 40px; color: black;"></i></button>
<button id="btnRedo" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-redo" style="font-size: 40px; color: black;"></i></button>
</div>
<div>
<button id="btnClear" class="btn" style="width: 80px; height: 70px;"><i class="fas fa-times" style="font-size: 40px; color: black;"></i></button>
</div>
</div>
<div class="canvas-box">
<canvas id="myCanvas" width="750" height="480" style="border:1px solid #000000;"></canvas>
</div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal"><i class="flaticon-cancel-12"></i> Discard</button>
<button type="button" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
this is my CSS code
#myCanvas{
background: transparent;
}
.canvas-box {
float: right;
margin-right: 5%;
display: inline-block;
background: url("/images/body-chart-image.png");
background-size: cover;
}
.all-body-chart-buttons{
float: left;
}
And this is my Javascript code
<script>
class Signature {
constructor() {
this.redo_list = [];
this.undo_list = [];
this.img = new Image();
this.eraser = false;
this.color = "#000000";
this.sign = false;
this.begin_sign = false;
this.width_line = 5;
this.canvas = document.getElementById('myCanvas');
this.offsetLeft = this.canvas.offsetLeft;
this.offsetTop = this.canvas.offsetTop;
this.context = this.canvas.getContext('2d');
this.context.lineJoin = 'round';
this.context.lineCap = 'round';
this.whenMouseDown();
this.whenMouseUp();
this.whenMouseMove();
this.createSignature();
this.clearCanvas();
this.resetCanvas();
this.changeColorToRed();
this.changeColorToBlack();
this.changeColorToBlue();
this.changeWithLineToSmall();
this.changeWithLineToMedium();
this.changeWithLineToLarge();
this.erase();
this.draw();
this.undo();
this.redo();
this.undoEvent();
this.redoEvent();
}
updateMousePosition(mX, mY) {
let rect = this.canvas.getBoundingClientRect();
let scaleX = this.canvas.width / rect.width;
let scaleY = this.canvas.height / rect.height;
this.cursorX = (mX - rect.left) * scaleX;
this.cursorY = (mY - rect.top) * scaleY;
}
whenMouseDown() {
document.addEventListener("mousedown", ({
pageX,
pageY
}) => {
this.sign = true;
this.updateMousePosition(pageX, pageY);
this.context.beginPath();
this.context.moveTo(this.cursorX, this.cursorY);
this.context.lineTo(this.cursorX, this.cursorY);
this.context.strokeStyle = this.color;
this.context.lineWidth = this.width_line;
this.context.stroke();
})
}
whenMouseUp() {
document.addEventListener("mouseup", () => {
this.sign = false;
this.begin_sign = false;
})
}
whenMouseMove() {
this.canvas.addEventListener('mousemove', ({
pageX,
pageY
}) => {
if (this.sign) {
this.updateMousePosition(pageX, pageY);
this.createSignature();
}
})
}
createSignature() {
if (this.erazer){
this.context.globalCompositeOperation = 'destination-out';
}
else{
this.context.globalCompositeOperation = 'source-over';
}
if (!this.begin_sign) {
this.context.beginPath();
this.context.moveTo(this.cursorX, this.cursorY);
this.redo_list = [];
this.undo_list.push(this.canvas.toDataURL());
this.begin_sign = true;
} else {
this.context.lineTo(this.cursorX, this.cursorY);
this.context.strokeStyle = this.color;
this.context.lineWidth = this.width_line;
this.context.stroke();
}
}
clearCanvas() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
changeColorToRed() {
document.getElementById("btnRedColor").addEventListener("click", () => {
this.color = "#9f3631";
})
}
changeColorToBlack() {
document.getElementById("btnBlackColor").addEventListener("click", () => {
this.color = "#000000";
})
}
changeColorToBlue() {
document.getElementById("btnBlueColor").addEventListener("click", () => {
this.color = "#00c1ca";
})
}
changeWithLineToSmall(){
document.getElementById("btnSmallWithLine").addEventListener("click", () => {
this.width_line = 5;
})
}
changeWithLineToMedium(){
document.getElementById("btnMediumWithLine").addEventListener("click", () => {
this.width_line = 10;
})
}
changeWithLineToLarge(){
document.getElementById("btnLargeWithLine").addEventListener("click", () => {
this.width_line = 20;
})
}
erase(){
document.getElementById("btnEraser").addEventListener("click", () => {
this.erazer = true;
})
}
draw(){
document.getElementById("btnDraw").addEventListener("click", () => {
this.erazer = false;
this.width_line = 5;
})
}
resetCanvas() {
document.getElementById("btnClear").addEventListener("click", () => {
this.context.globalCompositeOperation = 'source-over';
this.erazer = false;
this.clearCanvas();
})
}
undo(){
if (this.undo_list.length){
this.redo_list.push(this.canvas.toDataURL());
var restore_state = this.undo_list;
var img = this.img.src = restore_state;
var width = this.canvas.width;
var height = this.canvas.height;
img.onload = function() {
document.getElementById('myCanvas').getContext('2d').clearRect(0, 0, width, height);
document.getElementById('myCanvas').getContext('2d').drawImage(img, 0, 0, width, height, 0, 0, width, height);
}
}
}
redo(){
if(this.redo_list.length){
this.undo_list.push(this.canvas.toDataURL());
var restore_state = this.redo_list;
var img = this.img.src = restore_state;
var width = this.canvas.width;
var height = this.canvas.height;
img.onload = function() {
document.getElementById('myCanvas').getContext('2d').clearRect(0, 0, width, height);
document.getElementById('myCanvas').getContext('2d').drawImage(img, 0, 0, width, height, 0, 0, width, height);
}
}
}
undoEvent() {
document.getElementById("btnUndo").addEventListener("click", () => {
this.undo();
})
}
redoEvent() {
document.getElementById("btnRedo").addEventListener("click", () => {
this.redo();
})
}
}
document.addEventListener("DOMContentLoaded", event => {
new Signature();
});
</script>
All the functionalities working fine except undo and redo

How to change "mode" when adding a specific type of object?

I'm using fabricjs 1.7.20 and have "select" and "draw" modes. How can I make it so that when I add text (with the button, while still in draw mode) it sets the mode to the select mode so that I can edit the text object immediately?
var canvas = new fabric.Canvas("c", {
backgroundColor: "#fff"
});
canvas.setHeight(300);
canvas.setWidth(300);
// Add text
function Addtext() {
var text = new fabric.IText("Tap & type", {
fontSize: 30,
top: 10,
left: 10,
width: 200,
height: 200,
textAlign: "center"
});
canvas.add(text);
canvas.setActiveObject(text);
}
// Modes
$("#select").click(function() {
canvas.isDrawingMode = false;
});
$("#draw").click(function() {
canvas.isDrawingMode = true;
});
canvas {
border: 1px solid #dddddd;
margin-top: 10px;
border-radius: 3px;
}
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<button onclick="Addtext()">Add Text</button>
<button id="draw">Draw Mode</button>
<canvas id="c"></canvas>
You can use enterEditing() from text methods, and also a selectAll() if you need to.
var canvas = new fabric.Canvas("c", {
backgroundColor: "#fff"
});
canvas.setHeight(300);
canvas.setWidth(300);
// Add text
function Addtext() {
var text = new fabric.IText("Tap & type", {
fontSize: 30,
top: 10,
left: 10,
width: 200,
height: 200,
textAlign: "center"
});
canvas.add(text);
canvas.setActiveObject(text);
text.enterEditing();
text.selectAll();
text.renderCursorOrSelection(); // or canvas.renderAll();
canvas.isDrawingMode = false;
}
// Modes
$("#select").click(function() {
canvas.isDrawingMode = false;
});
$("#draw").click(function() {
canvas.isDrawingMode = true;
});
canvas {
border: 1px solid #dddddd;
margin-top: 10px;
border-radius: 3px;
}
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<button onclick="Addtext()">Add Text</button>
<button id="draw">Draw Mode</button>
<canvas id="c"></canvas>

I want to take a screenshot of a div using Html2canvas

I am using the Html2canvas in order to take a screenshot of a div and display it in a new window. Here is my javascript function
function capture() {
html2canvas(document.getElementById('screenshot'), {
onrendered: function(canvas) {
var img = canvas.toDataURL("image/png");
window.open(img);
}}
);
}
The problem with this code is that it captures only half of the div as the following image shows:
I changed the ID of the element to be captured to 'table' so that I can screenshot the table only. But it seems like the screenshot takes only half of the targeted div (in terms of height).
Now when I select the whole body:
function capture() {
html2canvas(document.body, {
onrendered: function(canvas) {
var img = canvas.toDataURL();
window.open(img);
}
});
the result is as follows:
I made a function that can adjust the output by 1 to 200% of the window height and width. To get your part working, I did the following:
....
html2canvas(document.body, {
onrendered: function(canvas) {
document.body.appendChild(canvas);
canvas.id = "ctx"
var ctx = document.getElementById('ctx');
var img = ctx.toDataURL("image/png");
window.open(img);
},....
Snippet
function hide(ele) {
var ele = document.querySelector(ele);
ele.style.display = 'none';
setTimeout(function() {
ele.style.display = 'block'
}, 1000);
return false;
}
function screenShot() {
var w = document.getElementById('w');
var h = document.getElementById('h');
var winW = window.outerWidth;
var winH = window.outerHeight;
var width = parseFloat(w.value * winW * .01);
var height = parseFloat(h.value * winH * .01);
html2canvas(document.body, {
onrendered: function(canvas) {
document.body.appendChild(canvas);
canvas.id = "ctx"
var ctx = document.getElementById('ctx');
var img = ctx.toDataURL("image/png");
window.open(img);
},
width: width,
height: height
});
return false;
}
main {
position: relative;
width: 100vw;
height: 100vh;
overflow: auto;
}
#panel {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 50px;
z-index: 1;
}
fieldset {
border-radius: 10px;
background: hsla(120, 100%, 50%, .5)
}
legend {
font: small-caps 700 20px/1.4'Source Code Pro';
}
section {
height: 33vh;
width: 100vw;
}
#sec1 {
background: red;
border: 1px solid blue;
}
#sec2 {
background: white;
border: 1px solid red;
}
#sec3 {
background: blue;
border: 1px solid white;
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>34571073</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js"></script>
</head>
<body>
<header id="panel">
<fieldset>
<legend>HTML2Canvas</legend>
<label for="w">Width.:
<input id="w" type="number" min="1" max="200" />%</label>
<br/>
<label for="h">Height:
<input id="h" type="number" min="1" max="200" />%</label>
<br/>
<input type="button" value="Capture" onclick="hide('#panel'); screenShot();" />
</fieldset>
</header>
<main>
<section id="sec1"></section>
<section id="sec2"></section>
<section id="sec3"></section>
</main>
</body>
</html>

Categories

Resources