HTML5 canvas and php on Chrome not working - javascript

I would love to create a fiddle for this to show but i'm using php and it won't let me use php in those so i'm hoping someone will still know whats going on!
I have a javascript that works completely fine on it's own. It is a HTML click and drag canvas. The click and drag is constrained to a circle and draws the image to the canvas when you click a button that is next to the canvas. This button calls a method that draws the image onto the canvas and makes it click and draggable. I have tested this by itself and it works beautifully. When I add a simple line of php code my click and drag canvas quits moving the image. When you click the button to draw the image on, that works, but then you can't move the image.
I am beyond confused because the php that i am using has nothing to do with what is going on in the canvas. Here is the code:
it's also important to point out that this code works fine in safari but doesn't work at all in chrome so i know it has something to do with chrome i just don't understand what the problem is.
My question is mainly, is there a way that safari loads versus chrome that would affect running javascript and php on the same page since it works fine in one browser and not the other. I just added the code so people would know what I am referring to.
Here is the PHP
<dl class="header">
<?php
$name = $_GET['id'];
if ($name=="bracelet") {
echo "<li>Design x!</li>";
}
elseif ($name=="purse") {
echo "<li>Design y!</li>";
}
elseif ($name=="ring") {
echo "<li>Design z!</li>";
}
?>
</dl>
Here is the full code
<HTML>
<HEAD>
<style>
#canvas {
border:1px solid red;
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</HEAD>
<BODY>
<dl class="header">
<?php
$name = $_GET['id'];
if ($name=="bracelet") {
echo "<li>Design x!</li>";
}
elseif ($name=="purse") {
echo "<li>Design y!</li>";
}
elseif ($name=="ring") {
echo "<li>Design z!</li>";
}
?>
</dl>
<h5>Add Images and Canvases with the buttons<br>
Click to select which image to move.<br>
Then move the mouse to desired drop location<br>
and click again to drop the image there.</h5>
<canvas id="canvas" width=300 height=300></canvas>
<input type="image" src="http://s25.postimg.org/tovdg674b/crystal_003.png" id="button1" width="35" height="20"></input>
<input type="image" src="http://s25.postimg.org/ph0l7f5or/crystal_004.png" id="button2" width="35" height="20"></input>
<input type="image" src="http://s25.postimg.org/60fvkwakr/crystal_005.png" id="button3" width="35" height="20"></input>
<input type="image" src="http://s25.postimg.org/fz5fl49e3/crystal_006.png" id="button4" width="35" height="20"></input>
<button id="save">save</button>
<br>
<script>
// canvas stuff
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 50;
var contexts = [];
var points = [];
// image stuff
var states = [];
var img = new Image();
img.onload = function () {}
img.src = "http://s25.postimg.org/5qs46n4az/crystal_009.png";
setUpCanvas();
setUpPoints();
function setUpCanvas() {
contexts.push(canvas.getContext("2d"));
// link the new canvas to its context in the contexts[] array
canvas.contextIndex = contexts.length;
// wire up the click handler
canvas.onclick = function (e) {
handleClick(e, this.contextIndex);
};
// wire up the mousemove handler
canvas.onmousemove = function (e) {
handleMousemove(e, this.contextIndex);
};
canvas.addEventListener('dblclick', function() {
removeState(this.contextIndex);
});
}
function setUpPoints() {
//points that make up a circle circumference to an array
points = [];
for (var degree=0; degree<360; degree++) {
var radians = degree * Math.PI/180;
var TO_RADIANS = Math.PI/180;
var xpoint = centerX + radius * Math.cos(radians);
var ypoint = centerY + radius * Math.sin(radians);
points.push({
x: xpoint,
y: ypoint
});
}
ctx.beginPath();
ctx.moveTo(points[0].x + 4, points[0].y + 4)
//draws the thin line on the canvas
for (var i = 1; i < points.length; i++) {
var pt = points[i];
ctx.lineTo(pt.x + 4, pt.y + 4);
}
ctx.stroke(); //end of drawing the thin line
}
function addCircle() {
ctx.beginPath();
ctx.moveTo(points[0].x + 4, points[0].y + 4)
//draws the thin line on the canvas
for (var i = 1; i < points.length; i++) {
var pt = points[i];
ctx.lineTo(pt.x + 4, pt.y + 4);
}
ctx.stroke(); //end of drawing the thin line
}
function clearAll() {
//Clear all canvases
for (var i = 0; i < contexts.length; i++) {
var context = contexts[i];
context.clearRect(0, 0, canvas.width, canvas.height);
}
}
function handleClick(e, contextIndex) {
e.stopPropagation();
var mouseX = parseInt(e.clientX - e.target.offsetLeft);
var mouseY = parseInt(e.clientY - e.target.offsetTop);
for (var i = 0; i < states.length; i++) {
var state = states[i];
console.log(state);
if (state.dragging) {
state.dragging = false;
state.draw();
continue;
}
if (state.contextIndex == contextIndex && mouseX > state.x && mouseX < state.x + state.width && mouseY > state.y && mouseY < state.y + state.height) {
state.dragging = true;
state.offsetX = mouseX - state.x;
state.offsetY = mouseY - state.y;
state.contextIndex = contextIndex;
}
state.draw();
}
}
function handleMousemove(e, contextIndex) {
e.stopPropagation();
var mouseX = parseInt(e.clientX - e.target.offsetLeft);
var mouseY = parseInt(e.clientY - e.target.offsetTop);
clearAll();
addCircle();
var minDistance = 1000;
var minPoint = -1;
for (var i = 0; i < states.length; i++) {
var state = states[i];
if (state.dragging) {
for (var i = 0; i < points.length; i++) {
var pt = points[i];
var dx = mouseX - pt.x;
var dy = mouseY - pt.y;
if ((dx > 0 && dx>120)) {
state.x = mouseX - state.offsetX;
state.y = mouseY - state.offsetY;
state.contextIndex = contextIndex;
} else if ((dx < 0 && dx < -120)) {
state.x = mouseX - state.offsetX;
state.y = mouseY - state.offsetY;
state.contextIndex = contextIndex;
}
else {
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < minDistance) {
minDistance = distance;
//points in relation to the constrained line (where it will be drawn to)
//reset state.x and state.y to closest point on the line
state.x = pt.x - img.width / 2;
state.y = pt.y - img.height / 2;
state.contextIndex = contextIndex;
}
}
}
}
state.draw();
}
}
function removeState(contextIndex) {
for (var i = 0; i < states.length; i++) {
var state = states[i];
state.remove();
}
}
function addState(image) {
var ptxy = points[1];
state = {}
state.dragging = false;
state.contextIndex = 1;
state.image = image;
state.x = ptxy.x - image.width / 2;
state.y = ptxy.y - image.height / 2;
state.width = image.width;
state.height = image.height;
state.offsetX = 0;
state.offsetY = 0;
state.draw = function () {
var context = contexts[this.contextIndex - 1];
if (this.dragging) {
context.strokeStyle = 'black';
context.strokeRect(this.x, this.y, this.width + 2, this.height + 2)
}
context.drawImage(this.image, this.x, this.y);
}
state.draw();
return (state);
}
function save() {
// var data = ctx.getImageData(0, 0, canvas.width, canvas.height);
}
$("#button1").click(function () {
states.push(addState(img));
});
$("#button2").click(function () {
states.push(addState(img));
});
$("#button3").click(function () {
states.push(addState(img));
});
$("#button4").click(function () {
states.push(addState(img));
});
$("#save").click(function () {
save();
});
</script>
</BODY>
</HTML>

Anyone curious and wanting to know the answer of how i solved this here you go. I am new to HTML5 canvas and how it works. After a lot of trial and error I found out that the canvas offset was wrong once the canvas changed from the top of the screen to somewhere else. It was as simple as that....

Related

Draggable text on canvas

I'm making a whiteboard app where I want to drag text around the whiteboard with my mouse. Below is my dragText() so far where I handle mouse events etc. I tested click and move mouse events, and they both work, however the function still doesn't work as intended (I can't drag the text). I am out of ideas.
Also I noticed that in the function handleMouseDown, whenever I click somewhere on canvas where text coordinates are out of bounds, everything works fine there, but whenever I click on the text (and so the if statement in the for loop becomes true) suddenly whole canvas returns true (function textInBounds). Why is that?
function dragText() {
var canvas = document.getElementById('board'),
ctx = canvas.getContext('2d'),
font = '14px sans-serif';
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var texts = [];
texts.push({ text: "Hello", x: 20, y: 20 });
var StartX;
var StartY;
for (var i = 0; i < texts.length; i++) {
var text = texts[i];
ctx.position = 'absolute';
ctx.font = font;
ctx.fillText(text.text, text.x, text.y);
}
canvas.addEventListener('mousedown', function(e) {
handleMouseDown(e);
})
function handleMouseDown(e) {
e.preventDefault();
StartX = parseInt(e.clientX - canvas.getBoundingClientRect().left);
StartY = parseInt(e.clientY - canvas.getBoundingClientRect().top);
for (var i = 0; i < texts.length; i++) {
if (textInBounds(StartX, StartY, i)) {
selectElement(i);
canvas.addEventListener('mousemove', function(e) {
handleMouseMove(e);
})
} else {
return;
}
}
}
var selectedElement;
function selectElement(element) {
selectedElement = element;
}
function textInBounds(x, y, i) {
var text = texts[i];
return (x <= (text.x + ctx.measureText(text.text).width) && x > text.x);
}
function handleMouseMove(e) {
if (selectedElement < 0) {
return;
}
e.preventDefault();
var MouseX, MouseY
MouseX = parseInt(e.clientX - canvas.getBoundingClientRect().left);
MouseY = parseInt(e.clientY - canvas.getBoundingClientRect().top);
var dx = MouseX - StartX;
var dy = MouseX - StartY;
StartX = MouseX;
StartY = MouseX;
var text = texts[selectedElement];
text.x += dx;
text.y += dy;
}
{
function handleMouseUp(e) {
e.preventDefault();
selectedElement = -1;
}
}
}
HTML
render()
{
return(
<div class="sketch" id="sketch">
<canvas className="board" id="board"> </canvas>
</div>
)
}
CSS
.board
{
width: 100%;
height: 100%;
}
.sketch
{
width: 100%;
height: 100%;
}

import javascript file in my angular 2 projet

i"m working in angular projet and i want to add two javascript file in my project ; so i just include those js file in my assets and call them in my angular cli script part . i can see that those file are called correcty .
but i have this problems :
my html code is :
<div class=" demo-1">
<div class="content">
<div id="large-header" class="large-header">
<canvas id="demo-canvas"></canvas>
<h1 class="main-title">ALTEN <span class="thin">GAVĀ²</span></h1>
</div>
</div>
</div><!-- /container -->
and my js code is :
(function() {
var width, height, largeHeader, canvas, ctx, points, target, animateHeader = true;
// Main
initHeader();
initAnimation();
addListeners();
function initHeader() {
width = window.innerWidth;
height = window.innerHeight;
target = {x: width/2, y: height/2};
largeHeader = document.getElementById('large-header');
largeHeader.style.height = height+'px';
canvas = document.getElementById('demo-canvas');
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
// create points
points = [];
for(var x = 0; x < width; x = x + width/20) {
for(var y = 0; y < height; y = y + height/20) {
var px = x + Math.random()*width/20;
var py = y + Math.random()*height/20;
var p = {x: px, originX: px, y: py, originY: py };
points.push(p);
}
}
// for each point find the 5 closest points
for(var i = 0; i < points.length; i++) {
var closest = [];
var p1 = points[i];
for(var j = 0; j < points.length; j++) {
var p2 = points[j]
if(!(p1 == p2)) {
var placed = false;
for(var k = 0; k < 5; k++) {
if(!placed) {
if(closest[k] == undefined) {
closest[k] = p2;
placed = true;
}
}
}
for(var k = 0; k < 5; k++) {
if(!placed) {
if(getDistance(p1, p2) < getDistance(p1, closest[k])) {
closest[k] = p2;
placed = true;
}
}
}
}
}
p1.closest = closest;
}
// assign a circle to each point
for(var i in points) {
var c = new Circle(points[i], 2+Math.random()*2, 'rgba(255,255,255,0.3)');
points[i].circle = c;
}
}
// Event handling
function addListeners() {
if(!('ontouchstart' in window)) {
window.addEventListener('mousemove', mouseMove);
}
window.addEventListener('scroll', scrollCheck);
window.addEventListener('resize', resize);
}
function mouseMove(e) {
var posx = posy = 0;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
}
else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
target.x = posx;
target.y = posy;
}
function scrollCheck() {
if(document.body.scrollTop > height) animateHeader = false;
else animateHeader = true;
}
function resize() {
width = window.innerWidth;
height = window.innerHeight;
largeHeader.style.height = height+'px';
canvas.width = width;
canvas.height = height;
}
// animation
function initAnimation() {
animate();
for(var i in points) {
shiftPoint(points[i]);
}
}
function animate() {
if(animateHeader) {
ctx.clearRect(0,0,width,height);
for(var i in points) {
// detect points in range
if(Math.abs(getDistance(target, points[i])) < 4000) {
points[i].active = 0.3;
points[i].circle.active = 0.6;
} else if(Math.abs(getDistance(target, points[i])) < 20000) {
points[i].active = 0.1;
points[i].circle.active = 0.3;
} else if(Math.abs(getDistance(target, points[i])) < 40000) {
points[i].active = 0.02;
points[i].circle.active = 0.1;
} else {
points[i].active = 0;
points[i].circle.active = 0;
}
drawLines(points[i]);
points[i].circle.draw();
}
}
requestAnimationFrame(animate);
}
function shiftPoint(p) {
TweenLite.to(p, 1+1*Math.random(), {x:p.originX-50+Math.random()*100,
y: p.originY-50+Math.random()*100, ease:Circ.easeInOut,
onComplete: function() {
shiftPoint(p);
}});
}
// Canvas manipulation
function drawLines(p) {
if(!p.active) return;
for(var i in p.closest) {
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.closest[i].x, p.closest[i].y);
ctx.strokeStyle = 'rgba(156,217,249,'+ p.active+')';
ctx.stroke();
}
}
function Circle(pos,rad,color) {
var _this = this;
// constructor
(function() {
_this.pos = pos || null;
_this.radius = rad || null;
_this.color = color || null;
})();
this.draw = function() {
if(!_this.active) return;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(156,217,249,'+ _this.active+')';
ctx.fill();
};
}
// Util
function getDistance(p1, p2) {
return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
}
})();
when i try to log the largeHeader viariable in my js it return null .
this code work correctly . but including it in angular cli make problems .
is that a problem of webpack ?
thank you in advance
It's important to say what build tool you are using. If it's Webpack based (ie. Angular CLI) then you can reference a JavaScript file (or any other type) with one of the following:
import * as test from './test.js';
// or
require('./test.js');
However, your error message indicates that your JavaScript is running, but it's failing on these lines:
largeHeader = document.getElementById('large-header');
largeHeader.style.height = height+'px';
It's not finding an element on your page with ID large-header, so the call to .style fails. I suspect that, because you are importing the file from the top level HTML page, the JavaScript code is running before the template has a chance to render, so the large-header element is not created at that point.
To diagnose further, you could use the Sources tab of the Chrome Dev Tools to set a breakpoint on the line in question, then inspect the Elements tab to see if the expected div is actually present at this point.
I'm not sure exactly what you're trying to achieve here, but throwing in arbitrary bits of JavaScript that are not part of the "Angular world" might not be the best way to approach an Angular app. In the long term, perhaps it would be better to refactor this code into a Component or a Directive.

HTML5 Canvas can't drag text

(english is not my native language, hope you cope on this)
I'm having trouble why is my text can't be dragged when I add another canvas on it.
Basically, what I wanted to happen is I can drag my text and draw, and when I click the button "DRAW" i will start to draw.
Here's my code :
// FUNCTION FOR DRAWING !!!
$(function() {
$.each(['#f00', '#ff0', '#0f0'], function() {
$('#colors_demo').append("<a href='#colors_sketch' data-color='" + this + "' style='width: 30px;height: 30px;display:inline-block; background: " + this + ";'></a> ");
});
$('#colors_sketch').sketch();
$('#colors_sketch').sketch({defaultColor: "#ff0"});
});
//FUNCTION FOR DISPLAY TEXT!!!
function cakeDedicationFree() {
if (document.getElementById('design3').checked) {
var canvas2 = document.getElementById("colors_sketch");
context = canvas2.getContext("2d");
var $canvas2 = $("#colors_sketch");
var canvasOffset = $canvas2.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas2.scrollLeft();
var scrollY = $canvas2.scrollTop();
var startX;
var startY;
var texts = []; // an array to hold text objects
var selectedText = -1;// this var will hold the index of the hit-selected text
function draw()
{ // clear the canvas & redraw all texts
context.clearRect(0, 0, canvas2.width, canvas2.height);
for (var i = 0; i < texts.length; i++)
{
var text = texts[i];
context.fillText(text.text, text.x, text.y);
}
}
function textHittest(x, y, textIndex) { // test if x,y is inside the bounding box of texts[textIndex]
var text = texts[textIndex];
return (x >= text.x && x <= text.x + text.width && y >= text.y - text.height && y <= text.y);
}
function handleMouseDown(d) {
d.preventDefault();
startX = parseInt(d.clientX - offsetX);
startY = parseInt(d.clientY - offsetY);
for (var i = 0; i < texts.length; i++) {
if (textHittest(startX, startY, i)) {
selectedText = i; } }
}
function handleMouseUp(d) { // done dragging
d.preventDefault();
selectedText = -1; }
function handleMouseOut(d) { // also done dragging
d.preventDefault();
selectedText = -1; }
function handleMouseMove(d) {
if (selectedText < 0) { return; }
d.preventDefault();
mouseX = parseInt(d.clientX - offsetX);
mouseY = parseInt(d.clientY - offsetY);
var dx = mouseX - startX;
var dy = mouseY - startY;
startX = mouseX;
startY = mouseY;
var text = texts[selectedText];
text.x += dx;
text.y += dy;
draw(); }
$("#colors_sketch").mousedown(function (d) { handleMouseDown(d); }); // listen for mouse events
$("#colors_sketch").mousemove(function (d) { handleMouseMove(d); });
$("#colors_sketch").mouseup(function (d) { handleMouseUp(d); });
$("#colors_sketch").mouseout(function (d) { handleMouseOut(d); });
$("#text_dedi").click(function () {
var y = texts.length * 20 + 20;
var text = { text: $("#dedi_text").val(),
x: 20,
y: y
};
context.font = "30px Roboto";
text.width = context.measureText(text.text).width;
text.height = 16;
text.color = "#fff";
texts.push(text); // put this new text in the texts array
draw(); // redraw everything
});
document.getElementById('clear').addEventListener('click', function() {
context.clearRect(0, 0, canvas2.width, canvas2.height);
texts = []; },
false);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://intridea.github.io/sketch.js/lib/sketch.js"></script>
<!-- DRAWING PART -->
<div id="colors_demo" class="tools">
</div>
<div class="tools">
Marker
Eraser
</div>
<!-- DISPLAY TEXT PART -->
<br> <input type="radio" id="design3" name="design_3" onchange="cakeDedicationFree()" />
Text
<input type="text" size="15" id="dedi_text" name="dedicationT" placeholder="Text">
<button id="text_dedi"> Post </button> <input type="button" value="Clear" id="clear" size="23" >
<canvas id="colors_sketch" width="800" height="300"></canvas>
AS you can see, there's a big bug happening ..
worst part in my system it really doesn't show up.
Hope someone can help me.. Thank you in advance!!!

How would I create a trail behind my shapes in canvas?

Right now I have some shapes (I only included the triangle as they're all generated the same way) that are generated when the user spins the mouse wheel. I want to leave a trail behind the shapes that slowly disappear. I've looked around and tried a few different ways but I can't seem to get any of them to work. Here's the code:
<html>
<head>
<script>
var canvas;
var context;
var triangles = [];
var timer;
function init() {
canvas = document.getElementById('canvas');
context = canvas.getContext("2d");
resizeCanvas();
window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('orientationchange', resizeCanvas, false);
canvas.onwheel = function(event) {
handleClick(event.clientX, event.clientY);
};
var timer = setInterval(resizeCanvas, 30);
}
function Triangle(x,y,triangleColor) {
this.x = x;
this.y = y;
this.triangleColor = triangleColor;
this.vx = Math.random() * 30 - 15;
this.vy = Math.random() * 30 - 15;
this.time = 100;
}
function handleClick(x,y) {
var colors = [[0,170,255], [230,180,125], [50,205,130]];
var triangleColor = colors[Math.floor(Math.random()*colors.length)];
triangles.push(new Triangle(x,y,triangleColor));
for (var i=0; i<triangles.length; i++) {
drawTriangle(triangles[i]);
}
}
function drawTriangle(triangle) {
context.beginPath();
context.moveTo(triangle.x,triangle.y);
context.lineTo(triangle.x+25,triangle.y+25);
context.lineTo(triangle.x+25,triangle.y-25);
var c = triangle.triangleColor
context.fillStyle = 'rgba(' + c[0] + ', ' + c[1] + ', ' + c[2] + ', ' + (triangle.time / 100) + ')';
context.fill();
}
function resizeCanvas() {
canvas.width = window.innerWidth-20;
canvas.height = window.innerHeight-20;
fillBackgroundColor();
for (var i=0; i<triangles.length; i++) {
var t = triangles[i];
drawTriangle(t);
if (t.x + t.vx > canvas.width || t.x + t.vx < 0)
t.vx = -t.vx
if (t.y + t.vy > canvas.height || t.y + t.vy < 0)
t.vy = -t.vy
if (t.time === 0) {
triangles.splice(i,1);
}
t.time -= 1;
t.x += t.vx;
t.y += t.vy;
}
}
function fillBackgroundColor() {
context.fillStyle = "black";
context.fillRect(0,0,canvas.width,canvas.height);
}
window.onload = init;
</script>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
</html>
The way I managed to do this is by storing past locations of my objects (for example 10 past locations, and draw line from one to the next one.
1.Add arrays pastX and pastY to your triangle object.
this.pastX = [];
this.pastY = [];
2.Each tick put every element 1 place further and add current location as first.
Right before you update triangle positions
for(var k = t.pastX.length; k > 0; k--){
if(k < 10){
t.pastX[k] = pastX[k-1];
t.pastY[k] = pastY[k-1];
}
t.pastX[0] = t.x;
t.pastY[0] = t.y;
draw lines between them like this (from 0 to 1, from 1 to 2 and so on);
for(var k = 0; k < t.pastX.length - 1; k++){
//draw line from pastX[k], pastY[k] to pastX[k + 1], pastY[k + 1]
}
Hope I helped you.

Drawing multiple polygons in js

I'm using this code, and it works with charm - It draws a polygon (with canvas) on a given picture, however I'm struggling to modify code, so that it would enable me to draw multiple polygons instead of just one.
I'm a noob to js and haven't found yet anything that might solve it, I'd appreciate any help/hint in some direction.
Code:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="main.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script>
//radius of click around the first point to close the draw
var END_CLICK_RADIUS = 15;
//the max number of points of your polygon
var MAX_POINTS = 8;
var mouseX = 0;
var mouseY = 0;
var isStarted = false;
var points = null;
var canvas = null;
window.onload = function() {
background = document.getElementById('justanimage');
//initializing canvas and draw color
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
changeColor("blue");
image = new Image();
image.onload = function() {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
};
image.src = 'justanimage.gif';
canvas.addEventListener("click", function(e) {
var x = e.clientX-canvas.offsetLeft;
var y = e.clientY-canvas.offsetTop;
if(isStarted) {
//drawing the next line, and closing the polygon if needed
if(Math.abs(x - points[0].x) < END_CLICK_RADIUS && Math.abs(y - points[0].y) < END_CLICK_RADIUS) {
isStarted = false;
} else {
points[points.length] = new Point(x, y);
if(points.length >= MAX_POINTS) {
isStarted = false;
}
}
} else if(points == null) {
//opening the polygon
points = new Array();
points[0] = new Point(x, y);
isStarted = true;
}
}, false);
//we just save the location of the mouse
canvas.addEventListener("mousemove", function(e) {
mouseX = e.clientX - canvas.offsetLeft;
mouseY = e.clientY - canvas.offsetTop;
}, false);
//refresh time
setInterval("draw();", 5);
}
//object representing a point
function Point(x, y) {
this.x = x;
this.y = y;
}
//resets the application
function reset() {
isStarted = false;
points = null;
document.getElementById("coordinates").innerHTML = " ";
}
//displays coordinates of the the point list
function save() {
if(points == null) {
alert("No picture!");
} else {
var s = "";
for(var a in points) {
//inversing y axis by (canvas.height - points[a].y)
s += "(" + points[a].x + "," + (canvas.height - points[a].y) + ")\n";
}
document.getElementById("coordinates").innerHTML = s + '\n';
}
}
//draws the current shape
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
if(points != null && points.length > 0) {
ctx.moveTo(points[0].x, points[0].y);
for(i = 1 ; i < points.length ; i++) {
ctx.lineTo(points[i].x, points[i].y);
}
if(isStarted) {
ctx.lineTo(mouseX, mouseY);
} else {
ctx.lineTo(points[0].x, points[0].y);
}
}
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
ctx.stroke();
}
</script>
</head>
<body>
<div id="outer">
<canvas id="canvas" width=300 height=300; ></canvas>
</div>
<p id="coordinates"> </p>
<input type="button" value="Save" onclick="save();" />
<input type="button" value="Reset" onclick="reset();" />
</body>
</html>
Basically this solution adds a new array polygons, which keeps all polygons. The points array is now included in the polygons.
var polygons = [];
window.onload = function () {
// ...
canvas.addEventListener("click", function (e) {
// ...
if (isStarted) {
//drawing the next line, and closing the polygon if needed
if (Math.abs(x - polygons[polygons.length - 1][0].x) < END_CLICK_RADIUS && Math.abs(y - polygons[polygons.length - 1][0].y) < END_CLICK_RADIUS) {
isStarted = false;
} else {
polygons[polygons.length - 1].push(new Point(x, y));
if (polygons[polygons.length - 1].length >= MAX_POINTS) {
isStarted = false;
}
}
} else {
//opening the polygon
polygons.push([new Point(x, y)]);
isStarted = true;
}
}, false);
// ...
}
function draw() {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
polygons.forEach(function (points, i) {
ctx.beginPath();
points.forEach(function (p, j) {
if (j) {
ctx.lineTo(p.x, p.y);
} else {
ctx.moveTo(p.x, p.y);
}
});
if (i + 1 === polygons.length && isStarted) { // just the last one
ctx.lineTo(mouseX, mouseY);
} else {
ctx.lineTo(points[0].x, points[0].y);
}
ctx.stroke();
});
}
(Another solution might be to save the image with the last polygon and use it again for the new polygon.)
Working example:
//radius of click around the first point to close the draw
var END_CLICK_RADIUS = 15;
//the max number of points of your polygon
var MAX_POINTS = 8;
var mouseX = 0;
var mouseY = 0;
var isStarted = false;
var polygons = [];
var canvas = null;
var ctx;
var image;
window.onload = function () {
var background = document.getElementById('justanimage');
//initializing canvas and draw color
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
//changeColor("blue"); // <-- is missing!
image = new Image();
image.onload = function () {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
};
image.src = 'http://lorempixel.com/10/10/';
canvas.addEventListener("click", function (e) {
var x = e.clientX - canvas.offsetLeft;
var y = e.clientY - canvas.offsetTop;
if (isStarted) {
//drawing the next line, and closing the polygon if needed
if (Math.abs(x - polygons[polygons.length - 1][0].x) < END_CLICK_RADIUS && Math.abs(y - polygons[polygons.length - 1][0].y) < END_CLICK_RADIUS) {
isStarted = false;
} else {
polygons[polygons.length - 1].push(new Point(x, y));
if (polygons[polygons.length - 1].length >= MAX_POINTS) {
isStarted = false;
}
}
} else {
//opening the polygon
polygons.push([new Point(x, y)]);
isStarted = true;
}
}, false);
//we just save the location of the mouse
canvas.addEventListener("mousemove", function (e) {
mouseX = e.clientX - canvas.offsetLeft;
mouseY = e.clientY - canvas.offsetTop;
}, false);
//refresh time
setInterval("draw();", 5);
}
//object representing a point
function Point(x, y) {
this.x = x;
this.y = y;
}
//resets the application
function reset() {
isStarted = false;
points = null;
document.getElementById("coordinates").innerHTML = " ";
}
//draws the current shape
function draw() {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
polygons.forEach(function (points, i) {
ctx.beginPath();
points.forEach(function (p, j) {
if (j) {
ctx.lineTo(p.x, p.y);
} else {
ctx.moveTo(p.x, p.y);
}
});
if (i + 1 === polygons.length && isStarted) { // just the last one
ctx.lineTo(mouseX, mouseY);
} else {
ctx.lineTo(points[0].x, points[0].y);
}
ctx.stroke();
});
}
<canvas id="canvas" width="500" height="500"></canvas>
<img id="justanimage" />

Categories