How do I get the code in jsfiddle to work in my Visual Studio Code? - javascript

const canvasEle = document.getElementById('drawing-container');
const canvasPad = document.getElementById('pad');
const toolbar = document.getElementById('toolbar');
const context = canvasEle.getContext('2d');
const padContext = canvasPad.getContext('2d');
const canvasOffsetX = canvas.offsetLeft;
const canvasOffsetY = canvas.offsetTop;
canvas.width = window.innerWidth - canvasOffsetX;
canvas.height = window.innerHeight - canvasOffsetY;
let startPosition = {
x: 0,
y: 0
};
let lineCoordinates = {
x: 0,
y: 0
};
let isDrawStart = false;
const getClientOffset = (event) => {
const {
pageX,
pageY
} = event.touches ? event.touches[0] : event;
const x = pageX - canvasPad.offsetLeft;
const y = pageY - canvasPad.offsetTop;
return {
x,
y
}
}
toolbar.addEventListener('click', e => {
if (e.target.id === 'clear') {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
});
toolbar.addEventListener('change', e => {
if(e.target.id === 'stroke') {
ctx.strokeStyle = e.target.value;
}
if(e.target.id === 'lineWidth') {
lineWidth = e.target.value;
}
});
const drawLine = (ctx) => {
if (!isDrawStart) {
return;
}
ctx.beginPath();
ctx.moveTo(startPosition.x, startPosition.y);
ctx.lineTo(lineCoordinates.x, lineCoordinates.y);
ctx.stroke();
}
const mouseDownListener = (event) => {
startPosition = getClientOffset(event);
isDrawStart = true;
}
const mouseMoveListener = (event) => {
if (!isDrawStart) return;
lineCoordinates = getClientOffset(event);
clearCanvas(padContext);
drawLine(padContext);
}
const mouseupListener = (event) => {
clearCanvas(padContext);
drawLine(context);
isDrawStart = false;
}
const clearCanvas = (ctx) => {
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
}
canvasPad.addEventListener('mousedown', mouseDownListener);
canvasPad.addEventListener('mousemove', mouseMoveListener);
canvasPad.addEventListener('mouseup', mouseupListener);
body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
color: white;
}
h1 {
background: #7F7FD5;
background: -webkit-linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5);
background: linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.cnv-wrapper {
height: 100%;
display: flex;
}
.pad {
height: 100%;
display: flex;
border: 4px solid #333;
}
.container {
height: 100%;
display: flex;
}
#toolbar {
display: flex;
flex-direction: column;
padding: 5px;
width: 70px;
background-color: #202020;
}
#toolbar * {
margin-bottom: 6px;
}
#toolbar label {
font-size: 12px;
}
#toolbar input {
width: 100%;
}
#toolbar button {
background-color: #1565c0;
border: none;
border-radius: 4px;
color:white;
padding: 2px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content = "IE = edge">
<meta name = "viewport" content = "width = device - width, initial - scale = 0.1">
<link rel = "stylesheet" href = "styles.css">
<title> Pipe Illustrator </title>
</head>
<body>
<section class = "container">
<div id = "toolbar">
<h1>Draw.</h1>
<label for="stroke">Stroke</label>
<input id="stroke" name='stroke' type="color">
<label for="lineWidth">Line Width</label>
<input id="lineWidth" name='lineWidth' type="number" value="5">
<button id="clear">Clear</button>
</div>
<div class = "drawing-container">
<canvas id = "drawing-container"></canvas>
</div>
<div class = "cnv-wrapper">
<canvas id = "cnv-wrapper"></canvas>
</div>
</section>
<script src = "./index.js"></script>
</body>
</html>
The project is to make a simple line drawer which makes allows me to draw fixed straight lines without the previous line being removed. The code written below is exactly what I need and was provided by another user from a question I asked previously about making it as my code wouldn't allow for the previous line to remain when drawing a new one.
This is the code below which is in jsfiddle, when I copy and paste it into my Visual studio code, I don't get the same output as I would in jsfiddle, the canvas doesn't appear nor does it allow anything to be drawn. Am I missing something ?
Right so this is the code i have written in VSC. It isn't entirely what was in the jsfiddle, i tried to integrate some other functions from another paint project i did. I was trying to add a toolbar for line colour and width. I think the way i have written it is contradicting it all got quite messy and was quite a fail. These are projects im doing to learn code as i am still a beginner to coding. Thank you for your help and input.
const canvasEle = document.querySelector('.draw-container');
const canvasPad = document.querySelector('.pad');
const context = canvasEle.getContext('2d');
const padContext = canvasPad.getContext('2d');
let startPosition = {
x: 0,
y: 0
};
let lineCoordinates = {
x: 0,
y: 0
};
let isDrawStart = false;
const getClientOffset = (event) => {
const {
pageX,
pageY
} = event.touches ? event.touches[0] : event;
const x = pageX - canvasPad.offsetLeft;
const y = pageY - canvasPad.offsetTop;
return {
x,
y
}
}
const drawLine = (ctx) => {
if (!isDrawStart) {
return;
}
ctx.beginPath();
ctx.moveTo(startPosition.x, startPosition.y);
ctx.lineTo(lineCoordinates.x, lineCoordinates.y);
ctx.stroke();
}
const mouseDownListener = (event) => {
startPosition = getClientOffset(event);
isDrawStart = true;
}
const mouseMoveListener = (event) => {
if (!isDrawStart) return;
lineCoordinates = getClientOffset(event);
clearCanvas(padContext);
drawLine(padContext);
}
const mouseupListener = (event) => {
clearCanvas(padContext);
drawLine(context);
isDrawStart = false;
}
const clearCanvas = (ctx) => {
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
}
canvasPad.addEventListener('mousedown', mouseDownListener);
canvasPad.addEventListener('mousemove', mouseMoveListener);
canvasPad.addEventListener('mouseup', mouseupListener);
body {
background-color: #ccc;
}
.cnv-wrapper {
position: relative;
}
.pad {
position: absolute;
top: 0px;
left: 0px;
border: 1px solid #333;
}
.draw-container {
border: 1px solid #333;
}
<div class="cnv-wrapper">
<canvas class="draw-container" width="500" height="500"></canvas>
<canvas class="pad" width="500" height="500"></canvas>
</div>

From comments where I advise:
You can't just copy and paste code [from fiddle] without also using the appropriate html tags. Your CSS needs to go in style tags. Your scripts need to go in script tags. The dom elements, e.g. the "canvas" needs to go in the body tag. Etc. ... You may also need to affix the appropriate "doctype" and you may need to trigger the scripts to run on document load.
As an example, I tried the pasted code using the above advice on my own computer and it worked.
I'll show the complete source and then followup with a runnable version here on SO. Note that the runnable version uses SO's utility for such and as such you won't see all the various tags I mentioned, but the functionality remains the same just as with the "fiddle".
Corrected "pasted" source showing all the relevant tags you need to create:
<!doctype html> <!-- Add appropriate doctype -->
<html>
<head>
<style>
/* Paste the CSS in a style tag */
body {
background-color: #ccc;
}
.cnv-wrapper {
position: relative;
}
.pad {
position: absolute;
top: 0px;
left: 0px;
border: 1px solid #333;
}
.draw-container {
border: 1px solid #333;
}
</style>
</head>
<body>
<div class="cnv-wrapper">
<canvas class="draw-container" width="500" height="500"></canvas>
<canvas class="pad" width="500" height="500"></canvas>
</div>
<script>
// Paste your init scripts into the onload event to ensure they get ran after the canvas is created
window.onload = function() {
const canvasEle = document.querySelector('.draw-container');
const canvasPad = document.querySelector('.pad');
const context = canvasEle.getContext('2d');
const padContext = canvasPad.getContext('2d');
let startPosition = {
x: 0,
y: 0
};
let lineCoordinates = {
x: 0,
y: 0
};
let isDrawStart = false;
const getClientOffset = (event) => {
const {
pageX,
pageY
} = event.touches ? event.touches[0] : event;
const x = pageX - canvasPad.offsetLeft;
const y = pageY - canvasPad.offsetTop;
return {
x,
y
}
}
const drawLine = (ctx) => {
if (!isDrawStart) {
return;
}
ctx.beginPath();
ctx.moveTo(startPosition.x, startPosition.y);
ctx.lineTo(lineCoordinates.x, lineCoordinates.y);
ctx.stroke();
}
const mouseDownListener = (event) => {
startPosition = getClientOffset(event);
isDrawStart = true;
}
const mouseMoveListener = (event) => {
if (!isDrawStart) return;
lineCoordinates = getClientOffset(event);
clearCanvas(padContext);
drawLine(padContext);
}
const mouseupListener = (event) => {
clearCanvas(padContext);
drawLine(context);
isDrawStart = false;
}
const clearCanvas = (ctx) => {
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
}
canvasPad.addEventListener('mousedown', mouseDownListener);
canvasPad.addEventListener('mousemove', mouseMoveListener);
canvasPad.addEventListener('mouseup', mouseupListener);
}
</script>
</body>
</html>
Now on to demonstrating this code works now here on SO.
Note that SO's intepreter of code also (like "fiddle") doesn't need the tags mentioned that would be needed when you copy and paste into your own editor. Therefore I re-mention where the pasted code goes in code comments.
// Your scripts will go in a <script> tag
// Use an onload event handler to ensure they get ran after the canvas is created
window.onload = function() {
const canvasEle = document.querySelector('.draw-container');
const canvasPad = document.querySelector('.pad');
const context = canvasEle.getContext('2d');
const padContext = canvasPad.getContext('2d');
let startPosition = {
x: 0,
y: 0
};
let lineCoordinates = {
x: 0,
y: 0
};
let isDrawStart = false;
const getClientOffset = (event) => {
const {
pageX,
pageY
} = event.touches ? event.touches[0] : event;
const x = pageX - canvasPad.offsetLeft;
const y = pageY - canvasPad.offsetTop;
return {
x,
y
}
}
const drawLine = (ctx) => {
if (!isDrawStart) {
return;
}
ctx.beginPath();
ctx.moveTo(startPosition.x, startPosition.y);
ctx.lineTo(lineCoordinates.x, lineCoordinates.y);
ctx.stroke();
}
const mouseDownListener = (event) => {
startPosition = getClientOffset(event);
isDrawStart = true;
}
const mouseMoveListener = (event) => {
if (!isDrawStart) return;
lineCoordinates = getClientOffset(event);
clearCanvas(padContext);
drawLine(padContext);
}
const mouseupListener = (event) => {
clearCanvas(padContext);
drawLine(context);
isDrawStart = false;
}
const clearCanvas = (ctx) => {
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
}
canvasPad.addEventListener('mousedown', mouseDownListener);
canvasPad.addEventListener('mousemove', mouseMoveListener);
canvasPad.addEventListener('mouseup', mouseupListener);
}
/* Your CSS would go in a <style> tag */
body {
background-color: #ccc;
}
.cnv-wrapper {
position: relative;
}
.pad {
position: absolute;
top: 0px;
left: 0px;
border: 1px solid #333;
}
.draw-container {
border: 1px solid #333;
}
<!-- Your HTML would go in the <body> tag -->
<div class="cnv-wrapper">
<canvas class="draw-container" width="500" height="500"></canvas>
<canvas class="pad" width="500" height="500"></canvas>
</div>

Related

How to make canvas lines visible when dragging (no libraries, only vanilla JS, React.JS if necessary.)

I'd like to add lines by two clicks, when moving the mouse the line should be visible. When click left mouse button again the line should be added. Only left button should draw.
How should I change my code to do this? (for now it allows to create lines,
but they aren't visible before mouseup).
Any help is appreciated! Thanks!
const canvasEl = document.getElementById('drawContainer')
canvasEl.style.position = 'absolute'
canvasEl.style.top = '12%'
canvasEl.style.left = '32%'
var lines = [], line;
const context = canvasEl.getContext('2d')
const collapseLinesBtn = document.getElementById('collapse_lines')
let startPosition = {x: 0, y: 0}
let lineCoordinates = {x: 0, y: 0}
let isDrawStart = false
const getClientOffset = (event) => {
const {pageX, pageY} = event.clicks ? event.clicks[0] : event
const x = pageX - canvasEl.offsetLeft
const y = pageY - canvasEl.offsetTop
return { x, y }
}
const initialDraw = () => {
context.beginPath() //allows to prevent previously created lines from delete
context.moveTo(startPosition.x, startPosition.y)
context.lineTo(lineCoordinates.x, lineCoordinates.y)
context.stroke()
line = [];
line.push([lineCoordinates.x, lineCoordinates.y]);
console.log(line)
}
const mouseDownListener = (e) => {
startPosition = getClientOffset(e)
//isDrawStart = true // isDrawStart = true + clearCanvas() + initialDraw() from const mouseMoveListener = one visible line when dragging + coordinates
context.beginPath();
context.moveTo(e.offsetX, e.offsetY);
context.lineTo(e.offsetX, e.offsetY);
}
const mouseMoveListener = (event) => {
if(!isDrawStart)
return
lineCoordinates = getClientOffset(event)
//clearCanvas()
//initialDraw()
//initialDraw(!isDrawStart())
}
const mouseUpListener = (e) => {
isDrawStart = false
context.lineTo(e.offsetX, e.offsetY);
context.stroke();
}
const clearCanvas = () => {
context.clearRect(0, 0, canvasEl.width, canvasEl.height)
}
canvasEl.addEventListener('mousedown', mouseDownListener)
canvasEl.addEventListener('mousemove', mouseMoveListener)
canvasEl.addEventListener('mouseup', mouseUpListener)
collapseLinesBtn.addEventListener('click', function clear() {
context.clearRect(0, 0, window.innerWidth, window.innerHeight);
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#collapse_lines {
position: absolute;
bottom: 75px;
left: 47%;
padding: 10px 25px;
font-size: 1rem;
}
</style>
<title>Test Task</title>
</head>
<body>
<div id="main_container">
<canvas id="drawContainer" width="700" height="700" style="border: 1px solid rgb(10, 10, 10)" ></canvas>
<button id="collapse_lines">collapse lines</button>
</div>
<script src="./app.js"></script>
</body>
</html>
In your mouseMoveListener just do something similar as you do in your mouseUpListener, without setting isDrawStart = false:
const mouseMoveListener = (event) => {
if(!isDrawStart)
return
lineCoordinates = getClientOffset(event)
// Clear the canvas each frame
clearCanvas()
// Similar to mouseUpListener
context.lineTo(lineCoordinates.x, lineCoordinates.y);
context.stroke();
}

How to draw via mouse-click without using the canvas-element

I am trying to create an "Etch-A-Sketch"-program, which should let the user draw only by clicking or holding the mouse-button. How can I realize that in JavaScript?
Somehow after the user chooses a color via clicking on the color-button, the color is already drawn as soon as the mouse cursor enters the drawing area (div class="container").
I've tried several functions, but it's still not working as expected...
Could someone please provide a hint?
"use strict";
const divContainer = document.querySelector(".container");
const btnsContainer = document.querySelector(".buttons");
const btnBlack = document.createElement("button");
const btnGreyScale = document.createElement("button");
const btnRgb = document.createElement("button");
const btnErase = document.createElement("button");
const btnShake = document.createElement("button");
function createGrid(col, rows) {
for(let i = 0; i < (col * rows); i++) {
const div = document.createElement("div");
divContainer.style.gridTemplateColumns = `repeat(${col}, 1fr)`;
divContainer.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
divContainer.appendChild(div).classList.add("box");
}
}
createGrid(16,16)
let isDrawing = false;
window.addEventListener("mousedown", () => {
isDrawing = true;
});
window.addEventListener("mouseup", () => {
isDrawing = false;
});
function paintBlack() {
const boxes = divContainer.querySelectorAll(".box");
btnBlack.textContent = "Black";
btnBlack.addEventListener("click", function () {
boxes.forEach(box => box.addEventListener("mouseover", function () {
this.style.background = "#000";
}))
})
btnsContainer.appendChild(btnBlack).classList.add("btn");
}
paintBlack();
function paintGreyScale() {
const boxes = divContainer.querySelectorAll(".box");
btnGreyScale.textContent = "Grey";
btnGreyScale.addEventListener("click", function () {
boxes.forEach(box => box.addEventListener("mouseover", function () {
let randNum = Math.floor(Math.random() * 256);
let grayScale = `rgb(${randNum},${randNum},${randNum})`;
box.style.background = grayScale;
}))
})
btnsContainer.appendChild(btnGreyScale).classList.add("btn");
}
paintGreyScale();
function paintRgb() {
const boxes = divContainer.querySelectorAll(".box");
btnRgb.textContent = "Rainbow";
btnRgb.addEventListener("click", function () {
boxes.forEach(box => box.addEventListener("mouseover", function () {
let r = Math.floor(Math.random() * 256);
let g = Math.floor(Math.random() * 256);
let b = Math.floor(Math.random() * 256);
const rgb = `rgb(${r},${g},${b})`;
box.style.background = rgb;
}))
})
btnsContainer.appendChild(btnRgb).classList.add("btn");
}
paintRgb();
function erase() {
const boxes = divContainer.querySelectorAll(".box");
btnErase.textContent = "Erase";
btnErase.addEventListener("click", function () {
boxes.forEach(box => box.addEventListener("mouseover", function () {
this.style.background = "#FFF";
}))
})
btnsContainer.appendChild(btnErase).classList.add("btn");
}
erase();
function clearCanvas() {
const boxes = divContainer.querySelectorAll(".box");
btnShake.textContent = "Shake it!";
btnShake.addEventListener("click", function () {
boxes.forEach(box => box.style.backgroundColor = "#FFF");
})
btnsContainer.appendChild(btnShake).classList.add("shake");
}
clearCanvas();
btnShake.addEventListener("click", clearCanvas);
*,
*::before,
*::after {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html {
font-size: 16px;
}
body {
background: linear-gradient(to bottom, #1488CC, #2B32B2);
color: #FFF;
line-height: 1.5;
height: 100vh;
}
#wrapper {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
text-align: center;
}
.container {
width: 500px;
height: 500px;
display: grid;
background-color: #FFF;
box-shadow: 0 0 10px;
}
.box {
border: .5px solid #808080;
}
.shake {
animation: shake .5s linear 1;
}
#keyframes shake {
10%,
90% {
transform: translate3d(-1px, 0, 0);
}
20%,
80% {
transform: translate3d(2px, 0, 0);
}
30%,
50%,
70% {
transform: translate3d(-4px, 0, 0);
}
40%,
60% {
transform: translate3d(4px, 0, 0);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Etch-A-Sketch</title>
</head>
<body>
<div id="wrapper">
<main>
<div class="container"></div>
<div class="buttons"></div>
</main>
</div>
<script src="etchAsketch.js"></script>
</body>
</html>
The mousedown event
window.addEventListener("mousedown", () => {
isDrawing = true;
});
sets isDrawing to true, and mouseup event to false, but you never use this variable to check whether the color should be drawn.
Solution: for each statement you have that's setting the background color of a square (except for clearCanvas), wrap it in an if statement checking if the user isDrawing:
if (isDrawing){this.style.background = "#000";} //black
if (isDrawing){this.style.background = grayScale;} //gray
if (isDrawing){this.style.background = rgb;} // rainbow
if (isDrawing){this.style.background = "#FFF";} // erase
boxes.forEach(box => box.style.backgroundColor = "#FFF");
}) //leave clearCanvas as it is

How to fix Div element "jump" on drag?

The dragging works but the bug is that when I drag the element somehow "jumps" and does not flow with the mouse. See it in the code. Don't worry about removing event listeners, I will add them as soon as this works.
I have an issue on a draggable "div" element. I've searched many answers before I posted this question but nothing seems to be the solution(or maybe I am not understanding the problem really well).
Thank you!
const hotspot = document.getElementsByClassName("hotspot")[0];
const container = document.getElementsByClassName("container")[0];
let containerRect = container.getBoundingClientRect();
let hsRect = hotspot.getBoundingClientRect();
let relMouse = { x: 0, y: 0 };
let windowMouse = { x: 0, y: 0 };
let isUserIntercating = false;
const handlePointerUp = (e) => {
isUserIntercating = false;
};
const handlePointerDown = (e) => {
isUserIntercating = true;
hsRect = hotspot.getBoundingClientRect();
relMouse = { x: e.pageX - hsRect.x, y: e.pageY - hsRect.y };
window.addEventListener("pointerup", handlePointerUp, false);
};
const handlePointerMove = (e) => {
hsRect = hotspot.getBoundingClientRect();
containerRect = container.getBoundingClientRect();
windowMouse = { x: e.clientX - relMouse.x, y: e.clientY - relMouse.y };
};
const update = (t) => {
requestAnimationFrame(update);
if (isUserIntercating) {
hotspot.style.transform = `translate(${
windowMouse.x - containerRect.x
}px,0px)`;
}
};
update();
hotspot.addEventListener("pointerdown", handlePointerDown, false);
window.addEventListener("pointermove", handlePointerMove, false);
body {
font-family: sans-serif;
margin: 0;
}
.container {
padding: 0;
margin: 50px;
max-width: 600px;
min-height: 600px;
background-color: blanchedalmond;
}
.hotspot {
/* position: absolute; */
background-color: aqua;
/* transform: translate(100px, 100px); */
min-height: 100px;
max-width: 100px;
z-index: 200;
}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div class="container">
<div class="hotspot"></div>
</div>
<script src="src/index.js"></script>
</body>
</html>
Try like this:
const hotspot = document.getElementsByClassName("hotspot")[0];
const container = document.getElementsByClassName("container")[0];
let containerRect = container.getBoundingClientRect();
let hsRect = hotspot.getBoundingClientRect();
let relMouse = { x: 0, y: 0 };
let windowMouse = { x: 0, y: 0 };
let isUserIntercating = false;
const handlePointerUp = (e) => {
isUserIntercating = false;
};
const handlePointerDown = (e) => {
isUserIntercating = true;
hsRect = hotspot.getBoundingClientRect();
relMouse = { x: e.pageX - hsRect.x, y: e.pageY - hsRect.y };
window.addEventListener("pointerup", handlePointerUp, false);
};
const handlePointerMove = (e) => {
hsRect = hotspot.getBoundingClientRect();
containerRect = container.getBoundingClientRect();
windowMouse = { x: e.clientX - relMouse.x, y: e.clientY - relMouse.y };
requestAnimationFrame(update);
};
const update = (t) => {
if (isUserIntercating) {
hotspot.style.transform = `translate(${
windowMouse.x - containerRect.x
}px,0px)`;
}
};
hotspot.addEventListener("pointerdown", handlePointerDown, false);
window.addEventListener("pointermove", handlePointerMove, false);
body {
font-family: sans-serif;
margin: 0;
}
.container {
padding: 0;
margin: 50px;
max-width: 600px;
min-height: 600px;
background-color: blanchedalmond;
}
.hotspot {
/* position: absolute; */
background-color: aqua;
/* transform: translate(100px, 100px); */
min-height: 100px;
max-width: 100px;
z-index: 200;
}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div class="container">
<div class="hotspot"></div>
</div>
<script src="src/index.js"></script>
</body>
</html>
The issue seemed to be that the update function kept calling itself all the time, which is not really ideal. The update should only be called in the handlePointerMove function (only change the hotspot position when the mouse moves).

how can I reuse the functions of my code javascript?

I wanted to make an effect similar to "click and hold" of this page, but with some changes, with svg forms, the point is that I did two functions that do what I wanted to do very well, but at the moment I introduced another svg form, the Data of the effect is transferred to the other, affecting the execution of the functions, the question is, how do I prevent this from happening?
Note: The best way to see what is happening is to let one of the two complete.
Here is an example of what I have programmed
of course I leave you all the code that I have been working
//Efect Drivers
class EffectValues {
constructor(count, time, initOffset, label) {
this.count = count;
this.time = time;
this.initOffset = initOffset;
this.label = label;
}
}
//Controlers
let counter; //it will be interval controller
let globalCount = 0;
//Call objects DOM
const loader = document.querySelector('.loader');
const circle = document.querySelector('.circle');
const svgText = document.querySelector('.svgText');
const textSvg = document.querySelector('.textSvg');
//Preloader svg
const startCircle = new EffectValues(0, 3, 1300, circle);
const showEffect = new EffectValues(0, 3, 500, svgText);
//Mouse events
// Circle
loader.addEventListener('mousedown', e => {
increase(e, startCircle);
});
loader.addEventListener('mouseup', e => {
decrease(e, startCircle);
});
// Text SVG
textSvg.addEventListener('mousedown', e => {
increase(e, showEffect);
});
textSvg.addEventListener('mouseup', e => {
decrease(e, showEffect);
});
//main functions
const increase = (e, { count, initOffset, time, label }) => {
let flag = true;
// console.log(flag);
clearInterval(counter);
while (e.type == 'mousedown') {
counter = setInterval(() => {
if (globalCount < initOffset) {
count = initOffset - globalCount;
label.style.strokeDashoffset = count;
globalCount++;
}
}, time);
break;
}
return flag;
};
const decrease = (e, { count, initOffset, time, label }) => {
let flag = true;
// console.log(flag);
clearInterval(counter);
while (e.type == 'mouseup') {
counter = setInterval(() => {
if (globalCount >= 0 && globalCount < initOffset) {
count = -globalCount + initOffset;
label.style.strokeDashoffset = count;
globalCount--;
} else {
flag = false;
}
}, time);
break;
}
return flag;
};
:root {
--dark: #2f3640;
--dark-light: #353b48;
--blue: #192a56;
--blue-dark: #273c75;
--cian: #0097e6;
--cian-light: #00a8ff;
--orange: #c23616;
--orange-light: #e84118;
}
* {
margin: 0;
padding: 0;
}
body {
min-height: 100vh;
background-color: var(--dark);
display: flex;
justify-content: center;
align-content: center;
}
.loader {
position: relative;
width: 50%;
height: 100vh;
}
.loader svg {
position: absolute;
width: 550px;
height: 550px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.loader svg circle {
width: 100%;
height: 100%;
fill: none;
stroke-width: 10;
stroke: var(--cian);
stroke-linecap: round;
transform: translate(5px, 5px);
stroke-dasharray: 1300;
stroke-dashoffset: 1300;
}
.textSvg {
position: relative;
width: 40%;
}
.textSvg svg text {
stroke: var(--orange-light);
fill: none;
stroke-width: 3;
stroke-dasharray: 500;
stroke-dashoffset: 500;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="styles.css" />
<title>Loader</title>
</head>
<body>
<div class="loader">
<svg>
<circle class="circle" cx="200" cy="200" r="200"></circle>
</svg>
</div>
<div class="textSvg">
<svg
xmlns="http://www.w3.org/2000/svg"
width="1413"
height="274"
viewBox="0 0 1413 274"
>
<text
class="svgText"
transform="translate(0 198)"
fill="#c6e0ee"
font-size="100"
font-family="MonotypeCorsiva, Monotype Corsiva"
>
<tspan x="0" y="0">David Figueroa</tspan>
</text>
</svg>
</div>
</body>
<script src="main.js" defer></script>
</html>
I have been looking for information but nothing has helped me.
Beforehand thank you very much
You can implement your requirements by moving global variables and functions inside the class.
Codepen here
//Efect Drivers
class EffectValues {
constructor(time, initOffset, label) {
this.time = time;
this.initOffset = initOffset;
this.label = label;
this.counter;
this.globalCount = 0;
}
increase(e) {
let flag = true;
// console.log(flag);
clearInterval(this.counter);
while (e.type == 'mousedown') {
this.counter = setInterval(() => {
if (this.globalCount < this.initOffset) {
const count = this.initOffset - this.globalCount;
this.label.style.strokeDashoffset = count;
this.globalCount++;
}
}, this.time);
break;
}
return flag;
};
decrease(e) {
let flag = true;
// console.log(flag);
clearInterval(this.counter);
while (e.type == 'mouseup') {
this.counter = setInterval(() => {
if (this.globalCount >= 0 && this.globalCount < this.initOffset) {
const count = -this.globalCount + this.initOffset;
this.label.style.strokeDashoffset = count;
this.globalCount--;
} else {
flag = false;
}
}, this.time);
break;
}
return flag;
};
}
//Call objects DOM
const loader = document.querySelector('.loader');
const circle = document.querySelector('.circle');
const svgText = document.querySelector('.svgText');
const textSvg = document.querySelector('.textSvg');
//Preloader svg
const startCircle = new EffectValues(3, 1300, circle);
const letterEffect = new EffectValues(3, 500, svgText);
//Mouse events
// Circle
loader.addEventListener('mousedown', e => {
startCircle.increase(e);
});
loader.addEventListener('mouseup', e => {
startCircle.decrease(e);
});
// Text SVG
textSvg.addEventListener('mousedown', e => {
letterEffect.increase(e);
});
textSvg.addEventListener('mouseup', e => {
letterEffect.decrease(e);
});

How to take a screenshot of specific part of webpage just like Firefox screenshot not using HTML canvas?

I need to have a cursor to drag and take screenshot of dragged area on HTML webpage. I tried using HTML canvas but it takes screenshot of specific div not the selected region on HTML webpage.
The new html2canvas version 1 has width, height, x and y options.
You can make use of these options to achieve a cropping feature the Firefox's Screenshot's way.
document.onmousedown = startDrag;
document.onmouseup = endDrag;
document.onmousemove = expandDrag;
var dragging = false,
dragStart = {
x: 0,
y: 0
},
dragEnd = {
x: 0,
y: 0
};
function updateDragger() {
dragger.classList.add('visible');
var s = dragger.style;
s.top = Math.min(dragStart.y, dragEnd.y) + 'px';
s.left = Math.min(dragStart.x, dragEnd.x) + 'px';
s.height = Math.abs(dragStart.y - dragEnd.y) + 'px';
s.width = Math.abs(dragStart.x - dragEnd.x) + 'px';
}
function startDrag(evt) {
evt.preventDefault();
dragging = true;
dragStart.x = dragEnd.x = evt.clientX;
dragStart.y = dragEnd.y = evt.clientY;
updateDragger();
}
function expandDrag(evt) {
if (!dragging) return;
dragEnd.x = evt.clientX;
dragEnd.y = evt.clientY;
updateDragger();
}
function endDrag(evt) {
dragging = false;
dragger.classList.remove('visible');
// here is the important part
html2canvas(document.body, {
width: Math.abs(dragStart.x - dragEnd.x),
height: Math.abs(dragStart.y - dragEnd.y),
x: Math.min(dragStart.x, dragEnd.x),
y: Math.min(dragStart.y, dragEnd.y)
})
.then(function(c) {
document.body.appendChild(c);
});
dragStart.x = dragStart.y = dragEnd.x = dragEnd.y = 0;
}
* {
user-select: none;
}
#dragger {
position: fixed;
background: rgba(0, 0, 0, .5);
border: 1px dashed white;
pointer-events: none;
display: none;
}
#dragger.visible {
display: block;
}
canvas {
border: 1px solid;
}
<script src="https://github.com/niklasvh/html2canvas/releases/download/v1.0.0-alpha.1/html2canvas.js"></script>
<div id="wrapper">
<p> Drag to take a screenshot ...</p>
<img crossOrigin src="https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png" width="120" height="120">
</div>
<div id="dragger" tabindex></div>

Categories