HTML5 Canvas - Dragging Text on Canvas Problem - javascript

I want to Drag Text which is located on the Canvas , I found a tutorial How to Drag a Rectange but i could not implement it on text , This is the Following code for moving the rectangle , can some one help me to implement it on Text ?
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Canvas Drag and Drop Test</title>
</head>
<body>
<section>
<div>
<canvas id="canvas" width="400" height="300">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
</div>
<script type="text/javascript">
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;
function rect(x,y,w,h) {
ctx.beginPath();
ctx.rect(x,y,w,h);
ctx.closePath();
ctx.fill();
}
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";
rect(0,0,WIDTH,HEIGHT);
ctx.fillStyle = "#444444";
rect(x - 15, y - 15, 30, 30);
}
function myMove(e){
if (dragok){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
}
}
function myDown(e){
if (e.pageX < x + 15 + canvas.offsetLeft && e.pageX > x - 15 +
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;
</script>
</section>
</body>
</html>
Test
And also when i add this Code in the HEAD tag it does not work. Why is it so ?

Basic example
http://jsfiddle.net/h3BCq/1/
Prettied up one (kept rect function, added new text function, draws the bounding box for the text)
http://jsfiddle.net/h3BCq/2/
I definitely cheated. I used px for the font size to easier grab its width. You could use em's, or points though you would just need to do a conversion to pixels to get an estimated width. I Basically just removed rect, and added filltext, and modified the check to check for the text width.

Related

detect close path in canvas

Hi I'm searching to find a way to close path with javascript.
I can draw a series of straight lines by clicking on the canvas but I want that when the line are closed the object create takes a grey background.
Like in this example when you close the wall the room appears
var needFirstPoint = true;
function drawNextLine(ctx, x, y) {
if (needFirstPoint) {
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(x, y);
needFirstPoint = false;
}
else {
ctx.lineTo(x, y);
ctx.stroke();
}
}
$(document).ready(function(){
var canvas = $('#myCanvas').get(0);
if (!canvas.getContext) { return; }
var ctx = canvas.getContext('2d');
$('#myCanvas').on('click', function(e){
var offset = $(this).offset();
var x = e.pageX - offset.left;
var y = e.pageY - offset.top;
drawNextLine(ctx, x, y);
});
});
canvas {
border: 1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="myCanvas" width="600" height="600"></canvas>
I don't know how to detect a close path that could form an object
EDIT: There is a simpler solution. Remember the position of the first click and check if any of the subsequent clicks are nearby.
https://codepen.io/anon/pen/pQLwGK
var startX = -1, startY = -1;
function dist(x0,y0,x1,y1)
{
return Math.sqrt( Math.pow(x1-x0,2) + Math.pow(y1-y0,2));
}
$(document).ready(function()
{
var canvas = $('#myCanvas').get(0);
if (!canvas.getContext) { return; }
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#f00';
ctx.beginPath();
$('#myCanvas').on('click', function(e)
{
console.log('click');
var offset = $(this).offset();
var x = e.pageX - offset.left;
var y = e.pageY - offset.top;
if (startX === -1)
{
console.log('start position is set to ',x ,y);
startX = x;
startY = y;
ctx.moveTo(x,y);
}
else
{
// checking if a click is within 20px of the starting point
if (dist(startX, startY,x,y ) < 20)
{
// assume that polygon is closed
ctx.lineTo(startX,startY);
ctx.fill();
console.log('fill');
}
else
{
ctx.lineTo(x,y);
}
ctx.stroke();
}
});
});

Drawing a circle with random color in canvas on mouse click

I am trying to develop a simple canvas application using html5 and javascript. I want to make a circle depending on the position of mouse click in the canvas. Each time user clicks in canvas a circle should be drawn. Moreover the color of circle needs to be randomly selected. I have written the random color and position function to get x and y position of mouse in canvas. But when i run nothing is happening.
Here is my html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="circle.js"></script>
<style type="text/css">
#testCanvas {
border: 2px solid;
}
</style>
</head>
<body>
<canvas id="testCanvas" width="400" height="400"> </canvas>
</body>
Here's my javascript code:
window.onload = init;
function init() {
// access the canvas element and its context
var canvas = document.getElementById("testCanvas");
var context = canvas.getContext("2d");
var pos = getMousePos(canvas, e);
posx = pos.x;
posy = pos.y;
context.fillStyle = randomColor();
// fill a circle
context.beginPath();
context.arc(posx,posy, 30, 0, 2 * Math.PI, true);
context.fill();
context.closePath();
}
function randomColor() {
var color = [];
for (var i = 0; i < 3; i++) {
color.push(Math.floor(Math.random() * 256));
}
return 'rgb(' + color.join(',') + ')';
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
You need to implement a click handler for the canvas so that every time you click on it you will receive a notification in form of an event:
// access the canvas element and its context
var canvas = document.getElementById("testCanvas");
var context = canvas.getContext("2d");
// add click handler
canvas.onclick = function(e) {
var pos = getMousePos(canvas, e); // get position as before
context.fillStyle = randomColor(); // get the fill color
// fill a circle
context.beginPath(); // now we can draw the circle at click
context.arc(pos.x, pos.y, 30, 0, 2 * Math.PI); // use pos object directly like this
context.fill();
// closePath() not needed here and won't work after fill() has been called anyways
}
function randomColor() {
var color = [];
for (var i = 0; i < 3; i++) {
color.push(Math.floor(Math.random() * 256));
}
return 'rgb(' + color.join(',') + ')';
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas {border: 1px solid #999}
<canvas id="testCanvas" width="400" height="400"> </canvas>
Here is another example / way of adding an event handler. You can change 'click' to 'mousemove' and others to try different things.
// access the canvas element and its context
window.onload = init;
function init(){
var canvas = document.getElementById("testCanvas");
var context = canvas.getContext("2d");
function drawCircle(pos,canvas){
posx = pos.x;
posy = pos.y;
context.fillStyle = randomColor();
// fill a circle
context.beginPath();
context.arc(posx,posy, 30, 0, 2 * Math.PI, true);
context.fill();
context.closePath();
}
function randomColor() {
var color = [];
for (var i = 0; i < 3; i++) {
color.push(Math.floor(Math.random() * 256));
}
return 'rgb(' + color.join(',') + ')';
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
} ;
}
canvas.addEventListener('click', function(evt){
var mousePos = getMousePos(canvas,evt);
drawCircle(mousePos,canvas);
},false);
}

Detect if Mouse is over an object inside canvas

I have created a line inside a canvas element. I am looking for the easiest way to detect if the position of the mouse is inside the line, which is inside the canvas.
I have used this function to see the position of the mouse inside the canvas, but I am very confused on how I should proceed.
function getMousePos(c, evt) {
var rect = c.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
I have also looked at this topic Fabricjs detect mouse over object path , but it detects if the mouse is inside the canvas, not inside the object.
The line that I create is a part of smaller lines, connected to each other.
for (var i = 0; i < 140 ; i++) {
ctx.beginPath();
ctx.moveTo(x[i],y[i]);
ctx.quadraticCurveTo(x[i],50,x[i+1],y[i+1]);
ctx.lineWidth = 40;
ctx.strokeStyle = 'white';
ctx.lineCap = 'round';
ctx.stroke();
}
where x[i] and y[i] are the arrays with the coordinates that I want.
I hope my question is clear, although I am not very familiar with javascript.
Thanks
Dimitra
A Demo: http://jsfiddle.net/m1erickson/Cw4ZN/
You need these concepts to check if the mouse is inside a line:
Define the starting & ending points of a line
Listen for mouse events
On mousemove, check if the mouse is within a specified distance of the line
Here's annotated example code for you to learn from.
$(function() {
// canvas related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
// dom element to indicate if mouse is inside/outside line
var $hit = $("#hit");
// determine how close the mouse must be to the line
// for the mouse to be inside the line
var tolerance = 5;
// define the starting & ending points of the line
var line = {
x0: 50,
y0: 50,
x1: 100,
y1: 100
};
// set the fillstyle of the canvas
ctx.fillStyle = "red";
// draw the line for the first time
draw(line);
// function to draw the line
// and optionally draw a dot when the mouse is inside
function draw(line, mouseX, mouseY, lineX, lineY) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(line.x0, line.y0);
ctx.lineTo(line.x1, line.y1);
ctx.stroke();
if (mouseX && lineX) {
ctx.beginPath();
ctx.arc(lineX, lineY, tolerance, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
}
// calculate the point on the line that's
// nearest to the mouse position
function linepointNearestMouse(line, x, y) {
//
lerp = function(a, b, x) {
return (a + x * (b - a));
};
var dx = line.x1 - line.x0;
var dy = line.y1 - line.y0;
var t = ((x - line.x0) * dx + (y - line.y0) * dy) / (dx * dx + dy * dy);
var lineX = lerp(line.x0, line.x1, t);
var lineY = lerp(line.y0, line.y1, t);
return ({
x: lineX,
y: lineY
});
};
// handle mousemove events
// calculate how close the mouse is to the line
// if that distance is less than tolerance then
// display a dot on the line
function handleMousemove(e) {
e.preventDefault();
e.stopPropagation();
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
if (mouseX < line.x0 || mouseX > line.x1) {
$hit.text("Outside");
draw(line);
return;
}
var linepoint = linepointNearestMouse(line, mouseX, mouseY);
var dx = mouseX - linepoint.x;
var dy = mouseY - linepoint.y;
var distance = Math.abs(Math.sqrt(dx * dx + dy * dy));
if (distance < tolerance) {
$hit.text("Inside the line");
draw(line, mouseX, mouseY, linepoint.x, linepoint.y);
} else {
$hit.text("Outside");
draw(line);
}
}
// tell the browser to call handleMousedown
// whenever the mouse moves
$("#canvas").mousemove(function(e) {
handleMousemove(e);
});
}); // end $(function(){});
body {
background-color: ivory;
}
canvas {
border: 1px solid red;
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<h2 id="hit">Move mouse near line</h2>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
About hit-testing Paths:
If you create Paths using path commands you can use context.isPointInPath(mouseX,mouseY) to check if the mouse is inside a path. context.isPointInPath does not work well with lines however because lines theoretically have zero width to "hit".
this.element.addEventListener("mouseenter", (event) => {});
mouse over a div
this.element.addEventListener("mouseleave", (event) => {});
mouse leaving div

Canvas circle progress bar with bounce effect

I have this code.
How I can make bounce effect as here? http://themeforest.net/item/cloud-admin-bootstrap-3-responsive-dashboard/full_screen_preview/6069264
Bounce example with a div
Change div.style.width with your canvas data..
max with the max value and the duration ..
requestAnimationframe is 60fps so 3000ms/60 gives you the number of frames.
function bounceOut(k){
return k<1/2.75?
7.5625*k*k:k<2/2.75?
7.5625*(k-=1.5/2.75)*k+.75:k<2.5/2.75?
7.5625*(k-=2.25/2.75)*k+.9375:
7.5625*(k-=2.625/2.75)*k+.984375
}
function animate(){
div.style.width=(bounceOut(current/duration)*max|0)+'px';
++current>duration||(a=webkitRequestAnimationFrame(animate));
}
var div=document.getElementsByTagName('div')[0],
duration=3000/60|0,
current=0,
max=500;
var a=webkitRequestAnimationFrame(animate);
Demo
http://jsfiddle.net/vL7Mp/1/
FULL CANVAS version
http://jsfiddle.net/vL7Mp/2/
jsut add a canvas and set the width & height
<canvas width="128" height="128"></canvas>
js
function animateC(p,C,K){
var c=C.getContext("2d"),
x=C.width/2,
r=x-(x/4),
s=(-90/180)*Math.PI,
p=p||0,
e=(((p*360|0)-90)/180)*Math.PI;
c.clearRect(0,0,C.width,C.height);
c.fillStyle=K;
c.textAlign='center';
c.font='bold '+(x/2)+'px Arial';
c.fillText(p*100|0,x,x+(x/5));
c.beginPath();
c.arc(x,x,r,s,e);
c.lineWidth=x/2;
c.strokeStyle=K;
c.stroke();
}
function bounceOut(k){
return k<1/2.75?
7.5625*k*k:k<2/2.75?
7.5625*(k-=1.5/2.75)*k+.75:k<2.5/2.75?
7.5625*(k-=2.25/2.75)*k+.9375:
7.5625*(k-=2.625/2.75)*k+.984375
}
function animate(){
animateC(bounceOut(current/duration),canvas,'rgba(127,227,127,0.3)');
++current>duration||(a=webkitRequestAnimationFrame(animate));
}
var canvas=document.getElementsByTagName('canvas')[0],
duration=6000/60|0,
current=0,
max=500,
a=webkitRequestAnimationFrame(animate);
if you have any questions just ask.
You can achieve a bounce effect by animating the draw using tweening with an easing equation.
Tween.js is a simple lib for handling this: https://github.com/sole/tween.js/
You would use it something like this:
var duration = 1000,
startValue = 0,
endValue = 100;
var tween = new TWEEN.Tween({x: startValue})
.to({ x: endValue }, duration)
.onUpdate(function() {
animate(this.x);
})
.easing(TWEEN.Easing.Bounce.Out)
.start();
Use this gist to get an easing function https://gist.github.com/dezinezync/5487119 also check out http://gizma.com/easing/
<html>
<head>
<title> two ball game</title>
</head>
<script type="text/javascript" src="jquery-1.11.3.min.js"></script>
<body>
<canvas id="canvas" width="852" height= "521" style= "border:5px solid grey ;" margin = right >
</canvas>
<script>
var x = 1;
var y = 1;
var dx = 2;
var dy = 1;
var ctx;
var WIDTH;
var HEIGHT;
init();
function circle(x,y,r) {
ctx.beginPath();
ctx.fillStyle="blue";
ctx.arc(x, y, 8, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
function rect(x,y,w,h) {
ctx.beginPath();
ctx.rect(x,y,w,h);
ctx.closePath();
ctx.fill();
}
function clear() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
}
function init() {
ctx = $('#canvas')[0].getContext("2d");
WIDTH = $("#canvas").width()
HEIGHT = $("#canvas").height()
return setInterval(draw, 10);
}
function draw() {
clear();
circle(x, y, 10);
if (x + dx > WIDTH || x + dx < 0)
dx = -dx;
if (y + dy > HEIGHT || y + dy < 0)
dy = -dy;
x += dx;
y += dy;
}
</script>
</body>
</html>
/****************************************************************\
write this code in your html

TypeError: Cannot call method 'getContext' of null (anonymous function)

I'm a beginner at this and haven't really done any JavaScript before so I hope you can help me. I've made a canvas that lets the user choose a shape and a colour with radio buttons which is then drawn on to the canvas. I've also added a checkbox with an option of adding a gradient to the chosen colour. Here's the program:
http://people.dsv.su.se/~caak1743/Canvas/canvas.html
Now I wan't to make it so that the shapes can be dragged and dropped around the canvas area. And I've found a code that I think can be altered to work on my program but I keep getting:
TypeError: Cannot call method 'getContext' of null
init
(anonymous function) for the line:
var ctx = canvas.getContext("2d");
and I have no idea what is wrong or how I can solve it. I've tried looking for similar programs with similar problems but haven't found anything that I can apply here. Here's the code that I'm trying to incorporate with mine:
function init() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
return setInterval(draw, 10);
}
function draw() {
clear();
ctx.fillStyle = "#FAF7F8";
rectangle(0,0,WIDTH,HEIGHT);
ctx.fillStyle = "#444444";
rectangle();
}
function myMove(e){
if (dragok){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
}
}
function myDown(e){
if (e.pageX < x + 15 + canvas.offsetLeft && e.pageX > x - 15 +
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;
Just correct it to the following:
<script type="text/javascript">
window.onLoad=function(){ init();};
function init() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
return setInterval(draw, 10);
}
function draw() {
clear();
ctx.fillStyle = "#FAF7F8";
rectangle(0,0,WIDTH,HEIGHT);
ctx.fillStyle = "#444444";
rectangle();
}
function myMove(e) {
if (dragok) {
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
}
}
function myDown(e) {
if (e.pageX < x + 15 + canvas.offsetLeft && e.pageX > x - 15 +
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;
</script>
This should work. The problem is canvas element need to be ready to run the script. Since the <script> in <head> section runs before loading the <canvas> it gives the error.
I found two solutions. The first is to add jquery to you page and then there is no need for using in-html js by wrapping the whole js code into $(document).ready(function() { Your code here });
what makes code run after html is ready, or just simply swapping head and body, where there is no need for using in-html js (it executes the html earlier than js). These should work.
You just need to do to that to get rid of the error.
Just add the canvas before the script and always place your script at the end.
<body>
<canvas id="ca"></canvas>
<script type="text/javascript">
var ca = document.getElementById("ca");
var co = ca.getContext("2d");
// whatever your code
</script>
</body>
Ensure that your script is AFTER your canvas element.

Categories