How do I draw lines in a grid? - javascript

I need advice on how to make an event and draw mouse lines in the grid. Somehow I can't do it so I can draw straight lines in a grid. But I still have a grid, I don't know how to fix a drawing error. I am adding my Javascript code below. My mouse drawing event doesn't work, it doesn't draw me at all.
JS code for grid:
;(function () {
let canvas, ctx, mouse
class Mouse {
constructor (ctx, x = 0, y = 0) {
this.x = x
this.y = y
this.ctx = ctx
}
set pos (evt) {
const canvasDimensions = canvas.getBoundingClientRect()
this.x = Math.floor(evt.clientX - canvasDimensions.left)
this.y = Math.floor(evt.clientY - canvasDimensions.top)
const { x, y, ctx } = this
const txt = `X: ${x}, Y: ${y}`
ctx.font = '16px Poppins'
const offsetX = x < canvas.width / 2 ? 15 : -ctx.measureText(txt).width - 15
const offsetY = y < canvas.height / 2 ? 20 : -13
ctx.fillText(txt, this.x + offsetX, this.y + offsetY)
}
}
class Line {
constructor (color, lineWidth, startX, startY, endX, endY) {
this.color = color
this.lineWidth = lineWidth
this.startX = startX
this.startY = startY
this.endX = endX
this.endY = endY
}
draw (ctx) {
const { color, lineWidth, startX, startY, endX, endY } = this
ctx.beginPath()
ctx.strokeStyle = color
ctx.lineWidth = lineWidth
ctx.moveTo(startX, startY)
ctx.lineTo(endX, endY)
ctx.stroke()
}
}
class Grid {
constructor (
color = 'black', lineWidth = 0.25, step = 25,
boldNth = 5, boldColor = 'black', boldWidth = 0.25
) {
this.color = color
this.lineWidth = lineWidth
this.step = step
this.boldNth = boldNth
this.boldColor = boldColor
this.boldWidth = boldWidth
this.lines = null
}
createLines () {
const {
color, lineWidth, step,
boldNth, boldColor, boldWidth
} = this
const lines = []
const div = boldNth * step
for (let x = 0; x < canvas.width; x += step) {
const isNth = x % div === 0
lines.push(
isNth
? new Line(boldColor, boldWidth, x, 0, x, canvas.height)
: new Line(color, lineWidth, x, 0, x, canvas.height)
)
}
for (let y = 0; y < canvas.height; y += step) {
const isNth = y % div === 0
lines.push(
isNth
? new Line(boldColor, boldWidth, 0, y, canvas.width, y)
: new Line(color, lineWidth, 0, y, canvas.width, y)
)
}
this.lines = lines
}
drawText (ctx) {
const { step, boldNth, boldColor } = this
ctx.font = '16px Poppins'
ctx.fillStyle = boldColor
ctx.fillText('0', 1, 15)
for (let x = step * boldNth; x < canvas.width; x += step * boldNth) {
ctx.fillText(x, x, 15)
}
for (let y = step * boldNth; y < canvas.height; y += step * boldNth) {
ctx.fillText(y, 0, y + 15)
}
}
draw (ctx) {
if (!this.lines) this.createLines()
this.lines.forEach(line => line.draw(ctx))
this.drawText(ctx)
}
}
function init () {
canvas = document.getElementById('Canvas')
ctx = canvas.getContext('2d')
mouse = new Mouse(ctx)
const grid = new Grid('black', 0.25, 50, 1)
grid.draw(ctx)
canvas.addEventListener('mousemove', (evt) => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
grid.draw(ctx)
mouse.pos = evt
})
canvas.addEventListener('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
var points = [ pointer.x, pointer.y, pointer.x, pointer.y ];
line = new fabric.Line(points, {
strokeWidth: 5,
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center'
});
});
canvas.addEventListener('mouse:move', function(o){
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
line.set({ x2: pointer.x, y2: pointer.y });
canvas.renderAll();
grid.draw(ctx)
});
canvas.on('mouse:up', function(o){
isDown = false;
grid.draw(ctx)
});
}
document.addEventListener('DOMContentLoaded', init)
})()

you can use this references codereview.stackexchange.com/questions/114702/… my it can help you – Tommy Ferdian Hadimarta 54 secs ago

Related

Determine if a Selection Marquee is over a Rotated Rectangle

I have a Rectangle class for drawing to HTML Canvas. It has a rotation property that gets applied in its draw method. If the user drags within the canvas, a selection marquee is being drawn. How can I set the Rectangle's active attribute to true when the Rectangle is within the selection marquee using math? This is a problem I'm having in another language & context so I do not have all of Canvas' methods available to me there (e.g. isPointInPath).
I found a StackOverflow post about finding Mouse position within rotated rectangle in HTML5 Canvas, which I am implementing in the Rectangle method checkHit. It doesn't account for the selection marquee, however. It's just looking at the mouse X & Y, which is still off. The light blue dot is the origin around which the rectangle is being rotated. Please let me know if anything is unclear. Thank you.
class Rectangle
{
constructor(x, y, width, height, rotation) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.xOffset = this.x + this.width/2;
this.yOffset = this.y + ((this.y+this.height)/2);
this.rotation = rotation;
this.active = false;
}
checkHit()
{
// translate mouse point values to origin
let originX = this.xOffset;
let originY = this.yOffset;
let dx = marquee[2] - originX;
let dy = marquee[3] - originY;
// distance between the point and the center of the rectangle
let h1 = Math.sqrt(dx*dx + dy*dy);
let currA = Math.atan2(dy,dx);
// Angle of point rotated around origin of rectangle in opposition
let newA = currA - this.rotation;
// New position of mouse point when rotated
let x2 = Math.cos(newA) * h1;
let y2 = Math.sin(newA) * h1;
// Check relative to center of rectangle
if (x2 > -0.5 * this.width && x2 < 0.5 * this.width && y2 > -0.5 * this.height && y2 < 0.5 * this.height){
this.active = true;
} else {
this.active = false;
}
}
draw()
{
ctx.save();
ctx.translate(this.xOffset, this.yOffset);
ctx.fillStyle = 'rgba(255,255,255,1)';
ctx.beginPath();
ctx.arc(0, 0, 3, 0, 2 * Math.PI, true);
ctx.fill();
ctx.rotate(this.rotation * Math.PI / 180);
ctx.translate(-this.xOffset, -this.yOffset);
if (this.active)
{
ctx.fillStyle = 'rgba(255,0,0,0.5)';
} else {
ctx.fillStyle = 'rgba(0,0,255,0.5)';
}
ctx.beginPath();
ctx.fillRect(this.x, this.y, this.width, this.y+this.height);
ctx.closePath();
ctx.stroke();
ctx.restore();
}
}
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var raf;
var rect = new Rectangle(50,50,90,30,45);
var marquee = [-3,-3,-3,-3];
var BB=canvas.getBoundingClientRect();
var offsetX=BB.left;
var offsetY=BB.top;
var start_x,start_y;
let draw = () => {
ctx.clearRect(0,0, canvas.width, canvas.height);
//rect.rotation+=1;
rect.draw();
ctx.fillStyle = "rgba(200, 200, 255, 0.5)";
ctx.fillRect(parseInt(marquee[0]),parseInt(marquee[1]),parseInt(marquee[2]),parseInt(marquee[3]))
ctx.strokeStyle = "white"
ctx.lineWidth = 1;
ctx.rect(parseInt(marquee[0]),parseInt(marquee[1]),parseInt(marquee[2]),parseInt(marquee[3]))
ctx.stroke()
raf = window.requestAnimationFrame(draw);
}
let dragStart = (e) =>
{
start_x = parseInt(e.clientX-offsetX);
start_y = parseInt(e.clientY-offsetY);
marquee = [start_x,start_y,0,0];
canvas.addEventListener("mousemove", drag);
}
let drag = (e) =>
{
let mouseX = parseInt(e.clientX-offsetX);
let mouseY = parseInt(e.clientY-offsetY);
marquee[2] = mouseX - start_x;
marquee[3] = mouseY - start_y;
rect.checkHit();
}
let dragEnd = (e) =>
{
marquee = [-10,-10,-10,-10];
canvas.removeEventListener("mousemove", drag);
}
canvas.addEventListener('mousedown', dragStart);
canvas.addEventListener('mouseup', dragEnd);
raf = window.requestAnimationFrame(draw);
body
{
margin:0;
}
#canvas
{
width: 360px;
height: 180px;
border: 1px solid grey;
background-color: grey;
}
<canvas id="canvas" width="360" height="180"></canvas>
Do convex polygons overlap
Rectangles are convex polygons.
Rectangle and marquee each have 4 points (corners) that define 4 edges (lines segments) connecting the points.
This solution works for all convex irregular polygons with 3 or more sides.
Points and edges must be sequential either Clockwise CW of Count Clockwise CCW
Test points
If any point of one poly is inside the other polygon then they must overlap. See example function isInside
To check if point is inside a polygon, get cross product of, edge start to the point as vector, and the edge as a vector.
If all cross products are >= 0 (to the left of) then there is overlap (for CW polygon). If polygon is CCW then if all cross products are <= 0 (to the right of) there is overlap.
It is possible to overlap without any points inside the other poly.
Test Edges
If any of the edges from one poly crosses any of the edges from the other then there must be overlap. The function doLinesIntercept returns true if two line segments intercept.
Complete test
Function isPolyOver(poly1, poly2) will return true if there is overlap of the two polys.
A polygon is defined by a set of Point's and Lines's connecting the points.
The polygon can be irregular, meaning that each edge can be any length > 0
Do not pass polygons with an edge of length === 0 or will not work.
Added
I added the function Rectangle.toPoints that transforms the rectangle and returning a set of 4 points (corners).
Example
Example is a copy of your code working using the above methods.
canvas.addEventListener('mousedown', dragStart);
canvas.addEventListener('mouseup', dragEnd);
requestAnimationFrame(draw);
const Point = (x = 0, y = 0) => ({x, y, set(x,y){ this.x = x; this.y = y }});
const Line = (p1, p2) => ({p1, p2});
const selector = { points: [Point(), Point(), Point(), Point()] }
selector.lines = [
Line(selector.points[0], selector.points[1]),
Line(selector.points[1], selector.points[2]),
Line(selector.points[2], selector.points[3]),
Line(selector.points[3], selector.points[0])
];
const rectangle = { points: [Point(), Point(), Point(), Point()] }
rectangle.lines = [
Line(rectangle.points[0], rectangle.points[1]),
Line(rectangle.points[1], rectangle.points[2]),
Line(rectangle.points[2], rectangle.points[3]),
Line(rectangle.points[3], rectangle.points[0])
];
function isInside(point, points) {
var i = 0, p1 = points[points.length - 1];
while (i < points.length) {
const p2 = points[i++];
if ((p2.x - p1.x) * (point.y - p1.y) - (p2.y - p1.y) * (point.x - p1.x) < 0) { return false }
p1 = p2;
}
return true;
}
function doLinesIntercept(l1, l2) {
const v1x = l1.p2.x - l1.p1.x;
const v1y = l1.p2.y - l1.p1.y;
const v2x = l2.p2.x - l2.p1.x;
const v2y = l2.p2.y - l2.p1.y;
const c = v1x * v2y - v1y * v2x;
if(c !== 0){
const u = (v2x * (l1.p1.y - l2.p1.y) - v2y * (l1.p1.x - l2.p1.x)) / c;
if(u >= 0 && u <= 1){
const u = (v1x * (l1.p1.y - l2.p1.y) - v1y * (l1.p1.x - l2.p1.x)) / c;
return u >= 0 && u <= 1;
}
}
return false;
}
function isPolyOver(p1, p2) { // is poly p2 under any part of poly p1
if (p2.points.some(p => isInside(p, p1.points))) { return true };
if (p1.points.some(p => isInside(p, p2.points))) { return true };
return p1.lines.some(l1 => p2.lines.some(l2 => doLinesIntercept(l1, l2)));
}
const ctx = canvas.getContext("2d");
var dragging = false;
const marquee = [0,0,0,0];
const rotate = 0.01;
var startX, startY, hasSize = false;
const BB = canvas.getBoundingClientRect();
const offsetX = BB.left;
const offsetY = BB.top;
class Rectangle {
constructor(x, y, width, height, rotation) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.rotation = rotation;
this.active = false;
}
toPoints(points = [Point(), Point(), Point(), Point()]) {
const xAx = Math.cos(this.rotation) / 2;
const xAy = Math.sin(this.rotation) / 2;
const x = this.x, y = this.y;
const w = this.width, h = this.height;
points[0].set(-w * xAx + h * xAy + x, -w * xAy - h * xAx + y);
points[1].set( w * xAx + h * xAy + x, w * xAy - h * xAx + y);
points[2].set( w * xAx - h * xAy + x, w * xAy + h * xAx + y);
points[3].set(-w * xAx - h * xAy + x, -w * xAy + h * xAx + y);
}
draw() {
ctx.setTransform(1, 0, 0, 1, this.x, this.y);
ctx.fillStyle = 'rgba(255,255,255,1)';
ctx.strokeStyle = this.active ? 'rgba(255,0,0,1)' : 'rgba(0,0,255,1)';
ctx.lineWidth = this.active ? 3 : 1;
ctx.beginPath();
ctx.arc(0, 0, 3, 0, 2 * Math.PI, true);
ctx.fill();
ctx.rotate(this.rotation);
ctx.beginPath();
ctx.rect(-this.width / 2, - this.height / 2, this.width, this.height);
ctx.stroke();
}
}
function draw(){
rect.rotation += rotate;
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
rect.draw();
drawSelector();
requestAnimationFrame(draw);
}
function drawSelector() {
if (dragging && hasSize) {
rect.toPoints(rectangle.points);
rect.active = isPolyOver(selector, rectangle);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillStyle = "rgba(200, 200, 255, 0.5)";
ctx.strokeStyle = "white";
ctx.lineWidth = 1;
ctx.beginPath();
ctx.rect(...marquee);
ctx.fill();
ctx.stroke();
} else {
rect.active = false;
}
}
function dragStart(e) {
startX = e.clientX - offsetX;
startY = e.clientY - offsetY;
drag(e);
canvas.addEventListener("mousemove", drag);
}
function drag(e) {
dragging = true;
const x = e.clientX - offsetX;
const y = e.clientY - offsetY;
const left = Math.min(startX, x);
const top = Math.min(startY, y);
const w = Math.max(startX, x) - left;
const h = Math.max(startY, y) - top;
marquee[0] = left;
marquee[1] = top;
marquee[2] = w;
marquee[3] = h;
if (w > 0 || h > 0) {
hasSize = true;
selector.points[0].set(left, top);
selector.points[1].set(left + w, top);
selector.points[2].set(left + w, top + h);
selector.points[3].set(left , top + h);
} else {
hasSize = false;
}
}
function dragEnd(e) {
dragging = false;
rect.active = false;
canvas.removeEventListener("mousemove", drag);
}
const rect = new Rectangle(canvas.width / 2, canvas.height / 2, 90, 90, Math.PI / 4);
body
{
margin:0;
}
#canvas
{
width: 360px;
height: 180px;
border: 1px solid grey;
background-color: grey;
}
<canvas id="canvas" width="360" height="180"></canvas>

draw arc between 2 lines & draw a curve 2 points

Framework: fabricjs
My first problem is to draw a angle betweens 2 Lines. My code is working but i'm not happy with the result.
My second problem is to draw a curve between 2 Points.
My Code for the first problem.
I have 3 Points:
A , B , C
2 Lines:
AB , BC
With this information i calculate distance points with distance 10.
let angle = this.calcAngle(A,B,C);
let distanceAB = this.calcCornerPoint(A, B, 10);
let distanceBC = this.calcCornerPoint(C, B, 10);
Calc Angle:
calcAngle(A, B, C, final, finalAddon = "°") {
var nx1 = A.x - B.x;
var ny1 = A.y - B.y;
var nx2 = C.x - B.x;
var ny2 = C.y - B.y;
this.lineAngle1 = Math.atan2(ny1, nx1);
this.lineAngle2 = Math.atan2(ny2, nx2);
if (nx1 * ny2 - ny1 * nx2 < 0) {
const t = lineAngle2;
this.lineAngle2 = this.lineAngle1;
this.lineAngle1 = t;
}
// if angle 1 is behind then move ahead
if (lineAngle1 < lineAngle2) {
this.lineAngle1 += Math.PI * 2;
}
}
Than draw a Path with:
this.drawAngleTrapez(distanceAB, distanceBC, B);
drawAngleTrapez(AB, BC, B) {
let points = [AB, BC, B];
let path = "";
if (this.trapezObjs[this.iterator]) {
this.canvas.remove(this.trapezObjs[this.iterator]);
}
path += "M " + Math.round(points[0].x) + " " + Math.round(points[0].y) + "";
for (let i = 1; i < points.length; i++) {
path += " L " + Math.round(points[i].x) + " " + Math.round(points[i].y) + "";
}
this.currentTrapez = this.trapezObjs[this.iterator] = new fabric.Path(path, {
selectable: false,
hasControls: false,
hasBorders: false,
hoverCursor: 'default',
fill: '#ccc',
strokeWidth: this.strokeWidth,
});
this.canvas.add(this.trapezObjs[this.iterator]);
}
And than i draw a Circle:
drawAnglePoint(B,d = 10) {
this.currentCorner = new fabric.Circle({
left: B.x,
top: B.y,
startAngle: this.lineAngle1,
endAngle: this.lineAngle2,
radius: 10,
fill: '#ccc',
selectable: false,
hasControls: false,
hasBorders: false,
hoverCursor: 'default',
});
this.canvas.add(this.currentCorner);
}
But the result ist not beautiful:
And the blue point is not on the end of the line, mabye here also a little fix.
this.startPoint.set({ left: C.x, top: C.y });
Second Problem solved: was an error in my calculation.
The problem is , its not a beautiful curve:
Rather than draw the central 'wedge' as 2 shapes - a triangle and a portion of a circle, you should instead draw it as the 2-sided figure that it is.
Circles are drawn by supplying the origin. Therefore, to draw the blue point on the end of the line, you should specify the same coordinates for the end-point as you do for the circle-centre.
The below code will re-create your first image with the exception of the text.
While I've drawn the swept-angle indicator transparently, ontop of the lines, you'd probably want to change the draw order, colour and opacity.
(I used 0x88/0xFF = 136/255 = 53.3%),
"use strict";
function newEl(tag){return document.createElement(tag)}
function byId(id){return document.getElementById(id)}
class vec2
{
constructor(x,y){this.x = x;this.y = y;}
get x(){ return this._x; }
set x(newVal){ this._x = newVal; }
get y(){ return this._y; }
set y(newVal){ this._y = newVal; }
get length(){return Math.hypot(this.x,this.y);}
set length(len){var invLen = len/this.length; this.timesEquals(invLen);}
add(other){return new vec2(this.x+other.x, this.y+other.y);}
sub(other){return new vec2(this.x-other.x, this.y-other.y);}
plusEquals(other){this.x+=other.x;this.y+=other.y;return this;}
minusEquals(other){this.x-=other.x;this.y-=other.y;return this;}
timesEquals(scalar){this.x*=scalar;this.y*=scalar;return this;}
divByEquals(scalar){this.x/=scalar;this.y/=scalar;return this;}
setTo(other){this.x=other.x;this.y=other.y;}
toString(){return `vec2 {x: ${this.x}, y: ${this.y}}` }
toStringN(n){ return `vec2 {x: ${this.x.toFixed(n)}, y: ${this.y.toFixed(n)}}` }
dotProd(other){return this.x*other.x + this.y*other.y;}
timesEquals(scalar){this.x *= scalar;this.y *= scalar;return this;}
normalize(){let len = this.length;this.x /= len;this.y /= len;return this;}
static clone(other){let result = new vec2(other.x, other.y);return result;}
clone(){return vec2.clone(this);}
};
window.addEventListener('load', onWindowLoaded, false);
function onWindowLoaded(evt)
{
var can = byId('output');
let A = new vec2(172,602), B = new vec2(734,602), C = new vec2(847,194);
myTest(can, [A,B,C]);
}
function circle(canvas, x, y, radius)
{
let ctx = canvas.getContext('2d');
ctx.moveTo(x,y);
ctx.beginPath();
ctx.ellipse(x,y, radius,radius, 0, 0, 2*Math.PI);
ctx.closePath();
ctx.fill();
}
function getAngle(origin, pt)
{
let delta = pt.sub(origin);
let angle = Math.atan2( delta.y, delta.x );
return angle;
}
function myTest(canvas, points)
{
let ctx = canvas.getContext('2d');
// background colour
//
ctx.fillStyle = '#ebedf0';
ctx.fillRect(0,0,canvas.width,canvas.height);
// white square grid
//
//60,33 = intersection of first
//115 = square-size
ctx.strokeStyle = '#FFFFFF';
ctx.lineWidth = 12;
for (let x=60; x<canvas.width; x+=112)
{
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
ctx.closePath();
}
for (let y=33; y<canvas.height; y+=112)
{
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
ctx.closePath();
}
// wedge indicating swept angle
let angle1 = getAngle(points[1], points[2]);
let angle2 = getAngle(points[1], points[0]);
ctx.beginPath();
ctx.moveTo(points[1].x,points[1].y);
ctx.arc(points[1].x,points[1].y, 70, angle1,angle2, true);
ctx.fillStyle = '#cccccc88';
ctx.fill();
console.log(angle1, angle2);
// lines
//
ctx.lineWidth = 9;
ctx.strokeStyle = '#c3874c';
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
ctx.lineTo(points[1].x, points[1].y);
ctx.lineTo(points[2].x, points[2].y);
ctx.stroke();
ctx.closePath();
// points
//
ctx.fillStyle = '#3b89c9';
ctx.beginPath();
points.forEach( function(pt){circle(canvas, pt.x,pt.y, 10);} );
ctx.closePath();
}
canvas
{
zoom: 67%;
}
<canvas id='output' width='996' height='730'></canvas>

Why is camera's position not correctly calculated (canvas)

I am making a clone of agar.io and I am stuck in my code. I can't understand why my camera's position is not correctly calculated. I want my camera's position to half the vector between the farthest blob and the closest blob.
Below is a picture and my code:
<html>
<head>
<title>Play Agario Clone</title>
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas id="game">
kindly update your browser.
</canvas>
<script>
var
canvas,
ctx,
width = innerWidth,
height = innerHeight,
mouseX = 0,
mouseY = 0;
var
camera = {
x: 0,
y: 0,
// camera
update: function(obj) {
var farthestBlobX = Math.max.apply(0, obj.blobs.map(function(cell) { return cell.x }));
var farthestBlobY = Math.max.apply(0, obj.blobs.map(function(cell) { return cell.y }));
var closestBlobX = Math.min.apply(0, obj.blobs.map(function(cell) { return cell.x }));
var closestBlobY = Math.min.apply(0, obj.blobs.map(function(cell) { return cell.y }));
var x = farthestBlobX - closestBlobX;
var y = farthestBlobY - closestBlobY;
var length = Math.sqrt(x * x + y * y);
this.x = length/2 - width/2;
this.y = length/2 - height/2;
}
},
player = {
defaultMass: 54,
x: 0,
y: 0,
blobs: [],
update: function () {
for (var i = 0; i < this.blobs.length; i ++) {
var x = mouseX + camera.x - this.blobs[i].x;
var y = mouseY + camera.y - this.blobs[i].y;
var length = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
var speed = 54/this.blobs[i].mass;
this.blobs[i].velX = x/length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].velY = y/length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].x += this.blobs[i].velX;
this.blobs[i].y += this.blobs[i].velY;
for (var j = 0; j < this.blobs.length; j ++) {
if (j != i && this.blobs[i] !== undefined) {
var blob1 = this.blobs[i];
var blob2 = this.blobs[j];
var x = blob2.x - blob1.x;
var y = blob2.y - blob1.y;
var dist = Math.sqrt(x * x + y * y);
if (dist < blob1.mass + blob2.mass) {
x /= dist;
y /= dist;
blob1.x = blob2.x - x * (blob1.mass + blob2.mass);
blob1.y = blob2.y - y * (blob1.mass + blob2.mass);
}
}
}
}
this.x += (mouseX - width/2)/(width/2) * 1;
this.y += (mouseY - height/2)/(height/2) * 1
},
split: function (cell) {
cell.mass /= 2;
this.blobs.push({
x: cell.x,
y: cell.y,
mass: cell.mass
});
},
draw: function () {
for (var i = 0; i < this.blobs.length; i ++) {
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(-camera.x + this.blobs[i].x, -camera.y + this.blobs[i].y, this.blobs[i].mass, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
}
}
};
function handleMouseMove (e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
function setup () {
canvas = document.getElementById("game");
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
addEventListener("mousemove", handleMouseMove);
player.blobs.push({
x: 0,
y: 0,
mass: player.defaultMass
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass/2
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass*2
});
var loop = function () {
update();
draw();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
function update () {
camera.update(player);
player.update();
}
function draw () {
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height);
player.draw();
}
setup();
</script>
</body>
</html>
Instead of computing everything relative to your camera, use your camera to set the global transformation matrix of your canvas, and only for this.
This way, your blobs' updates will be cleaner, and your camera easier to manage.
Now to get the middle position between two points, do (pt1 + pt2) / 2.
You were not clear in your question, if fartherstX and fartherstY should represent the same blob. In your code it wasn't, so I didn't change it.
Also, I didn't gone into all your logics, but beware NaN values, I got some while doing the edit.
function draw() {
var cw = ctx.canvas.width / 2;
var ch = ctx.canvas.height / 2;
// reset transform to clear the canvas
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height);
// here we really set the camera position
ctx.setTransform(1, 0, 0, 1, -camera.x + cw, -camera.y + ch);
ctx.strokeRect(0, 0, width, height); // just to show the original area
player.draw();
}
var
canvas,
ctx,
width = innerWidth,
height = innerHeight,
mouseX = 0,
mouseY = 0;
var camera = {
x: 0,
y: 0,
// camera
update: function(obj) {
var farthestBlobX = Math.max.apply(0, obj.blobs.map(function(cell) {
return cell.x
}));
var farthestBlobY = Math.max.apply(0, obj.blobs.map(function(cell) {
return cell.y
}));
var closestBlobX = Math.min.apply(0, obj.blobs.map(function(cell) {
return cell.x
}));
var closestBlobY = Math.min.apply(0, obj.blobs.map(function(cell) {
return cell.y
}));
this.x = (closestBlobX + farthestBlobX) / 2 || 0;
this.y = (closestBlobY + farthestBlobY) / 2 || 0;
}
},
player = {
defaultMass: 54,
x: 0,
y: 0,
blobs: [],
update: function() {
for (var i = 0; i < this.blobs.length; i++) {
var x = mouseX - this.blobs[i].x || 0;
var y = mouseY - this.blobs[i].y || 0;
var length = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
var speed = 54 / this.blobs[i].mass;
this.blobs[i].velX = x / length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].velY = y / length * speed * Math.min(1, Math.pow(x / this.blobs[i].mass, 2));
this.blobs[i].x += this.blobs[i].velX;
this.blobs[i].y += this.blobs[i].velY;
for (var j = 0; j < this.blobs.length; j++) {
if (j != i && this.blobs[i] !== undefined) {
var blob1 = this.blobs[i];
var blob2 = this.blobs[j];
var x = blob2.x - blob1.x;
var y = blob2.y - blob1.y;
var dist = Math.sqrt(x * x + y * y);
if (dist < blob1.mass + blob2.mass) {
x /= dist;
y /= dist;
blob1.x = blob2.x - x * (blob1.mass + blob2.mass);
blob1.y = blob2.y - y * (blob1.mass + blob2.mass);
}
}
}
}
this.x += (mouseX - width / 2) / (width / 2) * 1;
this.y += (mouseY - height / 2) / (height / 2) * 1;
},
split: function(cell) {
cell.mass /= 2;
this.blobs.push({
x: cell.x,
y: cell.y,
mass: cell.mass
});
},
draw: function() {
for (var i = 0; i < this.blobs.length; i++) {
ctx.fillStyle = "red";
ctx.beginPath();
ctx.arc(this.blobs[i].x, this.blobs[i].y, this.blobs[i].mass, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
}
}
};
function handleMouseMove(e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
function setup() {
canvas = document.getElementById("game");
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
addEventListener("mousemove", handleMouseMove);
player.blobs.push({
x: 10,
y: 10,
mass: player.defaultMass
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass / 2
});
player.blobs.push({
x: 100,
y: 100,
mass: player.defaultMass * 2
});
var loop = function() {
update();
draw();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
function update() {
camera.update(player);
player.update();
}
setup();
body {
margin: 0;
padding: 0;
}
<canvas id="game">kindly update your browser.</canvas>
I see there is an answer already..
var canvas;
var ctx;
var width = innerWidth;
var height = innerHeight;
var mouseX = 0;
var mouseY = 0;
const camera = {
x : 0,
y : 0,
update(obj) { // camera
this.x = (obj.blobsExtent.minx + obj.blobsExtent.maxx) / 2;
this.y = (obj.blobsExtent.miny + obj.blobsExtent.maxy) / 2;
this.x -= width / 2;
this.y -= height / 2;
}
};
const player = {
defaultMass : 54,
blobs : [],
blobsExtent : { // get the extent while updating the blobs save you having to iterate all the objects a second time to get extent
minx :0,
miny : 0,
maxx : 0,
maxy : 0,
},
update () {
var be = this.blobsExtent; // be for Blob Extent alias to save typing and make code easier to read
for (var i = 0; i < this.blobs.length; i++) {
var blob1 = this.blobs[i];
var x = mouseX - blob1.x;
var y = mouseY - blob1.y;
// to stop the divide by zero propigating NaN set length to 1 if less than 1
var length = Math.max(1,Math.sqrt(x * x + y * y)); // x * x is quicker than Math.pow(x,2)
var speed = 54 / blob1.mass;
blob1.velX = x / length * speed * Math.min(1, Math.pow(x / blob1.mass, 2));
blob1.velY = y / length * speed * Math.min(1, Math.pow(x / blob1.mass, 2));
blob1.x += blob1.velX;
blob1.y += blob1.velY;
for (var j = 0; j < this.blobs.length; j++) {
if (j != i) {
var blob2 = this.blobs[j];
var x = blob2.x - blob1.x;
var y = blob2.y - blob1.y;
var dist = Math.sqrt(x * x + y * y);
var radTotal = blob1.mass + blob2.mass;
if (dist < radTotal) {
x /= dist;
y /= dist;
blob1.x = blob2.x - x * radTotal;
blob1.y = blob2.y - y * radTotal;
}
}
}
if(i === 0){ // use first blob to setup min max
be.maxx = be.minx = blob1.x;
be.maxy = be.miny = blob1.y;
}else{
be.maxx = Math.max(be.maxx, blob1.x);
be.maxy = Math.max(be.maxy, blob1.y);
be.minx = Math.min(be.minx, blob1.x);
be.miny = Math.min(be.miny, blob1.y);
}
}
},
split (cell) {
cell.mass /= 2;
this.blobs.push(createBlob(cell.x, cell.y, cell.mass));
},
draw () {
var b; // alias for blob
ctx.fillStyle = "red"; // all the same colour then can render as one path
ctx.setTransform(1,0,0,1,-camera.x,-camera.y);
ctx.beginPath();
for (var i = 0; i < this.blobs.length; i++) {
b = this.blobs[i];
ctx.arc( b.x, b.y, b.mass, 0, Math.PI * 2);
ctx.closePath();
}
ctx.fill();
ctx.setTransform(1,0,0,1,0,0); // restore default transform
}
};
function handleMouseMove(e) {
mouseX = e.clientX + camera.x;
mouseY = e.clientY + camera.y;
}
function createBlob(x,y,mass){ return {x,y,mass} }
function setup() {
canvas = document.getElementById("game");
ctx = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
addEventListener("mousemove", handleMouseMove);
player.blobs.push(createBlob(0,0,player.defaultMass));
player.blobs.push(createBlob(100,100,player.defaultMass / 2));
player.blobs.push(createBlob(100,100,player.defaultMass * 2));
}
function update() {
camera.update(player);
player.update();
}
function draw() {
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height);
player.draw();
}
function loop() {
update();
draw();
requestAnimationFrame(loop);
}
setup();
requestAnimationFrame(loop);
body {
margin: 0;
padding: 0;
}
<canvas id="game"></canvas>

JavaScript stroke fill on click

I'm trying to to make it possible for an image on a canvas to have a box over it with low opacity, to make it be shown that it has been selected. So I need an onclick function, but i'm stuck on what to do. Any advice? I would aslo appreciate if someone could point me in the right direction on how to make the box also pulsate.
var image1 = new Kinetic.Image({
image: imageObj,
x: xposition,
y: yposition,
width: width,
height: height,
stroke: 'blue',
srokeFill: 'red',
strokeWidth: 5,
draggable: true,
dragBoundFunc: function (pos) {
if (pos.x < this.minX)
this.minX = pos.x;
return {
x: pos.x,
y: this.getAbsolutePosition().y
}
}
});
layer.on('mouseover', function (evt) {
var shape = evt.target;
document.body.style.cursor = 'pointer';
shape.strokeEnabled(true);
layer.draw();
});
layer.on('mouseout', function (evt) {
var shape = evt.target;
document.body.style.cursor = 'default';
shape.strokeEnabled(false);
layer.draw();
});
When making a clickable region on a canvas you need to.
- Create a redraw function.
- Find the mouse point inside of canvas.
- Do collision detection on the mouse point and region.
update: added multiple clickable regions.
// x1, y1, x2, y2, clicked
var boxes = [{
x1: 10,
y1: 10,
x2: 110,
y2: 110,
clicked: false
}, {
x1: 120,
y1: 10,
x2: 220,
y2: 110,
clicked: false
}];
function go() {
var can = document.getElementById('can');
var ctx = can.getContext('2d');
var w = can.width;
var h = can.height;
makeNoise(ctx);
var imageData = ctx.getImageData(0, 0, w, h);
var mx = 0;
var my = 0;
$('#can').mousemove(function(event) {
var offset = $(this).offset();
mx = event.pageX - offset.left;
my = event.pageY - offset.top;
redraw();
});
$('#can').click(function(event) {
var offset = $(this).offset();
mx = event.pageX - offset.left;
my = event.pageY - offset.top;
for (var i = 0, len = boxes.length; i < len; i++) {
var b = boxes[i];
if (hit(b.x1, b.y1, b.x2, b.y2)) {
b.clicked = !b.clicked;
}
}
redraw();
});
function redraw() {
// Draw the original image
ctx.putImageData(imageData, 0, 0);
// Draw the clickable region
for (var i = 0, len = boxes.length; i < len; i++) {
drawBox(boxes[i]);
}
// Draw the mouse. Probably only needed when testing
// mouse location.
drawMouse();
}
redraw();
// Collision dection of a square against mouse point.
// square points x1,y1 must be less than x2,y2
function hit(x1, y1, x2, y2) {
if (mx < x1 || my < y1 || mx > x2 || my > y2) return false;
return true;
}
function drawMouse() {
ctx.moveTo(mx, my);
ctx.fillStyle = "yellow";
ctx.beginPath();
ctx.arc(mx, my, 5, 0, Math.PI * 360);
ctx.fill();
}
function drawBox(b) {
if (b.clicked) {
// Mouse clicked.
ctx.fillStyle = "rgba(255,0,255,.5)"
} else if (hit(b.x1, b.y1, b.x2, b.y2)) {
// Mouse Over
ctx.fillStyle = "rgba(255,255,255,.5)"
} else {
// Mouse Out
ctx.fillStyle = "red";
}
ctx.fillRect(b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1);
}
}
// Fill a canvas context with noise.
function makeNoise(ctx) {
var can = ctx.canvas;
var imageData = ctx.getImageData(0, 0, can.width, can.height);
var d = imageData.data;
for (var i = 0, len = d.length; i < len; i += 4) {
d[i] = d[i + 1] = d[i + 2] = (Math.random() * 8) << 4;
d[i + 3] = 255;
}
ctx.putImageData(imageData, 0, 0);
}
go();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="can" width="400" height="300"></canvas>

KineticJS Animation by updating customized shape

I now have a customized Shape, and this shape is controlled by one global variable. Thus I assume I just need to change this global variable due to frame.time, erase the old shape, and create the new one.
But however it seems not working. The following is the simplified code.
<script>
var toControlShape;
var myDrawFunction(context) {
// toControlShape will be used here.
}
window.onload = function() {
var stage = new Kinetic.Stage({...});
var layer = new Kinetic.Layer();
var myShape = new Kinetic.Shape({
drawFunc: myDrawFunction,
...
});
layer.add(myShape);
stage.add(layer);
var animation = new Kinetic.Animation(function(frame) {
toControlShape = someFunction(frame.time);
myShape.remove();
myShape = new Kinetic.Shape({
drawFunc: myDrawFunction,
...
});
layer.add(myShape);
}, layer);
animation.start();
};
</script>
The shape displays properly as its initial state. But there is no animation.
I am pretty new to Javascript and HTML5. So there might be a lot of anti-patterns in this code. Pointing out them to me is also appreciated.
The complete code is here on jsFiddle
I think your doing it wrong. From the docs:
"Kinetic.Animation which modifies the shape's position with each
animation frame."
So i think you should stop remove the shape and instead just update the shape. Then it should probably the animation part work for you.
html ---
<!DOCTYPE html>
<html>
<head>
<title>Strath</title>
<meta http-equiv="X-UA-Compatible" content="IE=9" />
<script type="text/javascript" src="kinetic-v4.1.2.min.js"></script>
<script src="fiddle.js"></script>
<style type="text/css">
</style>
</head>
<body>
<div id="PureHTML5"></div>
</body>
</html>
js ---
var segsToSkip = 0;
var triangle;
window.onload = function() {
var stage = new Kinetic.Stage({
container: "PureHTML5",
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
/*
* create a triangle shape by defining a
* drawing function which draws a triangle
*/
var box = new Kinetic.Shape({
drawFunc: myDrawFunction,
stroke: "white",
strokeWidth: 8
});
var bbox= new Kinetic.Rect({
x:10,
y:10,
width:10,
height:10,
fill: 'green'
});
triangle = new Kinetic.Shape({
drawFunc: function(context) {
context.beginPath();
context.moveTo(10, 10);
context.lineTo(20, 80);
context.quadraticCurveTo(30, 10, 26, 17);
context.closePath();
context.stroke();
},
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4
});
layer.add(bbox);
// add the triangle shape to the layer
layer.add(box);
layer.add(triangle);
// add the layer to the stage
stage.add(layer);
var animation = new Kinetic.Animation(function(frame) {
console.log(frame.time);
var newSegsToSkip = Math.round(frame.time / 200);
triangle.setX(newSegsToSkip);
triangle.setDrawFunc(function(context) {
context.beginPath();
context.moveTo(newSegsToSkip, 10);
context.lineTo(newSegsToSkip+20, 80);
context.quadraticCurveTo(30, 10, 26, 17);
context.closePath();
context.stroke();
});
}, layer);
var animation2 = new Kinetic.Animation(function(frame) {
var newSegsToSkip = Math.round(frame.time / 200);
if (newSegsToSkip == segsToSkip) return;
else {
segsToSkip = newSegsToSkip;
box.remove();
box = new Kinetic.Shape({
drawFunc: myDrawFunction,
stroke: "black",
strokeWidth: 8
});
layer.add(box);
}
}, layer);
animation.start();
animation2.start();
};
var myDrawFunction = function(context) {
var x = 50;
var y = 50;
var width = 200;
var height = 200;
var radius = 20;
var dashedLength = 6;
var segsToDraw = 58;
context.beginPath();
context.drawDashedBox(x, y, width, height, radius, dashedLength, segsToSkip, segsToDraw);
context.closePath();
// context.stroke();
//this.fill(context);
this.stroke(context);
}
var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
CP.drawDashedBox = function(x, y, width, height, radius, dashedLength, segsToSkip, segsToDraw) {
// init
var env = getStratEnvForRCBox(x, y, width, height, radius, dashedLength, segsToSkip, segsToDraw);
// 'right'->'upper-right'->'down'->'bottom-right'->'left'->'bottom-left'->'up'->'upper-left'->'right'->...
while (env.segsToDraw > 0) {
console.log('drawing direction: ', env.direction, 'segsToDraw:', env.segsToDraw);
env.putToConsole();
if (env.direction == 'right') {
env = drawDashedLineNew(env, x + width - radius, y + height, dashedLength, this);
env.direction = 'bottom-right';
}
else if (env.direction == 'upper-right') {
env = drawDashedArcNew(env, x + width - radius, y + radius, radius, 0, Math.PI / 2, dashedLength, this);
env.direction = 'left';
}
else if (env.direction == 'down') {
env = drawDashedLineNew(env, x, y + height - radius, dashedLength, this);
env.direction = 'bottom-left';
}
else if (env.direction == 'bottom-right') {
env = drawDashedArcNew(env, x + width - radius, y + height - radius, radius, 3 * Math.PI / 2, 2 * Math.PI, dashedLength, this);
env.direction = 'up';
}
else if (env.direction == 'left') {
env = drawDashedLineNew(env, x + radius, y, dashedLength, this);
env.direction = 'upper-left';
}
else if (env.direction == 'bottom-left') {
env = drawDashedArcNew(env, x + radius, y + height - radius, radius, Math.PI, 3 * Math.PI / 2, dashedLength, this);
env.direction = 'right';
}
else if (env.direction == 'up') {
env = drawDashedLineNew(env, x + width, y + radius, dashedLength, this);
env.direction = 'upper-right';
}
else if (env.direction == 'upper-left') {
env = drawDashedArcNew(env, x + radius, y + radius, radius, Math.PI / 2, Math.PI, dashedLength, this);
env.direction = 'down';
}
}
}
function getStratEnvForRCBox(x, y, width, height, radius, dashLength, segsToSkip, segsToDraw) {
var direction = 'right';
var startX, startY;
if (direction == 'down') {
startX = x; startY = y + radius;
} else if (direction == 'right') {
startX = x + radius; startY = y + height;
} else if (direction == 'up') {
startX = x + width; startY = y + height - radius;
} else if (direction == 'left') {
startX = x + width - radius; startY = y;
}
var env = new Environment(startX, startY, 'gap', 0, direction, segsToSkip, segsToDraw);
return env;
}
function drawDashedLineNew(env, endX, endY, dashedLength, context) {
var dx = (endX - env.x), dy = (endY - env.y);
var angle = Math.atan2(dy, dx);
console.log('drawing line: angle =', angle, ' , ', env.gapOrDash, ' =', env.remainingLengthFromLastDraw);
var fromX = env.x, fromY = env.y;
// deal with remining
// we start loop from a fresh dash
if (env.gapOrDash == 'dash') {
// check if we need to skip
if (env.segsToSkip > 0) {
env.segsToSkip --;
} else {
context.moveTo(env.x, env.y);
context.lineTo(env.x + env.remainingLengthFromLastDraw * Math.cos(angle), env.y + env.remainingLengthFromLastDraw * Math.sin(angle));
// check if we quit
env.segsToDraw --;
if (env.segsToDraw == 0) return env;
}
// a full gap
fromX = env.x + (env.remainingLengthFromLastDraw + dashedLength) * Math.cos(angle);
fromY = env.y + (env.remainingLengthFromLastDraw + dashedLength) * Math.sin(angle);
} else if (env.gapOrDash == 'gap') {
fromX = env.x + env.remainingLengthFromLastDraw * Math.cos(angle);
fromY = env.y + env.remainingLengthFromLastDraw * Math.sin(angle);
}
var length = (endX - fromX) / Math.cos(angle);
if (endX - fromX == 0) length = Math.abs(endY - fromY);
var n = length / dashedLength;
var draw = true;
var x = fromX, y = fromY;
context.moveTo(x, y);
for (var i = 0; i < n; i++) {
x += dashedLength * Math.cos(angle);
y += dashedLength * Math.sin(angle);
if (draw) {
// check if we need to skip
if (env.segsToSkip > 0) {
env.segsToSkip --;
} else {
context.lineTo(x,y);
// check if we quit
env.segsToDraw --;
if (env.segsToDraw == 0) return env;
}
} else context.moveTo(x, y);
draw = !draw;
}
// deal with remaining
if (draw) {
// check if we need to skip
if (env.segsToSkip > 0) {
env.segsToSkip --;
} else
context.lineTo(endX, endY);
}
env.x = endX;
env.y = endY;
draw ? env.gapOrDash = 'dash' : env.gapOrDash = 'gap';
env.remainingLengthFromLastDraw = dashedLength - (endX - x) / Math.cos(angle);
return env;
}
function drawDashedArcNew(env, x, y, radius, startAngle, endAngle, dashedLength, context) {
var points = [];
var n = radius * Math.PI * 2/ dashedLength;
var stepAngle = Math.PI * 2 / n;
// deal with remaining
var angle = Math.asin(env.remainingLengthFromLastDraw / 2 / radius) * 2;
if (env.gapOrDash == 'dash') {
var angle = Math.asin(env.remainingLengthFromLastDraw / 2 / radius) * 2;
points.push({
x : (Math.cos(startAngle) * radius) + x,
y : - (Math.sin(startAngle) * radius) + y,
ex : (Math.cos(startAngle + angle) * radius) + x,
ey : - (Math.sin(startAngle + angle) * radius) + y
});
startAngle += stepAngle + angle;
} else {
startAngle += angle;
}
var draw = true;
while(startAngle + stepAngle <= endAngle) {
if (draw) {
points.push({
x : (Math.cos(startAngle) * radius) + x,
y : - (Math.sin(startAngle) * radius) + y,
ex : (Math.cos(startAngle + stepAngle) * radius) + x,
ey : - (Math.sin(startAngle + stepAngle) * radius) + y
});
}
startAngle += stepAngle;
draw = !draw;
}
// deal with the remaining
var endX = (Math.cos(endAngle) * radius) + x;
var endY = - (Math.sin(endAngle) * radius) + y;
//console.log('drawing arc: end-x:', endX, ',end-y:', endY);
if (draw) {
points.push({
x : (Math.cos(startAngle) * radius) + x,
y : - (Math.sin(startAngle) * radius) + y,
ex : endX,
ey : endY
});
}
env.x = endX;
env.y = endY;
draw ? env.gapOrDash = 'dash' : env.gapOrDash = 'gap';
env.remainingLengthFromLastDraw = dashedLength - radius * Math.sin( (endAngle - startAngle) / 2) * 2;
for(p = 0; p < points.length; p++){
//console.log('draw arc seg: from(', points[p].x, ',', points[p].y, ') to (', points[p].ex, ',', points[p].ey, ')');
// check if we need to skip
if (env.segsToSkip > 0) {
env.segsToSkip --;
} else {
context.moveTo(points[p].x, points[p].y);
context.lineTo(points[p].ex, points[p].ey);
// check if we quit
env.segsToDraw --;
if (env.segsToDraw == 0) return env;
}
}
return env;
}
function Environment(x, y, gapOrDash, remainingLengthFromLastDraw, direction, segsToSkip, segsToDraw) {
this.x = x;
this.y = y;
this.gapOrDash = gapOrDash;
this.remainingLengthFromLastDraw = remainingLengthFromLastDraw;
this.direction = direction;
this.segsToSkip = segsToSkip;
this.segsToDraw = segsToDraw;
}
Environment.prototype.putToConsole = function() {
//console.log('Environment:');
//console.log('x:', this.x, ',y:', this.y, 'direction:', this.direction);
//console.log('toSkip:', this.segsToSkip, 'toDraw:', this.segsToDraw);
}

Categories

Resources