Game Collision-detection FIX - javascript

I am making a game where it's about clicking on the nearest yellow dot from the green dot.
I got a list named dots.
You can check out my codepen to see the code I'm using.
My problem is that when you're playing the game, sometimes some of the yellow dots are too close to each other. So I am thinking if it's possible to make a collision-detection or something else, to check if the yellow dots collides?
Here is a picture of my game...
I made a red circle around the problem:
The link to my codepen project: /lolkie02/pen/PJVOdy?editors=0010
If you wanna try the game, it only works through iPhone or Android browser since I made the buttons etc. 'touchstart' in the javascript.
function getDistance(obj1, obj2) {
return Math.floor(
Math.sqrt(Math.pow(obj1.cx - obj2.cx, 2) + Math.pow(obj1.cy - obj2.cy, 2))
);
}
function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
function comparator(a, b) {
if (a[1] < b[1]) return -1;
if (a[1] > b[1]) return 1;
return 0;
}
function difference(source, toRemove) {
return source.filter(function(value) {
return toRemove.indexOf(value) == -1;
});
}
////////////////
// global vars
////////////////
var svg = document.getElementById("svg");
var dotMatrix = document.createElementNS(
"http://www.w3.org/2000/svg",
"circle"
);
var lineMatrix = document.createElementNS("http://www.w3.org/2000/svg", "line");
var screenW = window.innerWidth;
var screenH = window.innerHeight;
var totalDist = document.getElementById("distance");
////////////////
// line constructor
////////////////
function Line(x1, y1, x2, y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "line");
this.class = "line";
this.update = function(x1, y1, x2, y2) {
this.el.setAttribute("x1", x1 || this.x1);
this.el.setAttribute("y1", y1 || this.y1);
this.el.setAttribute("x2", x2 || this.x2);
this.el.setAttribute("y2", y2 || this.y2);
this.setAttr("class", this.class);
};
this.setAttr = function(attr, value) {
this.el.setAttribute(attr, value);
};
this.append = function() {
svg.insertBefore(this.el, svg.firstChild);
};
}
////////////////
// dot constructor
////////////////
function Dot(r, cx, cy) {
this.r = r;
this.cx = cx;
this.cy = cy;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.class = "dot";
this.update = function() {
this.el.setAttribute("r", this.r);
this.el.setAttribute("cx", this.cx);
this.el.setAttribute("cy", this.cy);
this.setAttr("class", this.class);
};
// activates a dot
this.activate = function() {
for (i = 0; i < dots.num; i++) {
dots.list[i].setAttr("data-selected", "false");
}
this.setAttr("data-selected", "true");
};
this.visited = function() {
this.setAttr("data-visited", "true");
};
// sets attribute to element
this.setAttr = function(attr, value) {
this.el.setAttribute(attr, value);
};
// gets attribute to element
this.getAttr = function(attr) {
return this.el.getAttribute(attr);
};
// appends element to svg and attaches event listeners
this.append = function() {
svg.appendChild(this.el);
this.el.addEventListener("touchstart", this.onClick);
};
// on click on element
this.onClick = function(event) {
//gets the id and the coords of the dot
var thisId = Number(event.target.getAttribute("data-id").substr(3, 2));
var thisCx = dots.list[thisId].cx;
var thisCy = dots.list[thisId].cy;
// calculates the distance between dots
var distances = [];
for (i = 0; i < dots.num; i++) {
distances[i] = [i, getDistance(dots.selected, dots.list[i])];
}
distances.sort(comparator);
distances.splice(0, 1);
var distancesLeft = [];
for (i = 0; i < distances.length; i++) {
if (dots.left.includes(distances[i][0])) {
distancesLeft.push(distances[i][0]);
}
}
//if the element is the nearest
if (thisId == distancesLeft[0] && dots.left.includes(thisId)) {
// calculates distances
var newDistance = getDistance(dots.list[thisId], dots.selected);
app.score.update(1); // punteggio x numero di poi
// app.score.update(newDistance); punteggio x distanza
//sets the active class to the selected dot
dots.list[thisId].activate();
dots.list[thisId].visited();
// creates the line
lines.list.push(
new Line(
dots.selected.cx,
dots.selected.cy,
dots.list[thisId].cx,
dots.list[thisId].cy
)
);
lines.list[lines.list.length - 1].update();
lines.list[lines.list.length - 1].append();
// creates the preview line
//TODO: eliminare le vecchie preline che rimangono vive
svg.addEventListener("mousemove", function prelineMove(e) {
mouseX = e.pageX;
mouseY = e.pageY;
app.preline.update(thisCx, thisCy, mouseX, mouseY);
});
//saves the selected dots coordinates
dots.selected.id = thisId;
dots.selected.cx = thisCx;
dots.selected.cy = thisCy;
//removes the dot from the list of remaining dots
for (i = 0; i < dots.left.length; i++) {
if (dots.left[i] === thisId) {
dots.left.splice(i, 1);
}
}
if (dots.left.length == 0) {
app.end(true);
}
} else {
app.end(false);
}
};
}
////////////////
// lines group
////////////////
var lines = {
list: []
};
////////////////
// dots group
////////////////
var dots = {};
dots.num = 20;
dots.list = [];
dots.start = 0;
dots.selected = {};
dots.selected.id = dots.start;
dots.left = [];
dots.preline;
////////////////
// app
////////////////
var app = {};
app.level = 2;
app.score = {};
app.score.number = 0;
app.score.el = document.getElementById("score");
app.score.update = function(score) {
app.score.number += score;
app.score.el.textContent = app.score.number;
};
app.score.reset = function() {
app.score.number = 0;
app.score.update(0);
};
app.results = function(points) {
if (points == "reset") {
sessionStorage.setItem("results", 0);
} else {
if (!sessionStorage.getItem("results")) {
sessionStorage.setItem("results", points);
} else {
var newscore = points;
sessionStorage.setItem("results", newscore);
}
}
};
app.launchScreen = function(lastScore, title, description, btnText) {
app.launchScreen.el = document.getElementById("launch-screen");
app.launchScreen.el.setAttribute("class", "is-visible");
var launchScreenTitle = document.getElementById("launch-screen__title");
launchScreenTitle.textContent = title;
var launchScreenDescription = document.getElementById(
"launch-screen__description"
);
launchScreenDescription.textContent = description;
app.launchScreen.btn = document.getElementById("start-btn");
app.launchScreen.btn.textContent = btnText;
app.launchScreen.btn.addEventListener("touchstart", function lauch() {
app.launchScreen.el.setAttribute("class", "");
app.start(app.level);
document.getElementById("score2").style.display = "block";
app.launchScreen.btn.removeEventListener("touchstart", lauch);
});
};
app.preline = new Line(0, 0, 200, 200);
app.preline.setAttr("id", "preline");
app.start = function(dotsNum) {
dots.num = dotsNum;
for (i = 0; i < dots.num; i++) {
var cx = getRandomArbitrary(45, screenW - 45);
var cy = getRandomArbitrary(45, screenH - 45);
dots.list[i] = new Dot(14, cx, cy);
dots.list[i].setAttr("data-id", "id-" + i);
dots.list[i].setAttr(
"style",
"animation-delay:" + i / 10 + "s; transform-origin: " + cx + 'px ' + cy + 'px;');
dots.list[i].update();
dots.list[i].append();
dots.left.push(i);
if (i == dots.start) {
dots.selected.cx = dots.list[dots.start].cx;
dots.selected.cy = dots.list[dots.start].cy;
dots.list[dots.start].setAttr("class", "dot dot--starting");
dots.left.splice(i, 1);
}
// adds the preline
app.preline.update(
dots.selected.cx,
dots.selected.cy,
dots.selected.cx,
dots.selected.cy
);
app.preline.append();
svg.addEventListener("mousemove", function prelineMove(e) {
mouseX = e.pageX;
mouseY = e.pageY;
app.preline.update(dots.selected.cx, dots.selected.cy, mouseX, mouseY);
});
}
// sets starting point
dots.list[dots.start].setAttr("data-selected", "true");
};
app.end = function(win) {
if (win) {
app.level += 2;
app.results(app.score.number);
} else {
app.level = 2;
}
dots.list = [];
dots.selected = {};
dots.left.length = 0;
svg.innerHTML = "";
if (win) {
app.launchScreen(
app.score.number,
"", //"Sådan!",
"", //"Din score er nu: " + sessionStorage.getItem("results") + ' Det næste level vil blive endnu hårdere.',
"NÆSTE LEVEL"
);
} else {
app.launchScreen(
0,
"", //"ARGH!",
"", //"Din endelige score blev: " + sessionStorage.getItem("results"),
"PRØV IGEN"
);
app.results("reset");
app.score.reset();
var score2 = document.getElementById('score2');
var number = score2.innerHTML;
number = 0;
score2.innerHTML = number;
document.getElementById("score2").style.display = "none";
}
};
app.launchScreen(
0,
"STIFINDER",
"Find den tætteste gule prik",
"SPIL"
);
$('.btn').on('touchstart',function(e,data) {
var score2 = document.getElementById('score2');
var number = score2.innerHTML;
number++;
score2.innerHTML = number;
});

Use Pythagorean theorem to determine whether the distance of the centers of two dots are closer (or equal) to the sum of their radii - in that case you have collision.
My answer to the similar question :https://stackoverflow.com/a/46973584/4154250

Related

Two signature pads in one form

I want to implement two signature pads in ONE form. One signature is for the applicant and the other one is for the evaluator.
The first pad works but the second pad is unresponsive. I am using JavaScript for the signature pads but it only works for the first pad. The signature will be saved to the database when the submit button is clicked. That is why id="save-signature-btn" is together with the code for the 'Submit' button.
form.blade.php
#extends('layouts.app')
#section('content')
<!doctype html>
<html lang="en">
<head>
</head>
<body>
{!! Form::open(['url' => 'page3/submit']) !!}
<h4 style="text-decoration: underline; font-weight: bold">Approved By:</h4>
<table class="table table-bordered">
<tr>
<th colspan="3">Approved By:</th>
</tr>
<tr>
<th colspan="1">Name</th>
<th colspan="1">Signature</th>
<th colspan="1">Date</th>
</tr>
<tr colspan=4>
<td colspan="1">
<div class="form-group">
{{Form::text('Officer_Name', '', ['class' => 'form-control', 'placeholder' => 'John Smith'])}}
</div>
</td>
<td colspan="1">
<div class="form-group">
<canvas id="signature-canvas" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>
<div id="signature-message"></div>
<div id="signature-buttons">
<input type="button" id="clear-signature-btn" value="Clear">
</div>
<input type="hidden" name="officer_signature" id="signature-data" value="">
</div>
</td>
<td>
<div class="form-group">
{{Form::date('Approval_Date', '', ['class' => 'form-control'])}}
</div>
</td>
</tr>
</table>
<br/>
<h4 style="text-decoration: underline; font-weight: bold">Applicant Signature:</h4>
<div class="form-group">
<canvas id="signature-canvas2" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>
<div id="signature-message2"></div>
<div id="signature-buttons2">
<input type="button" id="clear-signature-btn2" value="Clear">
</div>
<input type="hidden" name="applicant_signature" id="signature-data2" value="">
</div>
<br>
<div class="signature_pad_save">
<button type="submit" class="btn btn-primary" id="save-signature-btn">Submit</button>
</div>
<script src="js/signature_pad.js"></script>
<script src="js/signature_data.js"></script>
</body>
</html>
#endsection('content')
signature data.js
var clearButton = document.getElementById('clear-signature-btn'),
saveButton = document.getElementById('save-signature-btn'),
canvas = document.getElementById('signature-canvas'),
signaturePad;
function resizeCanvas() {
var ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
}
window.onresize = resizeCanvas;
resizeCanvas();
signaturePad = new SignaturePad(canvas);
clearButton.addEventListener('click', function (event) {
signaturePad.clear();
});
saveButton.addEventListener('click', function (event) {
if (signaturePad.isEmpty()) {
alert('Signature pad is blank. Please draw your signature.');
} else {
var sdata = signaturePad.toDataURL();
document.getElementById('signature-data').value = sdata;
document.getElementById('signature-form').submit();
}
});
signature pad.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.SignaturePad = factory());
}(this, (function () { 'use strict';
function Point(x, y, time) {
this.x = x;
this.y = y;
this.time = time || new Date().getTime();
}
Point.prototype.velocityFrom = function (start) {
return this.time !== start.time ? this.distanceTo(start) / (this.time - start.time) : 1;
};
Point.prototype.distanceTo = function (start) {
return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2));
};
Point.prototype.equals = function (other) {
return this.x === other.x && this.y === other.y && this.time === other.time;
};
function Bezier(startPoint, control1, control2, endPoint) {
this.startPoint = startPoint;
this.control1 = control1;
this.control2 = control2;
this.endPoint = endPoint;
}
// Returns approximated length.
Bezier.prototype.length = function () {
var steps = 10;
var length = 0;
var px = void 0;
var py = void 0;
for (var i = 0; i <= steps; i += 1) {
var t = i / steps;
var cx = this._point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
var cy = this._point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
if (i > 0) {
var xdiff = cx - px;
var ydiff = cy - py;
length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);
}
px = cx;
py = cy;
}
return length;
};
/* eslint-disable no-multi-spaces, space-in-parens */
Bezier.prototype._point = function (t, start, c1, c2, end) {
return start * (1.0 - t) * (1.0 - t) * (1.0 - t) + 3.0 * c1 * (1.0 - t) * (1.0 - t) * t + 3.0 * c2 * (1.0 - t) * t * t + end * t * t * t;
};
/* eslint-disable */
// http://stackoverflow.com/a/27078401/815507
function throttle(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function later() {
previous = options.leading === false ? 0 : Date.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function () {
var now = Date.now();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
}
function SignaturePad(canvas, options) {
var self = this;
var opts = options || {};
this.velocityFilterWeight = opts.velocityFilterWeight || 0.7;
this.minWidth = opts.minWidth || 0.5;
this.maxWidth = opts.maxWidth || 2.5;
this.throttle = 'throttle' in opts ? opts.throttle : 16; // in miliseconds
this.minDistance = 'minDistance' in opts ? opts.minDistance : 5;
if (this.throttle) {
this._strokeMoveUpdate = throttle(SignaturePad.prototype._strokeUpdate, this.throttle);
} else {
this._strokeMoveUpdate = SignaturePad.prototype._strokeUpdate;
}
this.dotSize = opts.dotSize || function () {
return (this.minWidth + this.maxWidth) / 2;
};
this.penColor = opts.penColor || 'black';
this.backgroundColor = opts.backgroundColor || 'rgba(0,0,0,0)';
this.onBegin = opts.onBegin;
this.onEnd = opts.onEnd;
this._canvas = canvas;
this._ctx = canvas.getContext('2d');
this.clear();
// We need add these inline so they are available to unbind while still having
// access to 'self' we could use _.bind but it's not worth adding a dependency.
this._handleMouseDown = function (event) {
if (event.which === 1) {
self._mouseButtonDown = true;
self._strokeBegin(event);
}
};
this._handleMouseMove = function (event) {
if (self._mouseButtonDown) {
self._strokeMoveUpdate(event);
}
};
this._handleMouseUp = function (event) {
if (event.which === 1 && self._mouseButtonDown) {
self._mouseButtonDown = false;
self._strokeEnd(event);
}
};
this._handleTouchStart = function (event) {
if (event.targetTouches.length === 1) {
var touch = event.changedTouches[0];
self._strokeBegin(touch);
}
};
this._handleTouchMove = function (event) {
// Prevent scrolling.
event.preventDefault();
var touch = event.targetTouches[0];
self._strokeMoveUpdate(touch);
};
this._handleTouchEnd = function (event) {
var wasCanvasTouched = event.target === self._canvas;
if (wasCanvasTouched) {
event.preventDefault();
self._strokeEnd(event);
}
};
// Enable mouse and touch event handlers
this.on();
}
// Public methods
SignaturePad.prototype.clear = function () {
var ctx = this._ctx;
var canvas = this._canvas;
ctx.fillStyle = this.backgroundColor;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(0, 0, canvas.width, canvas.height);
this._data = [];
this._reset();
this._isEmpty = true;
};
SignaturePad.prototype.fromDataURL = function (dataUrl) {
var _this = this;
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var image = new Image();
var ratio = options.ratio || window.devicePixelRatio || 1;
var width = options.width || this._canvas.width / ratio;
var height = options.height || this._canvas.height / ratio;
this._reset();
image.src = dataUrl;
image.onload = function () {
_this._ctx.drawImage(image, 0, 0, width, height);
};
this._isEmpty = false;
};
SignaturePad.prototype.toDataURL = function (type) {
var _canvas;
switch (type) {
case 'image/svg+xml':
return this._toSVG();
default:
for (var _len = arguments.length, options = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
options[_key - 1] = arguments[_key];
}
return (_canvas = this._canvas).toDataURL.apply(_canvas, [type].concat(options));
}
};
SignaturePad.prototype.on = function () {
this._handleMouseEvents();
this._handleTouchEvents();
};
SignaturePad.prototype.off = function () {
this._canvas.removeEventListener('mousedown', this._handleMouseDown);
this._canvas.removeEventListener('mousemove', this._handleMouseMove);
document.removeEventListener('mouseup', this._handleMouseUp);
this._canvas.removeEventListener('touchstart', this._handleTouchStart);
this._canvas.removeEventListener('touchmove', this._handleTouchMove);
this._canvas.removeEventListener('touchend', this._handleTouchEnd);
};
SignaturePad.prototype.isEmpty = function () {
return this._isEmpty;
};
// Private methods
SignaturePad.prototype._strokeBegin = function (event) {
this._data.push([]);
this._reset();
this._strokeUpdate(event);
if (typeof this.onBegin === 'function') {
this.onBegin(event);
}
};
SignaturePad.prototype._strokeUpdate = function (event) {
var x = event.clientX;
var y = event.clientY;
var point = this._createPoint(x, y);
var lastPointGroup = this._data[this._data.length - 1];
var lastPoint = lastPointGroup && lastPointGroup[lastPointGroup.length - 1];
var isLastPointTooClose = lastPoint && point.distanceTo(lastPoint) < this.minDistance;
// Skip this point if it's too close to the previous one
if (!(lastPoint && isLastPointTooClose)) {
var _addPoint = this._addPoint(point),
curve = _addPoint.curve,
widths = _addPoint.widths;
if (curve && widths) {
this._drawCurve(curve, widths.start, widths.end);
}
this._data[this._data.length - 1].push({
x: point.x,
y: point.y,
time: point.time,
color: this.penColor
});
}
};
SignaturePad.prototype._strokeEnd = function (event) {
var canDrawCurve = this.points.length > 2;
var point = this.points[0]; // Point instance
if (!canDrawCurve && point) {
this._drawDot(point);
}
if (point) {
var lastPointGroup = this._data[this._data.length - 1];
var lastPoint = lastPointGroup[lastPointGroup.length - 1]; // plain object
// When drawing a dot, there's only one point in a group, so without this check
// such group would end up with exactly the same 2 points.
if (!point.equals(lastPoint)) {
lastPointGroup.push({
x: point.x,
y: point.y,
time: point.time,
color: this.penColor
});
}
}
if (typeof this.onEnd === 'function') {
this.onEnd(event);
}
};
SignaturePad.prototype._handleMouseEvents = function () {
this._mouseButtonDown = false;
this._canvas.addEventListener('mousedown', this._handleMouseDown);
this._canvas.addEventListener('mousemove', this._handleMouseMove);
document.addEventListener('mouseup', this._handleMouseUp);
};
SignaturePad.prototype._handleTouchEvents = function () {
// Pass touch events to canvas element on mobile IE11 and Edge.
this._canvas.style.msTouchAction = 'none';
this._canvas.style.touchAction = 'none';
this._canvas.addEventListener('touchstart', this._handleTouchStart);
this._canvas.addEventListener('touchmove', this._handleTouchMove);
this._canvas.addEventListener('touchend', this._handleTouchEnd);
};
SignaturePad.prototype._reset = function () {
this.points = [];
this._lastVelocity = 0;
this._lastWidth = (this.minWidth + this.maxWidth) / 2;
this._ctx.fillStyle = this.penColor;
};
SignaturePad.prototype._createPoint = function (x, y, time) {
var rect = this._canvas.getBoundingClientRect();
return new Point(x - rect.left, y - rect.top, time || new Date().getTime());
};
SignaturePad.prototype._addPoint = function (point) {
var points = this.points;
var tmp = void 0;
points.push(point);
if (points.length > 2) {
// To reduce the initial lag make it work with 3 points
// by copying the first point to the beginning.
if (points.length === 3) points.unshift(points[0]);
tmp = this._calculateCurveControlPoints(points[0], points[1], points[2]);
var c2 = tmp.c2;
tmp = this._calculateCurveControlPoints(points[1], points[2], points[3]);
var c3 = tmp.c1;
var curve = new Bezier(points[1], c2, c3, points[2]);
var widths = this._calculateCurveWidths(curve);
// Remove the first element from the list,
// so that we always have no more than 4 points in points array.
points.shift();
return { curve: curve, widths: widths };
}
return {};
};
SignaturePad.prototype._calculateCurveControlPoints = function (s1, s2, s3) {
var dx1 = s1.x - s2.x;
var dy1 = s1.y - s2.y;
var dx2 = s2.x - s3.x;
var dy2 = s2.y - s3.y;
var m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 };
var m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 };
var l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
var l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
var dxm = m1.x - m2.x;
var dym = m1.y - m2.y;
var k = l2 / (l1 + l2);
var cm = { x: m2.x + dxm * k, y: m2.y + dym * k };
var tx = s2.x - cm.x;
var ty = s2.y - cm.y;
return {
c1: new Point(m1.x + tx, m1.y + ty),
c2: new Point(m2.x + tx, m2.y + ty)
};
};
SignaturePad.prototype._calculateCurveWidths = function (curve) {
var startPoint = curve.startPoint;
var endPoint = curve.endPoint;
var widths = { start: null, end: null };
var velocity = this.velocityFilterWeight * endPoint.velocityFrom(startPoint) + (1 - this.velocityFilterWeight) * this._lastVelocity;
var newWidth = this._strokeWidth(velocity);
widths.start = this._lastWidth;
widths.end = newWidth;
this._lastVelocity = velocity;
this._lastWidth = newWidth;
return widths;
};
SignaturePad.prototype._strokeWidth = function (velocity) {
return Math.max(this.maxWidth / (velocity + 1), this.minWidth);
};
SignaturePad.prototype._drawPoint = function (x, y, size) {
var ctx = this._ctx;
ctx.moveTo(x, y);
ctx.arc(x, y, size, 0, 2 * Math.PI, false);
this._isEmpty = false;
};
SignaturePad.prototype._drawCurve = function (curve, startWidth, endWidth) {
var ctx = this._ctx;
var widthDelta = endWidth - startWidth;
var drawSteps = Math.floor(curve.length());
ctx.beginPath();
for (var i = 0; i < drawSteps; i += 1) {
// Calculate the Bezier (x, y) coordinate for this step.
var t = i / drawSteps;
var tt = t * t;
var ttt = tt * t;
var u = 1 - t;
var uu = u * u;
var uuu = uu * u;
var x = uuu * curve.startPoint.x;
x += 3 * uu * t * curve.control1.x;
x += 3 * u * tt * curve.control2.x;
x += ttt * curve.endPoint.x;
var y = uuu * curve.startPoint.y;
y += 3 * uu * t * curve.control1.y;
y += 3 * u * tt * curve.control2.y;
y += ttt * curve.endPoint.y;
var width = startWidth + ttt * widthDelta;
this._drawPoint(x, y, width);
}
ctx.closePath();
ctx.fill();
};
SignaturePad.prototype._drawDot = function (point) {
var ctx = this._ctx;
var width = typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;
ctx.beginPath();
this._drawPoint(point.x, point.y, width);
ctx.closePath();
ctx.fill();
};
SignaturePad.prototype._fromData = function (pointGroups, drawCurve, drawDot) {
for (var i = 0; i < pointGroups.length; i += 1) {
var group = pointGroups[i];
if (group.length > 1) {
for (var j = 0; j < group.length; j += 1) {
var rawPoint = group[j];
var point = new Point(rawPoint.x, rawPoint.y, rawPoint.time);
var color = rawPoint.color;
if (j === 0) {
// First point in a group. Nothing to draw yet.
// All points in the group have the same color, so it's enough to set
// penColor just at the beginning.
this.penColor = color;
this._reset();
this._addPoint(point);
} else if (j !== group.length - 1) {
// Middle point in a group.
var _addPoint2 = this._addPoint(point),
curve = _addPoint2.curve,
widths = _addPoint2.widths;
if (curve && widths) {
drawCurve(curve, widths, color);
}
} else {
// Last point in a group. Do nothing.
}
}
} else {
this._reset();
var _rawPoint = group[0];
drawDot(_rawPoint);
}
}
};
SignaturePad.prototype._toSVG = function () {
var _this2 = this;
var pointGroups = this._data;
var canvas = this._canvas;
var ratio = Math.max(window.devicePixelRatio || 1, 1);
var minX = 0;
var minY = 0;
var maxX = canvas.width / ratio;
var maxY = canvas.height / ratio;
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttributeNS(null, 'width', canvas.width);
svg.setAttributeNS(null, 'height', canvas.height);
this._fromData(pointGroups, function (curve, widths, color) {
var path = document.createElement('path');
// Need to check curve for NaN values, these pop up when drawing
// lines on the canvas that are not continuous. E.g. Sharp corners
// or stopping mid-stroke and than continuing without lifting mouse.
if (!isNaN(curve.control1.x) && !isNaN(curve.control1.y) && !isNaN(curve.control2.x) && !isNaN(curve.control2.y)) {
var attr = 'M ' + curve.startPoint.x.toFixed(3) + ',' + curve.startPoint.y.toFixed(3) + ' ' + ('C ' + curve.control1.x.toFixed(3) + ',' + curve.control1.y.toFixed(3) + ' ') + (curve.control2.x.toFixed(3) + ',' + curve.control2.y.toFixed(3) + ' ') + (curve.endPoint.x.toFixed(3) + ',' + curve.endPoint.y.toFixed(3));
path.setAttribute('d', attr);
path.setAttribute('stroke-width', (widths.end * 2.25).toFixed(3));
path.setAttribute('stroke', color);
path.setAttribute('fill', 'none');
path.setAttribute('stroke-linecap', 'round');
svg.appendChild(path);
}
}, function (rawPoint) {
var circle = document.createElement('circle');
var dotSize = typeof _this2.dotSize === 'function' ? _this2.dotSize() : _this2.dotSize;
circle.setAttribute('r', dotSize);
circle.setAttribute('cx', rawPoint.x);
circle.setAttribute('cy', rawPoint.y);
circle.setAttribute('fill', rawPoint.color);
svg.appendChild(circle);
});
var prefix = 'data:image/svg+xml;base64,';
var header = '<svg' + ' xmlns="http://www.w3.org/2000/svg"' + ' xmlns:xlink="http://www.w3.org/1999/xlink"' + (' viewBox="' + minX + ' ' + minY + ' ' + maxX + ' ' + maxY + '"') + (' width="' + maxX + '"') + (' height="' + maxY + '"') + '>';
var body = svg.innerHTML;
// IE hack for missing innerHTML property on SVGElement
if (body === undefined) {
var dummy = document.createElement('dummy');
var nodes = svg.childNodes;
dummy.innerHTML = '';
for (var i = 0; i < nodes.length; i += 1) {
dummy.appendChild(nodes[i].cloneNode(true));
}
body = dummy.innerHTML;
}
var footer = '</svg>';
var data = header + body + footer;
return prefix + btoa(data);
};
SignaturePad.prototype.fromData = function (pointGroups) {
var _this3 = this;
this.clear();
this._fromData(pointGroups, function (curve, widths) {
return _this3._drawCurve(curve, widths.start, widths.end);
}, function (rawPoint) {
return _this3._drawDot(rawPoint);
});
this._data = pointGroups;
};
SignaturePad.prototype.toData = function () {
return this._data;
};
return SignaturePad;
})));
In your javascript code you are working only with
canvas = document.getElementById('signature-canvas')
So that is the problem.
You should add a class on both signature canvases in html code for example signature like this:
<canvas id="signature-canvas" class="signature" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>
<canvas id="signature-canvas2" class="signature" style="width:375px;height:150px;max-width:100%;border:8px #CCC solid;background-color: white;"></canvas>
And then in javascript add one more pair of commands for second signature pad for control buttons (submit and reset) for second canvas.

Javascript, How to stop or pause the setInterval timer in this code?

I have a code for a slideshow that runs automatically and all I want is to stop the timer when I click on the image and pause it when i hover over it.
I tried the clearinterval function but it didn't work at all, so I need your help please.
This is the JavaScript code:
var m3D = function() {
var e = 4;
var t = [],
n, r, i, s, o,
u = "",
a = "",
f = {
x: 0,
y: 0,
z: -650,
s: 0,
fov: 500
},
l = 0,
c = 0;
f.setTarget = function(e, t, n) {
if (Math.abs(t - e) > .1) {
f.s = 1;
f.p = 0;
f.d = t - e;
if (n) {
f.d *= 2;
f.p = 9
}
}
};
f.tween = function(e) {
if (f.s != 0) {
f.p += f.s;
f[e] += f.d * f.p * .01;
if (f.p == 10) f.s = -1;
else if (f.p == 0) f.s = 0
}
return f.s
};
var h = function(k, l, c, h, p) {
if (l) {
this.url = l.url;
this.title = l.title;
this.color = l.color;
this.isLoaded = false;
if (document.createElement("canvas").getContext) {
this.srcImg = new Image;
this.srcImg.src = u + l.src;
this.img = document.createElement("canvas");
this.canvas = true;
r.appendChild(this.img)
} else {
this.img = document.createElement("img");
this.img.src = u + l.src;
r.appendChild(this.img)
}
function v(e, t) {
return Math.floor(Math.random() * (t - e + 1)) + e
}
function m() {
var e = t.length;
var n = v(0, t.length);
l.src = u + "photo" + n + ".jpg";
if (f.s) return;
try {
if (t[n].canvas == true) {
f.tz = t[n].z - f.fov;
f.tx = t[n].x;
f.ty = t[n].y;
if (s) {
s.but.className = "button viewed";
s.img.className = "";
s.img.style.cursor = "pointer";
s.urlActive = false;
o.style.visibility = "hidden"
}
t[n].img.className = "button selected";
d(false);
s = t[n]
} else {}
} catch (r) {}
}
// this is the Interval timer
var g = setInterval(m, 6e3);
this.img.onclick = function()
{
/*
i want to reset the timer OR increase it when i click here
*/
alert("click");
if (f.s) return;
if (this.diapo.isLoaded) {
if (this.diapo.urlActive) {
top.location.href = this.diapo.url
} else {
f.tz = this.diapo.z - f.fov;
f.tx = this.diapo.x;
f.ty = this.diapo.y;
if (s) {
s.but.className = "button viewed";
s.img.className = "";
s.img.style.cursor = "pointer";
s.urlActive = false;
o.style.visibility = "hidden"
}
this.diapo.but.className = "button selected";
d(false);
s = this.diapo
}
}
};
this.but = document.createElement("div");
this.Img = document.createElement("Img");
this.but.className = "button";
this.Img.src = a + l.src;
this.but.appendChild(this.Img);
i.appendChild(this.but);
this.but.diapo = this;
this.Img.style.left = Math.round(this.but.offsetWidth * 1.2 * (k % e)) + "px";
this.Img.style.top = Math.round(this.but.offsetHeight * 1.2 * Math.floor(k / e)) + "px";
this.Img.style.zIndex = "50";
this.but.onclick = this.img.onclick;
n = this.img;
this.img.diapo = this;
this.zi = 25e3
} else {
this.img = document.createElement("div");
this.isLoaded = true;
this.img.className = "fog";
r.appendChild(this.img);
this.w = 300;
this.h = 300;
this.zi = 15e3
}
this.x = c;
this.y = h;
this.z = p;
this.css = this.img.style
};
h.prototype.anim = function() {
if (this.isLoaded) {
var e = this.x - f.x;
var t = this.y - f.y;
var n = this.z - f.z;
if (n < 20) n += 5e3;
var r = f.fov / n;
var i = this.w * r;
var s = this.h * r;
this.css.left = Math.round(l + e * r - i * .5) + "px";
this.css.top = Math.round(c + t * r - s * .5) + "px";
this.css.width = Math.round(i) + "px";
this.css.height = Math.round(s) + "px";
this.css.zIndex = this.zi - Math.round(n)
} else {
this.isLoaded = this.loading()
}
};
h.prototype.loading = function() {
if (this.canvas && this.srcImg.complete || this.img.complete) {
if (this.canvas) {
this.w = this.srcImg.width;
this.h = this.srcImg.height;
this.img.width = this.w;
this.img.height = this.h;
var e = this.img.getContext("2d");
e.drawImage(this.srcImg, 0, 0, this.w, this.h)
} else {
this.w = this.img.width;
this.h = this.img.height
}
this.but.className += " loaded";
return true
}
return false
};
var p = function() {
l = r.offsetWidth * .5;
c = r.offsetHeight * .5
};
var d = function(e) {
var n = 0,
r;
while (r = t[n++]) {
if (r.but) {
r.css.msInterpolationMode = e ? "bicubic" : "nearest-neighbor";
r.css.imageRendering = e ? "optimizeQuality" : "optimizeSpeed"
}
}
};
var v = function(e) {
r = document.getElementById("screen");
i = document.getElementById("bar");
o = document.getElementById("urlInfo");
p();
var n = 0,
s, u = e.length;
while (s = e[n++]) {
var a = 1e3 * (n % 4 - 1.5);
var f = Math.round(Math.random() * 4e3) - 2e3;
var l = n * (5e3 / u);
t.push(new h(n - 1, s, a, f, l));
var c = t.length - 1;
for (var d = 0; d < 3; d++) {
var a = Math.round(Math.random() * 4e3) - 2e3;
var f = Math.round(Math.random() * 4e3) - 2e3;
t.push(new h(c, null, a, f, l + 100))
}
/*
var d = t.length - 1;
for (var v = 0; v < 3; v++) {
var a = Math.round(Math.random() * 4e3) - 2e3;
var f = Math.round(Math.random() * 4e3) - 2e3;
t.push(new h(d, null, a, f, l + 100))
}
*/
}
m()
};
var m = function() {
if (f.tx) {
if (!f.s) f.setTarget(f.x, f.tx);
var e = f.tween("x");
if (!e) f.tx = 0
} else if (f.ty) {
if (!f.s) f.setTarget(f.y, f.ty);
var e = f.tween("y");
if (!e) f.ty = 0
} else if (f.tz) {
if (!f.s) f.setTarget(f.z, f.tz);
var e = f.tween("z");
if (!e) {
f.tz = 0;
d(true);
if (s.url) {
s.img.style.cursor = "pointer";
s.urlActive = true;
s.img.className = "href";
o.diapo = s;
o.onclick = s.img.onclick;
o.innerHTML = s.title || s.url;
o.style.visibility = "visible";
o.style.color = s.color || "#fff";
o.style.top = Math.round(s.img.offsetTop + s.img.offsetHeight - o.offsetHeight - 5) + "px";
o.style.left = Math.round(s.img.offsetLeft + s.img.offsetWidth - o.offsetWidth - 5) + "px"
} else {
s.img.style.cursor = "default"
}
/*
i want to pause the timer when i hover here
*/
s.img.onmouseover = function(){
alert("mouseover");
};
}
}
var n = 0,
r;
while (r = t[n++]) r.anim();
var g = setTimeout(m, 32)
};
return {
init: v
}
}()
And as you see, on line 90 I have the setInterval timer function and after it the onclick function where I need to "reset" the timer, and on line 270 the onmouseover function where I need to "pause" the timer.
So how to do this?
Try using a flag variable. Add var pauseSlideshow = false; somewhere at the top of the file, so it will be in the global scope. Change the m()function like so:
var m = function() {
if(!pauseSlideshow) {
/*
*
* all of the code already in m()
*
*/
} // make sure to add this additional curly brace
}
And then you need an onmouseover and an onmouseout function to toggle pauseSlideshow, like this:
s.img.onmouseover = function() {
pauseSlideshow = true;
};
s.img.onmouseout = function() {
pauseSlideshow = false;
};

JavaScript: Functions give "is not a function" when looped [duplicate]

This question already has answers here:
Pass correct "this" context to setTimeout callback?
(6 answers)
Closed 7 years ago.
When I run the tick() function once it works flawlessly, but when I loop it using setInterval(this.tick,this.interval) all the functions in tick() give the following error: Uncaught TypeError: this.{a function} is not a function.
This is the full code:
function Particles(settings){
this.canvas = document.getElementById('particle-js');
this.context = this.canvas.getContext('2d');
this.fps = 60;
this.interval = 1000/this.fps;
this.TWO_PI = Math.PI*2;
this.mousePosition;
this.tick = function(){
console.log("tick");
this.drawNodes();
this.clear();
}
setInterval(this.tick,this.interval);
this.generateNodes = function generateNodes(){
var nodes = [];
for(var i = 0; i < 1; i++){
var node = {
origin: {
x: this.random(0, this.canvas.width),
y: this.random(0, this.canvas.height)
},
direction: this.random(0,359),
subNodes: []
}
for(var j = 0; j < this.random(1,8); j++){
var subNode = {
xOffset: this.random(-50,50),
yOffset: this.random(-50,50),
distance: function(){
var x = Math.pow(this.xOffset,2);
var y = Math.pow(this.yOffset,2);
return Math.sqrt(x + y);
}
}
while(subNode.distance() < 20){
subNode = {
xOffset: this.random(-50,50),
yOffset: this.random(-50,50),
distance: function(){
var x = Math.pow(this.xOffset,2);
var y = Math.pow(this.yOffset,2);
return Math.sqrt(x + y);
}
}
}
node.subNodes.push(subNode);
}
nodes.push(node);
}
console.log("generated: " + nodes.length);
return nodes;
}
this.canvas.addEventListener('mousemove', function(evt) {
if(evt.offsetX) {
mouseX = evt.offsetX;
mouseY = evt.offsetY;
}
else if(e.layerX) {
mouseX = evt.layerX;
mouseY = evt.layerY;
}
this.mousePos = {
x: mouseX,
y: mouseY
}
}, false);
this.drawNodes = function drawNodes(){
for(var k = 0; k < this.nodes.length; k++){
var current_node = this.nodes[k];
this.fillCircle(current_node.origin.x,current_node.origin.y, 3);
for(var l = 0; l < current_node.subNodes.length; l++){
var current_subNode = current_node.subNodes[l];
this.fillLine(current_node.origin.x,current_node.origin.y,current_node.origin.x + current_subNode.xOffset, current_node.origin.y + current_subNode.yOffset)
this.fillCircle(current_node.origin.x + current_subNode.xOffset, current_node.origin.y + current_subNode.yOffset, 2);
}
}
}
this.fillCircle = function fillCircle(x, y, radius, color){
if(color == undefined || color == false){
color = "black";
}
this.context.fillStyle = color;
this.context.beginPath();
this.context.arc(x,y,radius,0,this.TWO_PI,false);
this.context.fill();
}
this.fillLine = function fillLine(xFrom, yFrom, xTo, yTo, color){
if(color == undefined || color == false){
color = "black";
}
this.context.beginPath();
this.context.moveTo(xFrom,yFrom);
this.context.lineTo(xTo, yTo);
this.context.lineWidth = 1;
this.context.stroke();
}
this.clear = function clear(color){
if(color == undefined || color == false){
color = "white";
}
this.context.fillStyle = color;
this.context.fillRect(0,0,this.canvas.width,this.canvas.height);
}
this.random = function random(min, max){
return min+Math.round((max-min)*Math.random());
}
this.nodes = this.generateNodes();
}
The following is shown in console:
That's because the setTimeout callback function's context isn't bound to your object, try this instead:
setInterval(this.tick.bind(this), this.interval);

How to make an array of graphic circles that I can redraw to the screen on intervals?

I want to draw circles on the screen but I want to store them in an array for later use in building a centipede type game. I am somewhat new to object in Javascript.
My object is Circles as below.
function Circles(x,y,r) {
var cX = x;
var cY = y;
var cR = r;
}
I want to create an array of say 50 circles that I can loop through and display to the screen because currently I have a square that moves around the screen that I can control with the left and right keys.
I want to redraw the array to the screen.
**How can I create the array?"
Code:
<script type="text/javascript">
var theCanvas=document.getElementById("myCanvas");
var canvasContext=theCanvas.getContext("2d");
var radX;
var radY;
var radR;
var context;
var numCircle = 50;
var circleArray = new Circles(50);
function Circles(x,y,r) {
var cX = x;
var cY = y;
var cR = r;
}
function clearCanvas() {
//context.clearRect(0,0,WIDTH,HEIGHT);
}
function drawCircle(x,y,r,context) {
context.beginPath();
context.arc(x,y,r,0,Math.PI*2,true);
context.closePath();
context.fill();
}
function getRandomColor() {
// creating a random number between 0 and 255 -- this will set the color of the random sized circle
var r = Math.floor(Math.random()*256);
var g = Math.floor(Math.random()*256);
var b = Math.floor(Math.random()*256);
// going from decimal to hex -- converts the int value to a hex for the color
var hexR = r.toString(16);
var hexG = g.toString(16);
var hexB = b.toString(16);
// making sure single character values are prepended with a "0"
if (hexR.length == 1) hexR = "0" + hexR;
if (hexG.length == 1) hexG = "0" + hexG;
if (hexB.length == 1) hexB = "0" + hexB;
// creating the hex value by concatenatening the string values
var hexColor = "#" + hexR + hexG + hexB;
return hexColor.toUpperCase();
}
function drawGameBottomLine() {
canvasContext.beginPath();
canvasContext.moveTo(0,530);
canvasContext.lineTo(450,530);
canvasContext.stroke();
}
function getRandomNum(x,y) {
radX = Math.random()*theCanvas.width;
radY = Math.random()*theCanvas.height;
}
function buildCircle() {
for(var i=0; i<numCircle; i++) {
do {
isDrawable = false;
radX = Math.random()*theCanvas.width;
radY = Math.random()*theCanvas.height;
radR = Math.random()*10+3;
if ((radX>5 && radX<435) && (radY>0 && radY<520)) {
circleArray.x[i] = radX;
circleArray.y[i] = radY;
circleArray.r[i] = radR;
isDrawable = true;
//canvasContext.fillStyle='#123321;'//getRandomColor();
//drawCircle(radX,radY,radR,canvasContext);
}
}
while (isDrawable == false);
}
}
function drawCircle(a) {
for(var i=0; i<numCircle; i++) {
canvasContext.fillStyle='#123321;'
drawCircle(circleArray.x[i],circleArray.y[i],circleArray.r[i],canvasContext);
}
}
drawGameBottomLine();
buildCircle();
drawCircles();
All of the code:
<!DOCTYPE HTML>
<html>
<head>
<style>
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" type="text/javascript"></script>
<script>
var context;
var rightKey = false;
var leftKey = false;
var upKey = false;
var downKey = false;
var block_x;
var block_y;
var block_h = 10;
var block_w = 10;
function init() {
//canvas = document.getElementById('myCanvas');
context = $('#myCanvas')[0].getContext('2d');
WIDTH = $('#myCanvas').width();
HEIGHT = $('#myCanvas').height();
block_x = WIDTH / 2 - 15;
block_y = HEIGHT /2 - 15;
setInterval('draw()', 25);
}
function clearCanvas() {
//context.clearRect(0,0,WIDTH,HEIGHT);
}
function rect(x,y,w,h) {
context.beginPath();
context.rect(x,y,w,h);
context.endPath();
}
function draw() {
clearCanvas();
if (rightKey)
block_x += 5;
else if (leftKey)
block_x -= 5;
if (upKey)
block_y -= 5;
else if (downKey)
block_y += 5;
if (block_x <= 0)
block_x = 0;
if ((block_x + block_w) >= WIDTH)
block_x = WIDTH - block_w;
if (block_y <= 0)
block_y = 0;
if ((block_y + block_h) >= HEIGHT)
block_y = HEIGHT - block_h;
context.fillRect(block_x,block_y,block_w,block_h);
}
function onKeyDown(evt) {
if (evt.keyCode == 39) rightKey = true;
else if (evt.keyCode == 37) leftKey = true;
if (evt.keyCode == 38) upKey = true;
else if (evt.keyCode == 40) downKey = true;
}
function onKeyUp(evt) {
if (evt.keyCode == 39) rightKey = false;
else if (evt.keyCode == 37) leftKey = false;
if (evt.keyCode == 38) upKey = false;
else if (evt.keyCode == 40) downKey = false;
}
$(document).keydown(onKeyDown);
$(document).keyup(onKeyUp);
</script>
</head>
<body onload="init();">
<canvas id="myCanvas" width="450" height="610" style="border:3px solid #c3c3c3;">
It appears that your browser does not support HTML5 and the canvas element.
</canvas>
<script type="text/javascript">
var theCanvas=document.getElementById("myCanvas");
var canvasContext=theCanvas.getContext("2d");
var radX;
var radY;
var radR;
var context;
var numCircle = 50;
var circleArray = new Circles(50);
function Circles(x,y,r) {
var cX = x;
var cY = y;
var cR = r;
}
function clearCanvas() {
//context.clearRect(0,0,WIDTH,HEIGHT);
}
function drawCircle(x,y,r,context) {
context.beginPath();
context.arc(x,y,r,0,Math.PI*2,true);
context.closePath();
context.fill();
}
function getRandomColor() {
// creating a random number between 0 and 255 -- this will set the color of the random sized circle
var r = Math.floor(Math.random()*256);
var g = Math.floor(Math.random()*256);
var b = Math.floor(Math.random()*256);
// going from decimal to hex -- converts the int value to a hex for the color
var hexR = r.toString(16);
var hexG = g.toString(16);
var hexB = b.toString(16);
// making sure single character values are prepended with a "0"
if (hexR.length == 1) hexR = "0" + hexR;
if (hexG.length == 1) hexG = "0" + hexG;
if (hexB.length == 1) hexB = "0" + hexB;
// creating the hex value by concatenatening the string values
var hexColor = "#" + hexR + hexG + hexB;
return hexColor.toUpperCase();
}
function drawGameBottomLine() {
canvasContext.beginPath();
canvasContext.moveTo(0,530);
canvasContext.lineTo(450,530);
canvasContext.stroke();
}
function getRandomNum(x,y) {
radX = Math.random()*theCanvas.width;
radY = Math.random()*theCanvas.height;
}
function buildCircle() {
for(var i=0; i<numCircle; i++) {
do {
isDrawable = false;
radX = Math.random()*theCanvas.width;
radY = Math.random()*theCanvas.height;
radR = Math.random()*10+3;
if ((radX>5 && radX<435) && (radY>0 && radY<520)) {
circleArray.x[i] = radX;
circleArray.y[i] = radY;
circleArray.r[i] = radR;
isDrawable = true;
//canvasContext.fillStyle='#123321;'//getRandomColor();
//drawCircle(radX,radY,radR,canvasContext);
}
}
while (isDrawable == false);
}
}
function drawCircle(a) {
for(var i=0; i<numCircle; i++) {
canvasContext.fillStyle='#123321;'
drawCircle(circleArray.x[i],circleArray.y[i],circleArray.r[i],canvasContext);
}
}
drawGameBottomLine();
buildCircle();
drawCircles();
</script>
</body>
</html>
It's really pretty simple. You just create an array with something like:
var anArray = [];
and then add objects to it:
anArray.push(object)
You might change your definition of a Circle to a simple factory function. Something like this would make everything pretty easy:
function Circle(x, y, r){
this.x = x;
this.y = y;
this.r = r;
}
// create an array
var anArray = [];
// make a circle instance
var aCircle = new Circle(100, 100, 20)
// you can now access the circle properties like this
aCircle.x
//add it to the array
anArray.push(aCircle)
//now this works too (the x coordinate of the first circle in the array):
anArray[0].x
I've added a fiddle with a working example pared down to the essentials: http://jsfiddle.net/markm/jxeh0kks/
You have a few errors in your code. The big one is that to access the objects in the array you need to specify the index of the array first.
//Don't do this:
circleArray.x[i] = radX;
// Do this:
circleArray[i].x = radX;

Drag and lock inside of the parent

Online sample http://jsfiddle.net/dhCLd/
A simple drag magnify,
(function($) {
$.fn.drag = function(opt) {
opt = $.extend({
handle: "",
cursor:"move"}, opt);
if(opt.handle === "") {
var $el = this;
} else {
var $el = this.find(opt.handle);
}
return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
if(opt.handle === "") {
var $drag = $(this).addClass('draggable');
} else {
var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
}
var z_idx = $drag.css('z-index'),
native_width = 0,
native_height = 0;
$drag.css('z-index', 1000).parents('.magnify').on("mousemove", function(e) {
if(!native_width && !native_height){
var image_object = new Image();
image_object.src = $(".small").attr("src");
native_width = image_object.width;
native_height = image_object.height;
}else{
var magnify_offset = $drag.parents('.magnify').offset();
var mx = e.pageX - magnify_offset.left;
var my = e.pageY - magnify_offset.top;
var rx = Math.round(mx/$(".small").width()*native_width - $drag.width()/2)*-1;
var ry = Math.round(my/$(".small").height()*native_height - $drag.height()/2)*-1;
var px = mx - $(".large").width()/2;
var py = my - $(".large").height()/2;
var bgp = rx + "px " + ry + "px";
$('.draggable').css({left:px, top:py, backgroundPosition: bgp}).on("mouseup", function() {
$(this).removeClass('draggable').css('z-index', z_idx);
});
}
});
e.preventDefault();
}).on("mouseup", function() {
if(opt.handle === "") {
$(this).removeClass('draggable');
} else {
$(this).removeClass('active-handle').parent().removeClass('draggable');
}
});
}
})(jQuery);
How can I make the "magnify" stops at the edges around the .small` image, if outside of the image then undraggable. If someone could help?
You can just limit the values of mx (in range [0,magnify's width]) and my (in range [0, magnify's height]):
var magnify = $drag.closest('.magnify');
var magnify_offset = magnify.offset();
var mx = Math.min(Math.max(e.pageX - magnify_offset.left,0),magnify.width());
var my = Math.min(Math.max(e.pageY - magnify_offset.top,0), magnify.height());
Updated demo.
To make the magnifying glass undraggable when it's outside a bounded area, simply test the position of the background image as it is being drag:
var cH = 175/2; //Half of the magnifying glass
if(rx > cH|| ry > cH || rx < -579 + cH || ry < -1107 + cH){ //579 and 1107 are the dimension of the background image
$(this).trigger("mouseup"); //Make it undraggable
return false;
}

Categories

Resources