HTML5 Canvas Line Problem - html

I can create lines but I want to create it like you can change the direction of it and size of line anyway like http://devfiles.myopera.com/articles/649/example5.html in this link.
This is my code
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
$("canvas").mousedown(function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var a = x;
var b = y;
context.beginPath();
context.lineWidth = 2;
context.lineCap = "round";
context.moveTo(a, b);
$("canvas").mousemove(function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
context.lineTo(x, y);
context.stroke();
});
$("canvas").mouseup(function(e) {
$("canvas").unbind("mousemove").unbind("mouseup");
});
});
Also you can look from.
http://jsfiddle.net/nSnDC/ How can I solve it

http://devfiles.myopera.com/articles/649/example5.js
The answer is just one short step away....
Basically you need to clean the line drawn every time the mouse move (your script failed to do so).

Related

Variable linewidth in HTML5 canvas line

I was trying to contribute to this post, HTML5 Canvas and Line Width
but it was deleted because it's not an official answer, because technically I'm also asking a question using the following code I get the same problem.
"I'm drawing line graphs on a canvas. The lines draw fine. The graph is scaled, every segment is drawn, color are ok, etc. My only problem is visually the line width varies. It's almost like the nib of a caligraphy pen. If the stroke is upward the line is thin, if the stroke is horizontal, the line is thicker.
My line thickness is constant, and my strokeStyle is set to black. I don't see any other properties of the canvas that affect such a varying line width but there must be.
"
<html>
<head>
<style>html{font-family:Verdana;}</style>
<script type="text/javascript">
var canvas ;
var context ;
var Val_max;
var Val_min;
var sections;
var xScale;
var yScale;
var Samsung = [21000,21000,23000,22000,22000,23000,23000];
function init() {
// set these values for your data
sections = 7;
Val_max = 25000;
Val_min = 10000;
var stepSize = 1500;
var columnSize = 75;
var rowSize = 75;
var margin = 10;
var xAxis = [""," Monday "," Tuesday"," Wednesday"," Thursday"," Friday"," Saturday"," Sunday"]//;
//
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.fillStyle = "#4d4d4d"
context.font = "10 pt Arial"
yScale = (canvas.height - columnSize - margin) / (Val_max - Val_min);
xScale = (canvas.width - rowSize) / sections;
context.strokeStyle="#4d4d4d"; // color of grid lines
context.beginPath();
// print Parameters on X axis, and grid lines on the graph
for (i=1;i<=sections;i++) {
var x = i * xScale;
context.fillText(xAxis[i], x,columnSize - margin);
context.moveTo(x, columnSize);
context.lineTo(x, canvas.height - margin);
}
// print row header and draw horizontal grid lines
var count = 0;
for (scale=Val_max;scale>=Val_min;scale = scale - stepSize) {
var y = columnSize + (yScale * count * stepSize);
context.fillText(scale, margin,y + margin);
context.moveTo(rowSize,y)
context.lineTo(canvas.width,y)
count++;
}
context.stroke();
context.lineWidth=20;
context.translate(rowSize,canvas.height + Val_min * yScale);
context.scale(1,-1 * yScale);
// Color of each dataplot items
context.strokeStyle="#2FBC3A";
plotData(Samsung);
}
function plotData(dataSet) {
// context.beginPath();
// context.moveTo(0, dataSet[0]);
// for (i=1;i<sections;i++) {
// context.lineTo(i * xScale, dataSet[i]);
// }
// context.stroke();
var love=0;
for (i=1;i<sections;i++) {
context.beginPath();
context.moveTo(love, dataSet[i-1]);
context.lineTo(i * xScale, dataSet[i]);
love=i*xScale;
context.stroke();
}
}
</script>
</head>
<body onLoad="init()">
<div align="center">
<canvas id="canvas" height="400" width="650">
</canvas>
<br>
<!--Legends for Dataplot -->
<span style="color:#4d4d4d"> Graph </span>
</div>
</body>
</html>
You are changing your context's scaleY in a non-uniform way.
So all the drawings after this operation will get shrunk on the Y axis.
To avoid that, apply this scaling only on your coordinates, at the time of drawing i.e
context.scale(1, -1 * yScale);
...
context.lineTo(x, y);
becomes
context.lineTo(x, y * -1 * yScale);
This way, your coordinate gets correctly scaled, but your stroke keeps its correct scale.
Also, you were drawing each segment separately, which would produce some holes in between of every segments, so I took the liberty of merging them in a single sub-path.
var canvas;
var context;
var Val_max;
var Val_min;
var sections;
var xScale;
var yScale;
var Samsung = [21000, 21000, 23000, 22000, 22000, 23000, 23000];
function init() {
// set these values for your data
sections = 7;
Val_max = 25000;
Val_min = 10000;
var columnSize = 75;
var rowSize = 75;
var margin = 10;
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.fillStyle = "#4d4d4d";
yScale = (canvas.height - columnSize - margin) / (Val_max - Val_min);
xScale = (canvas.width - rowSize) / sections;
context.lineWidth = 20;
context.translate(rowSize, canvas.height + Val_min * yScale);
//context.scale(1,-1 * yScale);
// ^-- Don't do that.
context.strokeStyle = "#2FBC3A";
plotData(Samsung);
}
function plotData(dataSet) {
var love = 0;
// make a single path from all the segments
context.beginPath();
for (var i = 0; i < sections; i++) {
// Here we scale the coordinate, not the drawings
context.lineTo(i * xScale, dataSet[i] * -1 * yScale);
love = i * xScale;
}
context.stroke();
}
init();
<canvas id="canvas" height="400" width="650">
</canvas>

Find distance between two selected coordinates on image using canvas

I want to find a length of line and radius of circle on image depend on image width
see below image
var canvas = document.getElementById('loadCanvas'),lastPos, isDown = false;
ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
ctx.lineCap = "round";
ctx.lineWidth = $('#canvasSelWidth').val();
ctx.globalCompositeOperation = "multiply";
ctx.strokeStyle = $('#canvasSelColor').val();
canvas.onmousedown = function(e) {
isDown = true;
SPos = getPos(e);
lastPos = getPos(e);
};
window.onmousemove = function(e) {
if (!isDown) return;
var pos = getPos(e);
ctx.beginPath();
ctx.moveTo(lastPos.x, lastPos.y);
ctx.lineTo(pos.x, pos.y);
ctx.stroke();
lastPos = pos;
};
window.onmouseup = function(e) {
isDown = false
lPos = getPos(e);
measurementOnImageCanvas();
};
function getPos(e) {
var rect = canvas.getBoundingClientRect();
xPosition = e.clientX - rect.left;
yPosition = e.clientY - rect.top;
return {x: e.clientX - rect.left, y: e.clientY - rect.top}
}
I am use for first coordinate lPos and last SPos.
var xCorData = lPos.x - SPos.x
var yCorData = lPos.y - SPos.y
var finalPixel = Math.sqrt( xCorData*xCorData + yCorData*yCorData );
var centimeters = finalPixel * 2.54 / 96;
var mm = centimeters*10;
var inch = mm*0.0393701;
Please help me for short out from this problem
Can not be done
I am assuming you wish to get the physical size of a pixel on the client machine. Unfortunately there is no way to get the display dimensions.
window.screen.width and window.screen.height will get you the resolution of the display but there is no way of knowing the size of the display. Even if it was possible to get the device brand and model you still do not know if it is using its own display or is plugged into another. Even worse, multi display setups may have two or more different screen sizes so that your canvas has regions where the pixel physical size is different.
All you can do is ask the clien to enter the screen dimetions.
Assuming you have the screen diagonal.
At the moment I am on a 17.3 laptop with a 1680 by 945 pixel display. To get the pixel size.
Assume that the pixels are square.
const mmPerInch = 25.4; // constant
var screenDiagonal = 17.3 * mmPerInch; // ??? how to get this (17.3) is the problem
var resX = window.screen.width; // nor do you know if the pixel is square
var resY = window.screen.height;
// now get the number of pixels diagonally
if(typeof Math.hypot === "function"){ // use the new hypot function if available
var pixelsDiagonal = Math.hypot(resX,resY);
}else{
var pixelsDiagonal = Math.sqrt(resX*resX+resY*resY);
}
// then divide the screen size by the pixels to get the pixel size.
var pixelSize_mm = screenDiagonal / pixelsDiagonal;
// result pixel is 0.23 by 0.23 mm
You now have the size of a pixel in mm and can use that to get a accurate measure of objects you render. But it is no guarantee as the browser may be zoomed in or out.
To convert from pixels to mm just multiply pixel dimensions by pixel size
function pixel2mm(pixels){
return pixels * pixelSize_mm;
}
Also asking for the diagonal is no guarantee that the correct value is entered or even known. Also not all pixels are square and that will be even harder to find out.
If you want to measure things on a image more than on the screen, you have all the necessary code, just you needed to tie up togheter.
You have to ASSUME that you are on a 96 DPI device or putting the DPI as a parameter. Also giving a fixed scale for your canvas is the another way to go ( as if you would be on a map ).
var canvas = document.getElementById('loadCanvas'),lastPos, isDown = false;
ctx = canvas.getContext("2d");
ctx.lineCap = "round";
ctx.lineWidth = 2;
ctx.strokeStyle = 'blue';
canvas.onmousedown = function(e) {
isDown = true;
SPos = getPos(e);
lastPos = SPos;
};
window.onmousemove = function(e) {
if (!isDown) return;
var pos = getPos(e);
ctx.clearRect(0,0,500,500)
ctx.beginPath();
ctx.moveTo(lastPos.x, lastPos.y);
ctx.lineTo(pos.x, pos.y);
ctx.stroke();
lPos = pos;
};
window.onmouseup = function(e) {
isDown = false
lPos = getPos(e);
measurementOnImageCanvas();
};
function getPos(e) {
var rect = canvas.getBoundingClientRect();
xPosition = e.clientX - rect.left;
yPosition = e.clientY - rect.top;
return {x: e.clientX - rect.left, y: e.clientY - rect.top}
}
function measurementOnImageCanvas() {
var xCorData = lPos.x - SPos.x
var yCorData = lPos.y - SPos.y
var finalPixel = Math.sqrt( xCorData*xCorData + yCorData*yCorData );
var inches = finalPixel / 96;
var centimeters = inches * 2.54;
var millimiters = centimeters * 10;
alert('line lenght:\n' + inches.toFixed(2) + ' inches\n' + centimeters.toFixed(4) + ' centimeters\n' + millimiters.toFixed(2) + ' millimeters\nAssuming you are on a 96 DPI device');
}
<canvas id="loadCanvas" width=500 height=500 />

Drag & drop image on canvas image

I want to drag & drop text above image. For that I am using canvas. I am using this code
<img id="scream" src="http://127.0.0.1/demo/images.jpg" alt="The Scream" style="display:none;" width="220" height="277"><p>Canvas:</p>
<canvas id="canvas" width="300" height="300" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
var c=document.getElementById("canvas");
var ctx1=c.getContext("2d");
var img=document.getElementById("scream");
ctx1.drawImage(img,10,10);
var canvas;
var ctx;
var x = 75;
var y = 50;
var dx = 5;
var dy = 3;
var WIDTH = 400;
var HEIGHT = 300;
var dragok = false,
text = "Hey there im moving!",
textLength = (text.length * 14)/2;
function rect(x,y,w,h) {
ctx.font = "14px Arial";
ctx.strokeText("Hey there im a moving!!", x, y);
}
function clear() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
}
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
return setInterval(draw, 10);
}
function draw() {
clear();
ctx.fillStyle = "#FAF7F8";
ctx.fillStyle = "#444444";
rect(x - 15, y + 15, textLength, 30);
}
function myMove(e){
if (dragok){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
}
}
function myDown(e){
if (e.pageX < x + textLength + canvas.offsetLeft && e.pageX > x - textLength + canvas.offsetLeft && e.pageY < y + 15 + canvas.offsetTop &&
e.pageY > y -15 + canvas.offsetTop){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
dragok = true;
canvas.onmousemove = myMove;
}
}
function myUp(){
dragok = false;
canvas.onmousemove = null;
}
init();
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
I either able to show image or drag & drop text but I want both, please help me where I am wrong. You can check here:- http://jsfiddle.net/FWdSv/11/
When you're clearing the canvas, you're also clearing your image.
So the easy fix is to redraw the image in your draw function:
function draw() {
clear();
ctx.drawImage(img,0,0);
ctx.fillStyle = "#FAF7F8";
ctx.fillStyle = "#444444";
rect(x - 15, y + 15, textLength, 30);
}
Alternatively:
You could display your image underneath your canvas so it's not affected when you clear the canvas.

calling function twice in canvas

actually I'm new in html5 and tring to do something using canvas , the function that i create is drawing a short ray length start from point and end in point , the problem is when I duplicate the function to run twice in the same time it doesn't work correctly , where is the problem in my code ?
first I create the canvas
<canvas id="mycanvas" width="1120" height="700" style="margin:auto;border:1px solid #000000;position:relative;z-index: 10;">
</canvas>
Then i create call a function twice
var path1Number=0;
window.addEventListener('load', function () {
var x = 185, y = 185;
direction1(x,y , path1Number);
direction1(x+91,y+91 , path1Number);
}, false);
then i create a function that draw a path start from point to point
function direction1(x,y , path1Number){
//draw canvas line
var canvas1 = document.getElementById('mycanvas');
var context = canvas1.getContext('2d');
var x2 = x;
var y2 = y;
var ini_x = x;
var ini_y = y;
var done = false;
var interval = setInterval(function() {
context.clearRect(0, 0, canvas1.width, canvas1.height);
context.beginPath();
context.moveTo(x, y);
if(x2<x+20 && !done){
context.lineTo(x2, y2);
context.closePath();
context.strokeStyle = 'red';
context.stroke();
x2+=1;
y2+=1;
}else{
done = true;
x+=1;
y+=1;
if(x2 >= ini_x + 91){
if(x2 == x){
clearInterval(interval);
context.closePath();
context.clearRect(0, 0, canvas1.width, canvas1.height);
path1Number+=1;
path1(x,y,path1Number);
}
}else{
x2+=1;
y2+=1;
}
context.lineTo(x2, y2);
context.closePath();
context.strokeStyle = 'red';
context.stroke();
}
},10);
}
the problem happened when i call this function twice it doesn't work correctly so what is the reason ? Thanks .

How do I keep object location from being increased exponentially after each call to draw function?

Simple animation that creates a firework-like effect on the canvas with each click. The issue is the animation is made with a setInterval(draw) and every time the canvas is redrawn the location of each particle is += particle.speed. But with each click the particles move faster and faster as it seems the speed of each particle is not reset.
As you can see with a couple clicks on the working example here: , with the first click the particles move very (correctly) slowly, but with each subsequent click the speed is increased.
JS used is pasted below as well, any help is greatly appreciated!
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
canvas.addEventListener("click", startdraw, false);
//Lets resize the canvas to occupy the full page
var W = window.innerWidth;
var H = window.innerHeight;
canvas.width = W;
canvas.height = H;
ctx.fillStyle = "black";
ctx.fillRect(0, 0, W, H);
//global variables
var radius;
radius = 10;
balls_amt = 20;
balls = [];
var locX = Math.round(Math.random()*W);
var locY = Math.round(Math.random()*H);
//ball constructor
function ball(positionx,positiony,speedX,speedY)
{
this.r = Math.round(Math.random()*255);
this.g = Math.round(Math.random()*255);
this.b = Math.round(Math.random()*255);
this.a = Math.random();
this.location = {
x: positionx,
y:positiony
}
this.speed = {
x: -2+Math.random()*4,
y: -2+Math.random()*4
};
}
function draw(){
ctx.globalCompositeOperation = "source-over";
//Lets reduce the opacity of the BG paint to give the final touch
ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
ctx.fillRect(0, 0, W, H);
//Lets blend the particle with the BG
//ctx.globalCompositeOperation = "lighter";
for(var i = 0; i < balls.length; i++)
{
var p = balls[i];
ctx.beginPath();
ctx.arc(p.location.x, p.location.y, radius, Math.PI*2, false);
ctx.fillStyle = "rgba("+p.r+","+p.g+","+p.b+", "+p.a+")";
ctx.fill();
var consolelogX = p.location.x;
var consolelogY = p.location.y;
p.location.x += p.speed.x;
p.location.y += p.speed.y;
}
}
function startdraw(e){
var posX = e.pageX; //find the x position of the mouse
var posY = e.pageY; //find the y position of the mouse
for(i=0;i<balls_amt;i++){
balls.push(new ball(posX,posY));
}
setInterval(draw,20);
//ball[1].speed.x;
}
After each click startdraw is called, which starts every time a new periodical call (setInterval) for the draw method. So after the 2nd click you have 2 parallel intervals, after the 3rd you have 3 parallel intervals.
It is not exponentially, only linearly increasing :)
A possible dirty fix:
Introduce an interval global variable, and replace this row:
setInterval(draw,20);
with this one:
if (!interval) interval = setInterval(draw,20);
Or a nicer solution is to start the interval at the onLoad event.
setInterval will repeat its call every 20th ms, and returns an ID.
You can stop the repetition by calling clearInterval(ID).
var id = setInterval("alert('yo!');", 500);
clearInterval(id);