I'm trying to draw into a canvas, but the more I go right, the more offset my drawing become.
Anyone have an idea why?
I have included the relevant code below:
CSS
html,body {
width:100%;
height:100%;
background:rgba(0,0,0,.2);
}
#container {
position:relative;
width:700px;
height:450px;
background:#fff;
overflow:hidden;
}
* {
-webkit-user-select: none;
}
canvas {
position: absolute;
top: 0;
left: 0;
background: #ccc;
width: 500px;
height: 200px;
}
HTML
<div id='adContainer'>
<canvas></canvas>
</div>
Javascript
var ctx;
var can = $('canvas');
$(document).ready(function() {
ctx = can[0].getContext('2d');
ctx.strokeStyle = "rgba(255,0,0,1)";
ctx.lineWidth = 5;
ctx.lineCap = 'round';
can.on("touchstart", function(event) {
event.preventDefault();
var e = event.originalEvent;
if(e.touches.length == 1) {
var posX = e.touches[0].pageX;
var posY = e.touches[0].pageY;
ctx.moveTo(posX, posY);
}
});
can.on("touchmove", function(event) {
event.preventDefault();
var e = event.originalEvent;
if(e.touches.length == 1) {
var posX = e.touches[0].pageX;
var posY = e.touches[0].pageY;
ctx.lineTo(posX, posY);
ctx.stroke();
}
});
});
Demo: http://jsfiddle.net/8Wtf8/
That is because you define the size of the canvas using CSS.
What happens is that when you don't explicitly define the size of the canvas using its width and height attributes the canvas defaults to size 300 x 150.
In your CSS you are then stretching the canvas element (look at it as an image) to 500px etc. - the content of the canvas is still 300 x 150.
You need to set the width and height on the canvas element itself:
<canvas width=500 height=200 id="myCanvas"></canvas>
and remove the definition from the CSS:
canvas {
position: absolute;
top: 0;
left: 0;
background: #ccc;
/*width: 500px;
height: 200px;*/
}
Also notice that background set by CSS will not be part of the canvas content.
Related
An HTML canvas element can be automatically resized by the dynamics of a HTML page: Maybe because its style properties are set to a percentage value, or maybe because it is inside a flex container.
Thereby the content of the canvas gets resized as well: Because of the interpolation the canvas content looks blurred (loss of resolution).
In order to keep the resolution to the maximum, one must render the canvas content based on the current pixel size of the element.
This fiddle shows how this can be done with the help of the function getComputedStyle: https://jsfiddle.net/fx98gmu2/1/
setInterval(function() {
var computed = getComputedStyle(canvas);
var w = parseInt(computed.getPropertyValue("width"), 10);
var h = parseInt(computed.getPropertyValue("height"), 10);
canvas.width = w;
canvas.height = h;
// re-rendering of canvas content...
}, 2000); // intentionally long to see the effect
With a setTimeout function I'm updating the width and height of the canvas to the computed values of these properties.
As the fiddle shows, this works only when increasing the size of the window. Whenever the window size gets decreased, the canvas (item of the flexbox) stays fixed.
Set its flex-basis to 0, allow it to shrink with flex-shrink, and don't force any minimum width:
#canvas {
flex: 1 1 0;
min-width: 0;
}
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
setInterval(function() {
var computed = getComputedStyle(canvas),
w = parseInt(computed.width, 10),
h = parseInt(computed.height, 10);
canvas.width = w;
canvas.height = h;
ctx.clearRect(0, 0, w, h);
ctx.beginPath();
ctx.arc(w/2, h/2, h/2, 0, Math.PI*2, true);
ctx.stroke();
}, 2000); // intentionally long to see the effect
#container {
border: 1px solid blue;
width: 100%;
display: flex;
}
#canvas {
border: 1px solid red;
flex: 1 1 0;
min-width: 0;
height: 150px;
}
<div id="container">
<canvas id="canvas"></canvas>
<div>something else...</div>
</div>
You need to place the canvas into a container with overflow:hidden and set canvas dimensions to dimensions of that container:
window.setTimeout( function() {
var div = $("div");
div.find("canvas").attr( { width:div.width(), height:div.height()} );
})
canvas { background:gold; display:block; }
div { width:50%; height:50%; border:1px solid; overflow:hidden; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<canvas width="200" height="100" />
</div>
I'm trying to adjust the size to correctly be position more in the middle and a larger div. I would like it to be 500x500. What I'm trying to do is do a classic version of what Windows Paint is.
The issue is adjusting the 'canvas' to the middle stops the paint brush to 'draw'.
Here is the code, I have so far.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
width: 500px;
height: 500px;
margin: auto;
top: 50%;
left: 50%;
width: 90%;
border: 3px solid #73AD21;
padding: 10px;
}
</style>
</head>
<body>
<div id="paint" >
<canvas id="myCanvas"></canvas>
</div>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var painting = document.getElementById('paint');
var paint_style = getComputedStyle(painting);
canvas.width = parseInt(paint_style.getPropertyValue('width'));
canvas.height = parseInt(paint_style.getPropertyValue('height'));
var mouse = {x: 0, y: 0};
canvas.addEventListener('mousemove', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
ctx.lineWidth = 10;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = '#00CC99';
canvas.addEventListener('mousedown', function(e) {
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
</script>
</body>
</html>
Get rid of the styling on body and replace it with this:
#paint {
height: 500px;
margin: auto;
width: 90%; /* you also had width: 500px, which one did you want? */
border: 3px solid #73AD21;
padding: 10px;
}
Fiddle - Looks like it's working okay with that change.
I have a popup with a canvas that displays a graph, but sometimes the graph is bigger than the canvas is there a way that I can add some sort of scrolling event to allow the user to scroll horizontally, to see the rest of the graph?
Canvas is a normal DOM element like img, so you can use the regular CSS styles to define the scrolling behavior. For example:
$(document).ready(function(){
var ctx = $("#canvs").get(0).getContext('2d');
ctx.fillStyle = 'black';
ctx.fillRect(0,0,1600,300);
ctx.strokeStyle = "lime";
ctx.moveTo(0, 150);
for (var i = 0; i <= 16; i++){
var y = i % 2 == 0 ? 50 : 250;
ctx.lineTo(i * 100, y);
ctx.stroke();
}
});
#cont{
display: block;
width: 500px;
height: 330px;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='cont'>
<canvas id='canvs' width='1600px' height='300px'></canvas>
</div>
I need to use the full space of canvas to draw. But here unable to use the top and left of the canvas to draw. I try make some changes in css, still no luck. Please help.
p.s. By clicking the button the canvas will popup.
<button onClick="openPopup();">click here</button>
<div id="test" class="popup">
<div class="cancel" onclick="closePopup();"></div>
<canvas id="canvas1" width="750" height="720" style="border: 1px solid black"></canvas>
</div>
<style>
.popup{
position:absolute;
top:0px;
left:0px;
margin:0px;
width: 900px;
height: 750px;
font-family:verdana;
font-size:13px;
padding:2px;
background-color:white;
border:2px solid grey;
z-index:100000000000000000;
display:none;
opacity:0.6;
filter:alpha(opacity=60);
margin-left: 300px;
margin-top: 90px;
overflow: auto;
}
.cancel{
display:relative;
cursor:pointer;
margin:0;
float:right;
height:10px;
width:14px;
padding:0 0 5px 0;
background-color:red;
text-align:center;
font-weight:bold;
font-size:11px;
color:white;
border-radius:3px;
z-index:100000000000000000;
}
.cancel:hover{
background:rgb(255,50,50);
}
</style>
<script>
function openPopup() {
document.getElementById('test').style.display = 'block';
}
function closePopup() {
document.getElementById('test').style.display = 'none';
}
var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
var isPressed = false;
var mx = 4, my = 4;
function move(e) {
getMouse(e);
if (isPressed) {
ctx.lineTo(mx, my);
ctx.stroke()
}
}
function up(e) {
getMouse(e);
isPressed = false;
}
function down(e) {
getMouse(e);
ctx.beginPath();
ctx.moveTo(mx, my);
isPressed = true;
}
can.onmousemove = move;
can.onmousedown = down;
can.onmouseup = up;
// waaaay oversimplified:
function getMouse(e) {
var element = can, offsetX = 0, offsetY = 0;
mx = e.pageX;
my = e.pageY;
}
</script>
The drawing point is not synced with mouse pointer.
That is the reason why you can't draw at the left part and the top part of the canvas, because the mouse is already out of the canvas if you try to draw something nearby the left edge.
Notice that how you get the current position of the drawing point:
function getMouse(e) {
var element = can, offsetX = 0, offsetY = 0;
mx = e.pageX;
my = e.pageY;
}
the variable e refers to mouseEvent object. and e.pageX means the distance between the mouse and the left side of the page, NOT YOUR CANVAS. So you should minus the left offset of the canvas from mx and do the same to my, so that the drawing point is right on where you want.
One simple solution:
set the canvas's margin, border and padding to 0;
.popup{
//everything else..
boder: 0;
margin-left: 0px;
margin-top: 0px;
}
Better solution:
minus the left offset to mx and my
function getMouse(e) {
var element = can, offsetX = 0, offsetY = 0;
mx = e.pageX - 305;
my = e.pageY - 95;
//Dynamically getting those padding and margin and border would be better!
}
My code is below. I also have it at http://jsfiddle.net/S2JHa/
I do not understand why cursor changes to I-beam when I click and drag the mouse over my picture.
If I remove "some text" then it does not change. This happens in Chrome. FF is fine.
Please if you can tell how to fix that I would appreciate it.
Thanks!
<div id="window">
<div>some text</div>
<div id="sketch" class="box">
<div class="contents">
<canvas id="image-layer"></canvas>
</div>
</div>
</div>
CSS:
#window #sketch
{
padding: 1cm 0;
}
#window #sketch canvas
{
left: 0;
position: absolute;
top: 0;
}
#window #sketch .contents
{
cursor: crosshair;
position: relative;
}
div.box
{
background-color: #fff;
border: 1px solid black;
border-radius: 0.3cm;
cursor: move;
left: 0;
position: fixed;
top: 0;
}
JavaScript:
function image_onload(e) {
var image = e.target;
$("div.box").draggable({
cancel: "div.box div.contents",
containment: "document"
});
var x = $("#window #sketch");
// size to fit image
x.css("width", image.width);
x.css("height", image.height);
// center sketch inside parent window
x.css("left", ($(window).width() - x.width()) / 2);
var canvas = document.getElementById("image-layer");
canvas.height = image.height;
canvas.width = image.width;
var context = canvas.getContext("2d");
context.drawImage(image, 0, 0);
}
function open(url) {
var image = new Image();
image.src = url;
image.onload = image_onload;
}
open("http://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png");
If you don't want interactivity with the canvas you can cancel the onmousedown event like so:
canvas.onmousedown = function () {
return false;
}
Fr IE you will need:
canvas.onselectstart = function () {
return false;
}
See updated jsfiddle here: http://jsfiddle.net/S2JHa/11/