Sudden change in picture quality in html canvas - javascript

I am making a canvas project and using some .png pictures. I used it in one file, canvas drew it up perfectly and all was well. But when i tried to to the same thing in a different file the quality of the pictures sank for no apparent reason. Would love some help/explenation to why this occured!
Here are the difference in coding, just open the files to see the difference in quality.
"Good quality code"
<!DOCTYPE html>
<html>
<head>
<title>Övning 1</title>
<style type="text/css">
*,body{
margin: 0px;
padding: 0px;
text-align: center;
background:url('bilder/background.png');
}
canvas{
border: 1px #999999 solid;
margin-top: 50px;
box-shadow: 2px 2px 1px rgba(50, 50, 50, 0.75) inset;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="900" height="400"></canvas>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var path = "bilder/helnot.png";
var image1 = new DragImage(path, 200, 100);
var image2 = new DragImage(path, 300, 100);
var gKlav = new Image();
gKlav.src = "bilder/g-klav.png";
var loop = setInterval(function() {
ctx.fillStyle = "#FFFFFF";
ctx.fillRect(0, 0, 900, 400);
image1.update();
image2.update();
}, 30);
var mouseX = 0;
var mouseY = 0;
var mousePressed = false;
var dragging = false;
function DrawLines(){
ctx.fillStyle = "#000000";
ctx.fillRect(50,160,800,1);
ctx.fillRect(50,180,800,1);
ctx.fillRect(50,200,800,1);
ctx.fillRect(50,220,800,1);
ctx.fillRect(50,240,800,1);
ctx.drawImage(gKlav, 40, 40);
}
//Saves the cursers location into two vairables
$(document).mousemove(function(e) {
mouseX = e.offsetX;
mouseY = e.offsetY;
})
//Specifies what happens when the mouse is clicked
$(document).mousedown(function() {
mousePressed = true;
}).mouseup(function() {
mousePressed = false;
dragging = false;
});
//'this.x' and 'that.x' refers to the location of the top left corner of the image.
//'startX' and 'startY' refers to the distance between the curser and the image.
function DragImage(src, x, y) {
var that = this;
var startX = 0;
var startY = 0;
var drag = false;
this.x = x;
this.y = y;
var img = new Image();
img.src = src;
this.update = function() {
if (mousePressed) {
var left = that.x;
var right = that.x + img.width;
var top = that.y;
var bottom = that.y + img.height;
if (!drag) {
startX = mouseX - that.x;
startY = mouseY - that.y;
}
if (mouseX < right && mouseX > left && mouseY < bottom && mouseY > top) {
if (!dragging){
dragging = true;
drag = true;
}
}
} else {
drag = false;
$(document).mouseup(function(){
if((that.y + (img.height/2)) > 145 && (that.y + (img.height/2)) < 155){that.y = 140}
if((that.y + (img.height/2)) > 155 && (that.y + (img.height/2)) < 165){that.y = 150}
if((that.y + (img.height/2)) > 165 && (that.y + (img.height/2)) < 175){that.y = 160}
if((that.y + (img.height/2)) > 175 && (that.y + (img.height/2)) < 185){that.y = 170}
if((that.y + (img.height/2)) > 185 && (that.y + (img.height/2)) < 195){that.y = 180}
if((that.y + (img.height/2)) > 195 && (that.y + (img.height/2)) < 205){that.y = 190}
});
}
//Makes the image 'drag' across the screen.
if (drag) {
that.x = mouseX - startX;
that.y = mouseY - startY;
}
ctx.drawImage(img, that.x, that.y);
DrawLines();
}
}
</script>
</body>
</html>
"Bad quality code"
<!DOCTYPE html>
<html>
<head>
<title>Övning 2</title>
<style type="text/css">
*,body{
margin: 0px;
padding: 0px;
text-align: center;
background:url('bilder/background.png');
}
canvas{
border: 1px #999999 solid;
margin-top: 50px;
box-shadow: 2px 2px 1px rgba(50, 50, 50, 0.75) inset;
}
button{
white-space:nowrap;
display:inline-block;
position:relative;
background:#C22E3A;
border:1px black solid;
text-decoration:none;
color:white;
padding: 6px 9px;
border-radius:3px;
margin:5px;
padding-left:50px;
padding-right: 50px;
-webkit-box-shadow: 0 5px 1px rgba(0,0,0,0.2);
text-shadow: 0px -1px 0px rgba(0,0,0,0.5);
transition: background-color linear 0.07s;
}
button:active{
top:3px;
-webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.3);
}
#inputBox{
display: none;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="900" height="400"></canvas><br />
<button id="start" onclick="Activate()">Start</button><br />
<input type="text" id="inputBox">
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var start = false;
var helnot = "bilder/helnot.png";
var helnot2 = new RandomizeNote(helnot);
var gKlav = new Image();
gKlav.src = "bilder/g-klav.png";
var loop = setInterval(function() {
if(start){
document.getElementById('start').style.display = "none";
document.getElementById('inputBox').style.display = "inline";
helnot2.update();
}
Sheet();
}, 30);
function Sheet(){
ctx.fillStyle = "#000000";
ctx.fillRect(200,160,500,1);
ctx.fillRect(200,180,500,1);
ctx.fillRect(200,200,500,1);
ctx.fillRect(200,220,500,1);
ctx.fillRect(200,240,500,1);
ctx.drawImage(gKlav, 200, 150);
}
function Activate(){
start = true;
}
function RandomizeNote(src){
var img = new Image();
img.src = src;
this.update = function(){
ctx.drawImage(img, 430, 150);
}
}
</script>
</body>
</html>

Related

Replicate Canvas resize in a Div

There's any way to replicate this scale behavior in a div ?
Here's an example of the behavior I wanted to reproduce within the div. I already have the movement part, and I just wanted to know about the resizing.
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<style>
body {
margin: 0px;
padding: 0px;
}
#wrapper {
position: relative;
border: 1px solid #9C9898;
width: 578px;
height: 200px;
}
#buttonWrapper {
position: absolute;
width: 30px;
top: 2px;
right: 2px;
}
input[type="button"] {
padding: 5px;
width: 30px;
margin: 0px 0px 2px 0px;
}
</style>
<script>
function draw(scale, translatePos) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
context.save();
context.translate(translatePos.x, translatePos.y);
context.scale(scale, scale);
context.beginPath(); // begin custom shape
context.moveTo(-119, -20);
context.bezierCurveTo(-159, 0, -159, 50, -59, 50);
context.bezierCurveTo(-39, 80, 31, 80, 51, 50);
context.bezierCurveTo(131, 50, 131, 20, 101, 0);
context.bezierCurveTo(141, -60, 81, -70, 51, -50);
context.bezierCurveTo(31, -95, -39, -80, -39, -50);
context.bezierCurveTo(-89, -95, -139, -80, -119, -20);
context.closePath(); // complete custom shape
var grd = context.createLinearGradient(-59, -100, 81, 100);
grd.addColorStop(0, "#8ED6FF"); // light blue
grd.addColorStop(1, "#004CB3"); // dark blue
context.fillStyle = grd;
context.fill();
context.lineWidth = 5;
context.strokeStyle = "#0000ff";
context.stroke();
context.restore();
}
window.onload = function() {
var canvas = document.getElementById("myCanvas");
var translatePos = {
x: canvas.width / 2,
y: canvas.height / 2
};
var scale = 1.0;
var scaleMultiplier = 0.8;
var startDragOffset = {};
var mouseDown = false;
// add button event listeners
document.getElementById("plus").addEventListener("click", function() {
scale /= scaleMultiplier;
draw(scale, translatePos);
}, false);
document.getElementById("minus").addEventListener("click", function() {
scale *= scaleMultiplier;
draw(scale, translatePos);
}, false);
// add event listeners to handle screen drag
canvas.addEventListener("mousedown", function(evt) {
mouseDown = true;
startDragOffset.x = evt.clientX - translatePos.x;
startDragOffset.y = evt.clientY - translatePos.y;
});
canvas.addEventListener("mouseup", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mouseover", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mouseout", function(evt) {
mouseDown = false;
});
canvas.addEventListener("mousemove", function(evt) {
if (mouseDown) {
translatePos.x = evt.clientX - startDragOffset.x;
translatePos.y = evt.clientY - startDragOffset.y;
draw(scale, translatePos);
}
});
draw(scale, translatePos);
};
jQuery(document).ready(function() {
$("#wrapper").mouseover(function(e) {
$('#status').html(e.pageX + ', ' + e.pageY);
});
})
</script>
</head>
<body onmousedown="return false;">
<div id="wrapper">
<canvas id="myCanvas" width="578" height="200">
</canvas>
<div id="buttonWrapper">
<input type="button" id="plus" value="+"><input type="button" id="minus" value="-">
</div>
</div>
<h2 id="status">
0, 0
</h2>
</body>
</html>
I tried to use css scale, but it resizes the div too, I want to modify only the space and the elements inside it.

Unable to get proper position in Canvas using ES6 (why isn't this code working properly?)

I am trying make an paint app using ES6. But i am not getting proper position and line in canvas.
This line is not drawn in correct position, like top-left is formed when i click and from 0,0 corner of canvas.
As you can see Line is not starting from the point Cursor is pointing and this difference increases as we move from TOP-LEFT cornor to BOTTOM-RIGHT cornor.
const TOOL_LINE = 'line';
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Paint {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.context = canvas.getContext("2d");
}
set activeTool(tool) {
this.tool = tool;
}
init() {
this.canvas.onmousedown = e => this.onMouseDown(e);
}
onMouseDown(e) {
this.saveData = this.context.getImageData(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
this.canvas.onmousemove = e => this.onMouseMove(e);
document.onmouseup = e => this.onMouseUp(e);
this.startPos = this.getMouseCoordinatesCanvas(e, this.canvas);
}
onMouseMove(e) {
this.currentPos = this.getMouseCoordinatesCanvas(e, this.canvas);
switch (this.tool) {
case TOOL_LINE:
this.drawShape();
break;
default:
break;
}
}
onMouseUp(e) {
this.canvas.onmousemove = null;
document.onmouseup = null;
}
drawShape() {
this.context.putImageData(this.saveData, 0, 0);
this.context.beginPath();
this.context.moveTo(this.startPos.x, this.startPos.y);
this.context.lineTo(this.currentPos.x, this.currentPos.y);
this.context.stroke();
}
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = e.clientX - rect.left;
let y = e.clientY - rect.top;
return new Point(x, y);
}
}
var paint = new Paint("canvas");
paint.activeTool = TOOL_LINE;
paint.init();
document.querySelectorAll("[data-tools]").forEach(
item => {
item.addEventListener("click", e => {
let selectedTool = item.getAttribute("data-tools");
paint.activeTool = selectedTool;
});
}
);
#Container {
background-color: lime;
height: 310px;
}
.toolbox,
#canvas {
display: inline-block;
}
.toolbox {
background-color: gray;
padding: 0px 15px 15px 15px;
left: 10px;
top: 11px;
}
.group {
margin: 5px 2px;
}
#line {
transform: rotate(-90deg);
}
.ico {
margin: 3px;
font-size: 23px;
}
.item:hover,
.item.active {
background-color: rgba(160, 160, 160, 0.5);
color: white;
}
#canvas {
background-color: white;
margin: 5px;
float: right;
width: 400px;
height: 300px;
}
<script src="https://kit.fontawesome.com/c1d28c00bc.js" crossorigin="anonymous"></script>
<div class="container">
<div id="Container">
<div class="toolbox">
<center>
<div class="group tools">
<div class="item active" data-tools="line">
<i class="ico far fa-window-minimize" id="line" title="Line"></i>
</div>
</div>
</center>
</div>
<canvas id="canvas"></canvas>
</div>
</div>
Here is link of code.
Thanks in advance.
The issue is 1 or both of 2 things
Your canvas is being displayed at 400x300 but it only has 300x150 pixels. Canvases have 2 sizes. One size is the size they are displayed set with CSS. The other is how many pixels which is usually set in code by setting canvas.width and canvas.height. The default number of pixels is 300x150
If you actually want them to be different sizes then you need to take that into account in your mouse code. The correct code is
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = (e.clientX - rect.left) * canvas.width / rect.width;
let y = (e.clientY - rect.top) * canvas.height / rect.height;
return new Point(x, y);
}
const TOOL_LINE = 'line';
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Paint {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.context = canvas.getContext("2d");
}
set activeTool(tool) {
this.tool = tool;
}
init() {
this.canvas.onmousedown = e => this.onMouseDown(e);
}
onMouseDown(e) {
this.saveData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
this.canvas.onmousemove = e => this.onMouseMove(e);
document.onmouseup = e => this.onMouseUp(e);
this.startPos = this.getMouseCoordinatesCanvas(e, this.canvas);
}
onMouseMove(e) {
this.currentPos = this.getMouseCoordinatesCanvas(e, this.canvas);
switch (this.tool) {
case TOOL_LINE:
this.drawShape();
break;
default:
break;
}
}
onMouseUp(e) {
this.canvas.onmousemove = null;
document.onmouseup = null;
}
drawShape() {
this.context.putImageData(this.saveData, 0, 0);
this.context.beginPath();
this.context.moveTo(this.startPos.x, this.startPos.y);
this.context.lineTo(this.currentPos.x, this.currentPos.y);
this.context.stroke();
}
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = (e.clientX - rect.left) * canvas.width / rect.width;
let y = (e.clientY - rect.top) * canvas.height / rect.height;
return new Point(x, y);
}
}
var paint = new Paint("canvas");
paint.activeTool = TOOL_LINE;
paint.init();
document.querySelectorAll("[data-tools]").forEach(
item => {
item.addEventListener("click", e => {
let selectedTool = item.getAttribute("data-tools");
paint.activeTool = selectedTool;
});
}
);
#Container {
background-color: lime;
height: 310px;
}
.toolbox,
#canvas {
display: inline-block;
}
.toolbox {
background-color: gray;
padding: 0px 15px 15px 15px;
left: 10px;
top: 11px;
}
.group {
margin: 5px 2px;
}
#line {
transform: rotate(-90deg);
}
.ico {
margin: 3px;
font-size: 23px;
}
.item:hover,
.item.active {
background-color: rgba(160, 160, 160, 0.5);
color: white;
}
#canvas {
background-color: white;
margin: 5px;
float: right;
width: 400px;
height: 300px;
}
<script src="https://kit.fontawesome.com/c1d28c00bc.js" crossorigin="anonymous"></script>
<div class="container">
<div id="Container">
<div class="toolbox">
<center>
<div class="group tools">
<div class="item active" data-tools="line">
<i class="ico far fa-window-minimize" id="line" title="Line"></i>
</div>
</div>
</center>
</div>
<canvas id="canvas"></canvas>
</div>
</div>
If you don't want them to be different sizes then you need to make the sizes match. I always set the size using CSS and then use code to make the canvas match that size.
Something like this
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
canvas.width = width;
canvas.height = height;
}
return needResize;
}
Note that anytime you change the canvas size it will get cleared but in any case.
const TOOL_LINE = 'line';
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
canvas.width = width;
canvas.height = height;
}
return needResize;
}
class Paint {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.context = canvas.getContext("2d");
resizeCanvasToDisplaySize(canvas);
}
set activeTool(tool) {
this.tool = tool;
}
init() {
this.canvas.onmousedown = e => this.onMouseDown(e);
}
onMouseDown(e) {
this.saveData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
this.canvas.onmousemove = e => this.onMouseMove(e);
document.onmouseup = e => this.onMouseUp(e);
this.startPos = this.getMouseCoordinatesCanvas(e, this.canvas);
}
onMouseMove(e) {
this.currentPos = this.getMouseCoordinatesCanvas(e, this.canvas);
switch (this.tool) {
case TOOL_LINE:
this.drawShape();
break;
default:
break;
}
}
onMouseUp(e) {
this.canvas.onmousemove = null;
document.onmouseup = null;
}
drawShape() {
this.context.putImageData(this.saveData, 0, 0);
this.context.beginPath();
this.context.moveTo(this.startPos.x, this.startPos.y);
this.context.lineTo(this.currentPos.x, this.currentPos.y);
this.context.stroke();
}
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = (e.clientX - rect.left) * canvas.width / rect.width;
let y = (e.clientY - rect.top) * canvas.height / rect.height;
return new Point(x, y);
}
}
var paint = new Paint("canvas");
paint.activeTool = TOOL_LINE;
paint.init();
document.querySelectorAll("[data-tools]").forEach(
item => {
item.addEventListener("click", e => {
let selectedTool = item.getAttribute("data-tools");
paint.activeTool = selectedTool;
});
}
);
#Container {
background-color: lime;
height: 310px;
}
.toolbox,
#canvas {
display: inline-block;
}
.toolbox {
background-color: gray;
padding: 0px 15px 15px 15px;
left: 10px;
top: 11px;
}
.group {
margin: 5px 2px;
}
#line {
transform: rotate(-90deg);
}
.ico {
margin: 3px;
font-size: 23px;
}
.item:hover,
.item.active {
background-color: rgba(160, 160, 160, 0.5);
color: white;
}
#canvas {
background-color: white;
margin: 5px;
float: right;
width: 400px;
height: 300px;
}
<script src="https://kit.fontawesome.com/c1d28c00bc.js" crossorigin="anonymous"></script>
<div class="container">
<div id="Container">
<div class="toolbox">
<center>
<div class="group tools">
<div class="item active" data-tools="line">
<i class="ico far fa-window-minimize" id="line" title="Line"></i>
</div>
</div>
</center>
</div>
<canvas id="canvas"></canvas>
</div>
</div>
A common reason to make them different sizes is to support HI-DPI displays. In that case though the mouse code can go back to the way it was if you use the canvas transform.
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth * devicePixelRatio | 0;
const height = canvas.clientHeight * devicePixelRatio | 0;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
canvas.width = width;
canvas.height = height;
}
return needResize;
}
and then set the transform before drawing
ctx.scale(devicePixelRatio, devicePixelRatio);
const TOOL_LINE = 'line';
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth * devicePixelRatio | 0;
const height = canvas.clientHeight * devicePixelRatio | 0;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
canvas.width = width;
canvas.height = height;
}
return needResize;
}
class Paint {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.context = canvas.getContext("2d");
resizeCanvasToDisplaySize(canvas);
}
set activeTool(tool) {
this.tool = tool;
}
init() {
this.canvas.onmousedown = e => this.onMouseDown(e);
}
onMouseDown(e) {
this.saveData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
this.canvas.onmousemove = e => this.onMouseMove(e);
document.onmouseup = e => this.onMouseUp(e);
this.startPos = this.getMouseCoordinatesCanvas(e, this.canvas);
}
onMouseMove(e) {
this.currentPos = this.getMouseCoordinatesCanvas(e, this.canvas);
switch (this.tool) {
case TOOL_LINE:
this.drawShape();
break;
default:
break;
}
}
onMouseUp(e) {
this.canvas.onmousemove = null;
document.onmouseup = null;
}
drawShape() {
this.context.setTransform(1, 0, 0, 1, 0, 0); // the default
this.context.putImageData(this.saveData, 0, 0);
this.context.scale(devicePixelRatio, devicePixelRatio);
this.context.beginPath();
this.context.moveTo(this.startPos.x, this.startPos.y);
this.context.lineTo(this.currentPos.x, this.currentPos.y);
this.context.stroke();
}
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = (e.clientX - rect.left);
let y = (e.clientY - rect.top);
return new Point(x, y);
}
}
var paint = new Paint("canvas");
paint.activeTool = TOOL_LINE;
paint.init();
document.querySelectorAll("[data-tools]").forEach(
item => {
item.addEventListener("click", e => {
let selectedTool = item.getAttribute("data-tools");
paint.activeTool = selectedTool;
});
}
);
#Container {
background-color: lime;
height: 310px;
}
.toolbox,
#canvas {
display: inline-block;
}
.toolbox {
background-color: gray;
padding: 0px 15px 15px 15px;
left: 10px;
top: 11px;
}
.group {
margin: 5px 2px;
}
#line {
transform: rotate(-90deg);
}
.ico {
margin: 3px;
font-size: 23px;
}
.item:hover,
.item.active {
background-color: rgba(160, 160, 160, 0.5);
color: white;
}
#canvas {
background-color: white;
margin: 5px;
float: right;
width: 400px;
height: 300px;
}
<script src="https://kit.fontawesome.com/c1d28c00bc.js" crossorigin="anonymous"></script>
<div class="container">
<div id="Container">
<div class="toolbox">
<center>
<div class="group tools">
<div class="item active" data-tools="line">
<i class="ico far fa-window-minimize" id="line" title="Line"></i>
</div>
</div>
</center>
</div>
<canvas id="canvas"></canvas>
</div>
</div>
note this line
this.saveData = this.context.getImageData(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
was wrong too. It should be
this.saveData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
clientWidth and clientHeight are the display size. width and height are the resolution (number of pixels in the canvas)

Why OffsetTop and offsetLeft not working?

I have my canvas and when I click I get X and Y, e.g. x=10 y=10, and when I use scrollbar drop and click in the same position I will get x= not 10 and y=not 10. Why?
<canvas></canvas>
<script>
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
topCanvas = canvas.offsetTop;
leftCanvas = canvas.offsetLeft;
function click(e)
{
console.log("x="+(e.clientX-leftCanvas));
console.log("y="+(e.clientY-topCanvas));
}
</script>
Why scrollbar not helping..
let canvas = document.querySelector('canvas');
let topCanvas = canvas.offsetTop;
let leftCanvas = canvas.offsetLeft;
canvas.addEventListener('click', e => {
console.log('not considering scroll position');
console.log(" x=" + (e.clientX - leftCanvas));
console.log(" y=" + (e.clientY - topCanvas));
console.log('considering scroll position');
console.log(" x=" + e.layerX);
console.log(" y=" + e.layerY);
});
div {
border: 1px solid;
max-height: 300px;
overflow: auto;
}
canvas {
border: 1px solid;
width: 500px;
height: 1000px;
margin-left: 30px;
margin-top: 30px;
}
<div>
<canvas></canvas>
</div>

How do I add a onClick event handler to a canvas element and control mouse movement actions?

I have an image within a canvas, I want to be to click the image and drag the image(without lifting the left mouse button) and the image at the position where the left mouse button was released. For now as soon as the mouse icon hovers over the canvas, the image moves with it, I tried to add an onclick listener event but I am sure my newbie-ness got in the way of my progress.
Here is what I had come up with so far. How can I make this work with my existing code?
var canvas = document.getElementById('customCanvas');
var context = canvas.getContext('2d');
make_base();
function make_base()
{
upload_image = new Image();
upload_image.src = 'https://lh3.googleusercontent.com/-6Zw-hozuEUg/VRF7LlCjcLI/AAAAAAAAAKQ/A61C3bhuGDs/w126-h126-p/eagle.jpg';
upload_image.onload = function(){
context.drawImage(upload_image, 0, 0);
canvas.addEventListener('click', canvas.onmousemove = function(e) {
/// correct mouse position so its relative to canvas
var rect = canvas.getBoundingClientRect(),
constantX = 0, constantY = 0,
x = e.clientX - rect.left,
y = e.clientY - rect.top;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(upload_image, x, y);
});
}
}
* {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
}
.sidepane {
height: 100%;
background: #E8E8EA;
}
.sidepane .form {
height: 80px;
margin: 10px 0;
}
.sidepane .assets {
width: 100%;
}
#assetText {
font-size: 24px;
}
.assets .text, .assets .image {
margin: 10px 0;
}
.assets .image ul li {
width: 50px;
height: 50px;
margin-right: 5px;
float: left;
overflow: hidden;
}
.assets .image ul li img {
width: 100%;
height: 100%;
}
.canvas .block {
position: relative;
width: 600px; height: 600px;
margin: 10px;
border: 1px solid;
box-shadow: 0px 0px 5px black;
}
.item {
border: 1px solid transparent;
position: absolute;
}
.item.selected {
border-color: blue;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="sidepane col-sm-2 col-md-2 col-lg-2">
<form method="post" action="/images" enctype="multipart/form-data">
<!--<div class="form">-->
<h3>Form</h3>
<input type="file" class="form-control" placeholder="Upload Your Images" name="filefield">
<button id="submit" class="btn btn-default">upload</button>
<!-- Upload Form here -->
<!--</div>-->
<hr />
<div class="assets">
<h3>Assets</h3>
<div class="text">
<h4>Text</h4>
<input type="text" name="textfield">
<button id="addText" class="btn btn-default">Add Text</button>
</div>
<div class="image">
<h4>Images</h4>
<ul class="list-unstyled">
<!-- List of images here -->
<!-- <li><img src="images/sample.jpeg" class="img-rounded" /></li> -->
</ul>
</div>
</div>
<input type="submit" >
</form>
</div>
<!-- canvas -->
<div class="canvas col-sm-8 col-md-8 col-lg-8">
<div class="block">
<!-- Add images and texts to here -->
<canvas id="customCanvas" width="598" height="598" style="border: 1px solid #000000">
</canvas>
</div>
</div>
First, you have to check if your mouse is on the image, and then check if you are trying to drag the image. To do that, you need some events, mousedown, mouseup and mousemove. To check if your mouse pointer is on the image, you have to get the X, Y, width, height of that image. Final code below.
Edit
Some more changes. Image class has no X and Y properties so I had to define variables that will store that data and make some changes to isInside function.
var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
var context = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 300;
var upload_image;
var imageX, imageY;
var mouseX, mouseY;
var imageDrag = false;
make_base();
canvas.addEventListener("mousemove", function (evt) {
var mousePos = getMousePos(canvas, evt);
mouseX = mousePos.x;
mouseY = mousePos.y;
});
function getMousePos(canvas, event) {
var rect = canvas.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
}
function isInsideImage(rect) {
var pos = { x: mouseX, y: mouseY };
return pos.x > imageX && pos.x < imageX + rect.width && pos.y < imageY + rect.height && pos.y > imageY;
}
function make_base()
{
upload_image = new Image();
imageX = 0;
imageY = 0;
upload_image.onload = function(){
context.drawImage(upload_image, 0, 0);
}
upload_image.src = 'https://lh3.googleusercontent.com/-6Zw-hozuEUg/VRF7LlCjcLI/AAAAAAAAAKQ/A61C3bhuGDs/w126-h126-p/eagle.jpg';
}
canvas.addEventListener("mousedown", function (evt) {
if(isInsideImage(upload_image)) {
imageDrag = true;
}
});
canvas.addEventListener("mouseup", function (evt) {
if(imageDrag)
imageDrag = false;
});
setInterval(function() {
if(imageDrag) {
context.clearRect(0, 0, canvas.width, canvas.height);
imageX = mouseX;
imageY = mouseY;
context.drawImage(upload_image, imageX, imageY);
}
}, 1000/30);
The event you're looking for would be https://developer.mozilla.org/en/docs/Web/Events/mousedown - AFAIK (correct me if I'm wrong) but the click event would only fire when a complete click event has completed (both down and up).
Here's some sample code for this;
var mouseX;
var mouseY; // Accessible outside the function. Easier access to canvas drawing.
var canvas = ''; // Complete this to get canvas element
canvas.addEventListener("mousedown", function(mouse){
// Get mouse co-ordinates
})
Inside this event listener, you can check for your current mouse position...
var canvasElement = element.getBoundingClientRect()
mouseX = mouse.pageX - canvasElement.left;
mouseY = mouse.pageY - canvasElement.top;
Use these variables when drawing your image to the canvas to determine the image's x and y position. These should change as your mouse moves around the canvas. I.e, pass them to your make_base() function;
make_base(mouseX, mouseY)
Update your drawing function to account for them;
function make_base(mouseX, mouseY)
{
upload_image = new Image();
upload_image.src = 'https://lh3.googleusercontent.com/-6Zw-hozuEUg/VRF7LlCjcLI/AAAAAAAAAKQ/A61C3bhuGDs/w126-h126-p/eagle.jpg';
upload_image.onload = function(){
context.drawImage(upload_image, 0, 0);
canvas.addEventListener('click', canvas.onmousemove = function(e) {
/// correct mouse position so its relative to canvas
var rect = canvas.getBoundingClientRect(),
constantX = 0, constantY = 0,
x = mouseX,
y = mouseY
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(upload_image, x, y);
});
}
}
PLEASE NOTE that the code above is not complete, for example, the X and Y will be based on where your mouse is on the PAGE, not the CANVAS. there are separate calculations needed to account for this.
Or, you can just embed an external link under the image to take you to wherever you want!

Drag and Drop over grid and revert back if size is greater than grid

This is my Canvas element:
<canvas id="canvas" width="280px" height="280px" style="background: #fff;"></canvas>
And this is my element section from which i want to drag elements to each grid unit of this canvas.
<div id="element1" style="width:55px; height:55px; border: 1px solid; background: lightblue"></div>
<div id="element2" style="width:111px; height:55px; border: 1px solid; background: lightgreen">
<div id="element1" style="width:55px; height:55px; border-right: 1px solid"></div>
And this is the script:
<script type="text/javascript" language="javascript">
var bw = 280;
var bh = 280;
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.strokeStyle = "black";
function drawGrid() {
for (var x = 0; x <= bw; x += 56) {
context.moveTo(x, 0);
context.lineTo(x, 280);
context.stroke();
}
for (var y = 0; y <= bh; y += 56) {
context.moveTo(0, y);
context.lineTo(280, y);
context.stroke();
}
}
drawGrid();
</script>

Categories