HTML5 Canvas slider - javascript

Trying to create a slider class that lets you easily and quickly customize values. You can drag the handle or click on any part of the slider to move the handle there, and it works... sort of. You can click as many times as you want, but... if you even click once or if you drag, then let go and try again, it only goes down (never up) a tiny bit. That probably sounds confusing, so here's the fiddle.
var Slider = createEntity({
init: function (args) {
args = args || {};
this.x = args.x || 0;
this.y = args.y || 0;
this.width = args.width || 10;
this.height = args.height || 100;
this.min = args.min || 0;
this.max = args.max || 100;
this.value = args.value || 50;
this.rotation = args.rotation || 0;
this.on = args.on || function () {};
var backFill = randHsla();
args.back = args.back || {};
this.back = args.back;
args.back.fill = args.back.fill || backFill;
this.back.fill = args.back.fill;
args.back.borderFill = args.back.borderFill || backFill;
this.back.borderFill = args.back.borderFill;
args.back.width = args.back.width || 5;
this.back.width = args.back.width;
args.back.x = args.back.x || this.width / 2 - this.back.width / 2;
this.back.x = args.back.x;
var handleColor = randHsla();
args.handle = args.handle || {};
this.handle = args.handle;
args.handle.fill = args.handle.fill || handleColor;
this.handle.fill = args.handle.fill;
args.handle.borderStroke = args.handle.borderStroke || handleColor;
this.handle.borderStroke = args.handle.borderStroke;
args.handle.height = args.handle.height || 5;
this.handle.height = args.handle.height;
args.handle.y = args.handle.y || 0;
this.handle.y = args.handle.y;
this.updatePos();
},
draw: function (fx) {
fx.save();
fx.translate(this.x, this.y);
fx.rotate(this.rotation);
fx.fillStyle = this.back.fill;
fx.beginPath();
fx.fillRect(this.back.x, 0, this.back.width, this.height);
fx.closePath();
fx.fillStyle = this.handle.fill;
fx.strokeStyle = this.handle.borderStroke;
fx.beginPath();
fx.rect(0, this.handle.y, this.width, this.handle.height);
fx.closePath();
fx.fill();
fx.stroke();
fx.restore();
},
updateVal: function () {
var oldVal = this.value,
handleRange = this.height - this.handle.height,
valRange = this.max - this.min;
this.value = (handleRange - this.handle.y) / handleRange * valRange + this.min;
if (this.on instanceof Function && this.value !== oldVal) {
this.on();
}
return this;
},
updatePos: function () {
var handleRange = this.height - this.handle.height,
valRange = this.max - this.min;
this.handle.y = handleRange - ((this.value - this.min) / valRange) * handleRange;
return this;
},
getMouse: function (map) {
var self = this,
mouse = getMouse(map),
bounds = {};
setBounds();
map.addEventListener('mousedown', function (event) {
if (hasPoint(bounds, mouse.x, mouse.y)) {
map.addEventListener('mousemove', onMouseMove);
map.addEventListener('mouseup', onMouseUp);
} else if (hasPoint(self, mouse.x, mouse.y)) {
var y = mouse.y - self.y;
self.handle.y = Math.min(self.height - self.handle.height, Math.max(y, 0));
self.updateVal();
}
});
function onMouseUp(event) {
map.removeEventListener('mousemove', onMouseMove, false);
map.removeEventListener('mouseup', onMouseUp, false);
}
function onMouseMove(event) {
var y = mouse.y - self.y;
self.handle.y = Math.min(self.height - self.handle.height, Math.max(y, 0));
self.updateVal();
}
function setBounds() {
bounds.x = self.x;
bounds.y = self.y + self.handle.y;
bounds.width = self.width;
bounds.height = self.handle.height;
}
return this;
}
});
External functions such as createEntity and hasPoint can be found here.
How would I make it work after clicking the slider and letting go after the first?

Add the event listeners if the user clicks on the handle as well, to enable dragging.
map.addEventListener('mousedown', function(event) {
if (hasPoint(bounds, mouse.x, mouse.y)) {
map.addEventListener('mousemove', onMouseMove);
map.addEventListener('mouseup', onMouseUp);
} else if (hasPoint(self, mouse.x, mouse.y)) {
map.addEventListener('mousemove', onMouseMove);
map.addEventListener('mouseup', onMouseUp);
var y = mouse.y - self.y;
self.handle.y = Math.min(self.height - self.handle.height, Math.max(y, 0));
self.updateVal();
}
});

Related

Converting jquery controls to javascript

So i am trying to implement simple touch controls on a javascript game. I have the following answer from a search:
Snake Game with Controller Buttons for Mobile Use **UPDATED**
However I was trying to change this jquery into javascript so that it would work with my game
Jquery:
$(document).on('click', '.button-pad > button', function(e) {
if ($(this).hasClass('left-btn')) {
e = 37;
}
Javascript:
var contoller = document.getElementById("button-pad").on('click',
'.button-pad > button', function(e) {
if ('.button-pad > button'(this).hasClass('btn-left')) {
e = 37;
}
I thought I had it sorted but it is not working at all
Codepen here:
https://codepen.io/MrVincentRyan/pen/VqpMrJ?editors=1010
Your existing code has some problems with it, but it was close enough where I could translate it. However, your current code seems to want to reassign the event argument being passed to the click handler (e) to 37. This makes no sense. Most likely you just want another variable set to 37 and that's what I've done below:
spaceInvader(window, document.getElementById('space-invader'));
window.focus();
let game = null;
let ship = null;
function spaceInvader (window, canvas) {
canvas.focus();
var context = canvas.getContext('2d');
/* GAME */
function Game () {
this.message = '';
this.rebel = [];
this.republic = [];
this.other = [];
this.size = {x: canvas.width, y: canvas.height};
this.wave = 0;
this.refresh = function () {
this.update();
this.draw();
requestAnimationFrame(this.refresh);
}.bind(this);
this.init();
}
Game.MESSAGE_DURATION = 1500;
Game.prototype.init = function () {
this.ship = new Ship(this);
this.addRebel(this.ship);
this.refresh();
};
Game.prototype.update = function () {
this.handleCollisions();
this.computeElements();
this.elements.forEach(Element.update);
if (!this.rebel.length) {
this.showText('Gatwick closed', true);
return;
}
if (!this.republic.length) this.createWave();
};
Game.prototype.draw = function () {
context.clearRect(0, 0, this.size.x, this.size.y);
this.elements.forEach(Element.draw);
Alien.drawLife(this.republic);
if (this.message) {
context.save();
context.font = '30px Arial';
context.textAlign='center';
context.fillStyle = '#FFFFFF';
context.fillText(this.message, canvas.width / 2, canvas.height / 2);
context.restore();
}
};
Game.prototype.computeElements = function () {
this.elements = this.other.concat(this.republic, this.rebel);
};
Game.prototype.addRebel = function (element) {
this.rebel.push(element);
};
Game.prototype.addRepublic = function (element) {
this.republic.push(element);
};
Game.prototype.addOther = function (element) {
this.other.push(element);
};
Game.prototype.handleCollisions = function () {
this.rebel.forEach(function(elementA) {
this.republic.forEach(function (elementB) {
if (!Element.colliding(elementA, elementB)) return;
elementA.life--;
elementB.life--;
var sizeA = elementA.size.x * elementA.size.y;
var sizeB = elementB.size.x * elementB.size.y;
this.addOther(new Explosion(this, sizeA > sizeB ? elementA.pos : elementB.pos));
}, this);
}, this);
this.republic = this.republic.filter(Element.isAlive);
this.rebel = this.rebel.filter(Element.isAlive);
this.other = this.other.filter(Element.isAlive);
this.republic = this.republic.filter(this.elementInGame, this);
this.rebel = this.rebel.filter(this.elementInGame, this);
};
Game.prototype.elementInGame = function (element) {
return !(element instanceof Bullet) || (
element.pos.x + element.halfWidth > 0 &&
element.pos.x - element.halfWidth < this.size.x &&
element.pos.y + element.halfHeight > 0 &&
element.pos.y - element.halfHeight < this.size.x
);
};
Game.prototype.createWave = function () {
this.ship.life = Ship.MAX_LIFE;
this.ship.fireRate = Math.max(50, Ship.FIRE_RATE - 50 * this.wave);
this.wave++;
this.showText('Wave: ' + this.wave);
var waveSpeed = Math.ceil(this.wave / 2);
var waveProb = (999 - this.wave * 2) / 1000;
var margin = {x: Alien.SIZE.x + 10, y: Alien.SIZE.y + 10};
for (var i = 0; i < 2; i++) {
var x = margin.x + (i % 8) * margin.x;
var y = -200 + (i % 3) * margin.y;
this.addRepublic(new Alien(this, {x: x, y: y}, waveSpeed, waveProb));
}
};
Game.prototype.showText = function (message, final) {
this.message = message;
if (!final) setTimeout(this.showText.bind(this, '', true), Game.MESSAGE_DURATION);
};
/* GENERIC ELEMENT */
function Element (game, pos, size) {
this.game = game;
this.pos = pos;
this.size = size;
this.halfWidth = Math.floor(this.size.x / 2);
this.halfHeight = Math.floor(this.size.y / 2);
}
Element.update = function (element) {
element.update();
};
Element.draw = function (element) {
element.draw();
};
Element.isAlive = function (element) {
return element.life > 0;
};
Element.colliding = function (elementA, elementB) {
return !(
elementA === elementB ||
elementA.pos.x + elementA.halfWidth < elementB.pos.x - elementB.halfWidth ||
elementA.pos.y + elementA.halfHeight < elementB.pos.y - elementB.halfHeight ||
elementA.pos.x - elementA.halfWidth > elementB.pos.x + elementB.halfWidth ||
elementA.pos.y - elementA.halfHeight > elementB.pos.y + elementB.halfHeight
);
};
/* SHIP */
function Ship(game) {
var pos = {
x: Math.floor(game.size.x / 2) - Math.floor(Ship.SIZE.x / 2),
y: game.size.y - Math.floor(Ship.SIZE.y / 2)
};
Element.call(this, game, pos, Ship.SIZE);
this.kb = new KeyBoard();
this.speed = Ship.SPEED;
this.allowShooting = true;
this.life = Ship.MAX_LIFE;
this.fireRate = Ship.FIRE_RATE;
}
Ship.SIZE = {x: 67, y: 100};
Ship.SPEED = 8;
Ship.MAX_LIFE = 5;
Ship.FIRE_RATE = 200;
Ship.prototype.update = function () {
if (this.kb.isDown(KeyBoard.KEYS.LEFT) && this.pos.x - this.halfWidth > 0) {
this.pos.x -= this.speed;
} else if (this.kb.isDown(KeyBoard.KEYS.RIGHT) && this.pos.x + this.halfWidth < this.game.size.x) {
this.pos.x += this.speed;
}
if (this.allowShooting && this.kb.isDown(KeyBoard.KEYS.SPACE)) {
var bullet = new Bullet(
this.game,
{x: this.pos.x, y: this.pos.y - this.halfHeight },
{ x: 0, y: -Bullet.SPEED },
true
);
this.game.addRebel(bullet);
this.toogleShooting();
}
};
Ship.prototype.draw = function () {
var img = document.getElementById('ship');
context.save();
context.translate(this.pos.x - this.halfWidth, this.pos.y - this.halfHeight);
context.drawImage(img, 0, 0);
context.restore();
this.drawLife();
};
Ship.prototype.drawLife = function () {
context.save();
context.fillStyle = 'white';
context.fillRect(this.game.size.x -112, 10, 102, 12);
context.fillStyle = 'red';
context.fillRect(this.game.size.x -111, 11, this.life * 100 / Ship.MAX_LIFE, 10);
context.restore();
};
Ship.prototype.toogleShooting = function (final) {
this.allowShooting = !this.allowShooting;
if (!final) setTimeout(this.toogleShooting.bind(this, true), this.fireRate);
};
/* ALIENS */
function Alien(game, pos, speed, shootProb) {
Element.call(this, game, pos, Alien.SIZE);
this.speed = speed;
this.shootProb = shootProb;
this.life = 3;
this.direction = {x: 1, y: 1};
}
Alien.SIZE = {x: 51, y: 60};
Alien.MAX_RANGE = 350;
Alien.CHDIR_PRO = 0.990;
Alien.drawLife = function (array) {
array = array.filter(function (element) {
return element instanceof Alien;
});
context.save();
context.fillStyle = 'white';
context.fillRect(10, 10, 10 * array.length + 2, 12);
array.forEach(function (alien, idx) {
switch (alien.life) {
case 3:
context.fillStyle = 'green';
break;
case 2:
context.fillStyle = 'yellow';
break;
case 1:
context.fillStyle = 'red';
break;
}
context.fillRect(10 * idx + 11, 11, 10, 10);
});
context.restore();
};
Alien.prototype.update = function () {
if (this.pos.x - this.halfWidth <= 0) {
this.direction.x = 1;
} else if (this.pos.x + this.halfWidth >= this.game.size.x) {
this.direction.x = -1;
} else if (Math.random() > Alien.CHDIR_PRO) {
this.direction.x = -this.direction.x;
}
if (this.pos.y - this.halfHeight <= 0) {
this.direction.y = 1;
} else if (this.pos.y + this.halfHeight >= Alien.MAX_RANGE) {
this.direction.y = -1;
} else if (Math.random() > Alien.CHDIR_PRO) {
this.direction.y = -this.direction.y;
}
this.pos.x += this.speed * this.direction.x;
this.pos.y += this.speed * this.direction.y;
if (Math.random() > this.shootProb) {
var bullet = new Bullet(
this.game,
{x: this.pos.x, y: this.pos.y + this.halfHeight },
{ x: Math.random() - 0.5, y: Bullet.SPEED },
false
);
this.game.addRepublic(bullet);
}
};
Alien.prototype.draw = function () {
var img = document.getElementById('fighter');
context.save();
context.translate(this.pos.x + this.halfWidth, this.pos.y + this.halfHeight);
context.rotate(Math.PI);
context.drawImage(img, 0, 0);
context.restore();
};
/* BULLET */
function Bullet(game, pos, direction, isRebel) {
Element.call(this, game, pos, Bullet.SIZE);
this.direction = direction;
this.isRebel = isRebel;
this.life = 1;
try {
var sound = document.getElementById('sound-raygun');
sound.load();
sound.play().then(function () {}, function () {});
}
catch (e) {
// only a sound issue
}
}
Bullet.SIZE = {x: 6, y: 20};
Bullet.SPEED = 3;
Bullet.prototype.update = function () {
this.pos.x += this.direction.x;
this.pos.y += this.direction.y;
};
Bullet.prototype.draw = function () {
context.save();
var img;
if (this.isRebel) {
context.translate(this.pos.x - this.halfWidth, this.pos.y - this.halfHeight);
img = document.getElementById('rebel-bullet');
}
else {
context.translate(this.pos.x + this.halfWidth, this.pos.y + this.halfHeight);
img = document.getElementById('republic-bullet');
context.rotate(Math.PI);
}
context.drawImage(img, 0, 0);
context.restore();
};
/* EXPLOSION */
function Explosion(game, pos) {
Element.call(this, game, pos, Explosion.SIZE);
this.life = 1;
this.date = new Date();
try {
var sound = document.getElementById('sound-explosion');
sound.load();
sound.play().then(function () {}, function () {});
}
catch (e) {
// only a sound issue
}
}
Explosion.SIZE = {x: 115, y: 100};
Explosion.DURATION = 150;
Explosion.prototype.update = function () {
if (new Date() - this.date > Explosion.DURATION) this.life = 0;
};
Explosion.prototype.draw = function () {
var img = document.getElementById('explosion');
context.save();
context.translate(this.pos.x - this.halfWidth, this.pos.y - this.halfHeight);
context.drawImage(img, 0, 0);
context.restore();
};
/* KEYBOARD HANDLING */
function KeyBoard() {
var state = {};
window.addEventListener('keydown', function(e) {
state[e.keyCode] = true;
});
window.addEventListener('keyup', function(e) {
state[e.keyCode] = false;
});
this.isDown = function (key) {
return state[key];
};
}
KeyBoard.KEYS = {
LEFT: 37,
RIGHT: 39,
SPACE: 32
};
window.addEventListener('load', function() {
game = new Game();
});
// Get all the button elements that are children of elements that have
// the .button-pad class and convert the resulting node list into an Array
let elements =
Array.prototype.slice.call(document.querySelectorAll('.button-pad button'));
// Loop over the array
elements.forEach(function(el){
el.textContent = "XXXX";
// Set up a click event handler for the current element being iterated:
el.addEventListener('click', function(e) {
// When the element is clicked, check to see if it uses the left-btn class
if(this.classList.contains('left-btn')) {
// Perform whatever actions you need to:
ship.update();
}
});
});
}
<h1>Gatwick invaders</h1>
<p>Press <b>left arrow</b> to go left, <b>right arrow</b> to go right, and <b>space</b> to shoot...</p>
<canvas id="space-invader" width="640" height="500" tabindex="0"></canvas>
<img id="fighter" src="https://raw.githubusercontent.com/MrVIncentRyan/assets/master/drone1.png" />
<img id="ship" src="https://raw.githubusercontent.com/MrVIncentRyan/assets/master/cop1.png" />
<img id="rebel-bullet" src="https://raw.githubusercontent.com/OlivierB-OB/starwars-invader/master/rebelBullet.png" />
<img id="republic-bullet" src="https://raw.githubusercontent.com/OlivierB-OB/starwars-invader/master/republicBullet.png" />
<img id="explosion" src="https://raw.githubusercontent.com/OlivierB-OB/starwars-invader/master/explosion.png" />
<audio id="sound-explosion" src="https://raw.githubusercontent.com/OlivierB-OB/starwars-invader/master/explosion.mp3"></audio>
<audio id="sound-raygun" src="https://raw.githubusercontent.com/OlivierB-OB/starwars-invader/master/raygun.mp3"></audio>
</div>
<div class="button-pad">
<div class="btn-up">
<button type="submit" class="up">
<img src="http://aaronblomberg.com/sites/ez/images/btn-up.png" />
</button>
</div>
<div class="btn-right">
<button type="submit" class="right">
<img src="http://aaronblomberg.com/sites/ez/images/btn-right.png" />
</button>
</div>
<div class="btn-down">
<button type="submit" class="down">
<img src="http://aaronblomberg.com/sites/ez/images/btn-down.png" />
</button>
</div>
<div class="btn-left">
<button type="submit" class="left">
<img src="http://aaronblomberg.com/sites/ez/images/btn-left.png" />
</button>
</div>
</div>
A custom solution for emulating keypresses on mobile in both vanilla Javascript as well as jQuery!
// jQuery (edge), for use with ES2015-19
/*
$(document).on("click", ".example-btn", e => { // Click event handler
if($(this).hasClass("example-btn")) { // Verifying that element has class
e = 37
jQuery.event.trigger({type: "keypress", which: character.charCodeAt(e)}) // Simulating keystroke
// The following is simply for debugging, remove if needed
alert("Button validation confirmed!")
console.log("E: ", e)
}
})
*/
// Pure Javascript (ECMA Standard)
document.querySelector(".example-btn").addEventListener("click", function(e) { // Click event handler
if(this.classList.contains("example-btn")) { // Verifying that element has class
e = 37
if(document.createEventObject) {
var eventObj = document.createEventObject();
eventObj.keyCode = e;
document.querySelector(".example-btn").fireEvent("onkeydown", eventObj);
} else if(document.createEvent) {
var eventObj2 = document.createEvent("Events");
eventObj2.initEvent("keydown", true, true);
eventObj2.which = e;
document.querySelector(".example-btn").dispatchEvent(eventObj2);
}
// The following is simply for debugging, remove if needed
alert("Button validation confirmed!");
console.log("E: ", e);
}
});
// ---------------------------------------------------------------------------------------------------
/*
You can not use the "this" statement when referring to an embedded element. In your previous code "this" would refer to ".button-container > .example-btn" which the compiler will interpret as only the parent element, being .button-container (.button-pad in your code) not the child element in which you want. Also there is no such thing as returning a character code and expecting it to automatically know what to do with it. I assume you are doing this to emulate a keystroke on a mobile device and I assure you that this design works although it might be flawed. Give it a try and I hope it does something to at least help if not solve your problem.
*/
// ---------------------------------------------------------------------------------------------------
When an event listener is attached to an element, that listener is not unique for the element, but it propagates to its children.
This functionality is enabled in jQuery by adding a parameter on an event listener a parameter that targets the element that we want.
This is not case in vanillaJS, but using e.target we can inspect in which elements the event is executed.
Probably your are looking something like this. However, I would prefer to add an id in the button so you can more easily work with it.
document.addEventListener('click', function(e){
if(e.target.tagName === 'BUTTON' && e.target.classList.value.includes('btn-left')){
// execute your code
}
});

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.

Game Collision-detection FIX

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

in three.js using orthographic camera while dragging object mouse pointer comes to center

I am trying to drag the object in orthographic camera view. When I start dragging object jumps and mouse pointer comes to center of object then it start dragging normally, but mouse point remains at center. I want mouse pointer should be there where I place at start and it drag object.
So I want when moving a model in the orthogonal views using the cursor, the center of the object is moved to the cursor at the moment.
I would like to be able to select anywhere on a model, without the center jumping to the cursor. Here is my code
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/*
* Running this will allow you to drag three.js around the screen.
*
* feature requests:
* 1. add rotation?
* 2. axis lock
* 3. inertia dragging
* 4. activate/deactivate? prevent propagation?
*
* #author zz85 from
* follow on http://twitter.com/blurspline
*/
THREE.DragControls = function(_camera, _objects, _domElement, objects) {
if (_objects instanceof THREE.Scene) {
_objects = _objects.children;
}
_objects = objects;
var objectstodrag = new Array();
var _projector = new THREE.Projector();
var _selected;
var me = this;
_offset=new THREE.Vector3();
this.onDocumentMouseMove = function(event) {
var elem = _domElement;
var rect = elem.getBoundingClientRect();
x = (event.clientX - rect.left) / rect.width;
y = (event.clientY - rect.top) / rect.height;
var vector = new THREE.Vector3((x) * 2 - 1, -(y) * 2 + 1, 0.5);
var raycaster = _projector.pickingRay(vector, _camera);
if (_selected) {
var targetPos = raycaster.ray.direction.clone().multiplyScalar(_selected.distance).add(raycaster.ray.origin);
// targetPos.sub(_offset);
var deltax = targetPos.x - _selected.object.position.x;
var deltay = (-targetPos.z) - _selected.object.position.y;
var deltaz = targetPos.y - _selected.object.position.z;
var xenable = true;
var yenable = true;
var zenable = true;
if (selViewMode == "front" || selViewMode == "back") {
yenable = false;
} else if (selViewMode == "right" || selViewMode == "left") {
xenable = false;
} else if (selViewMode == "top" || selViewMode == "bottom") {
zenable = false;
} else {
return;
}
for (var i = 0; i < objectstodrag.length; i++) {
if (xenable == true) {
objectstodrag[i].position.x += deltax;
console.log('xaxis')
// objectstodrag[i].position.x = targetPos.x;
// objectstodrag[i].position.x =objectstodrag[i].position.x /4;
}
if (yenable == true) {
objectstodrag[i].position.y += deltay;
console.log('yaxis')
// objectstodrag[i].position.y = targetPos.z;
// objectstodrag[i].position.y=objectstodrag[i].position.y/4
}
if (zenable == true) {
objectstodrag[i].position.z +=deltaz;
console.log('zaxis')
// objectstodrag[i].position.z = targetPos.y;
// objectstodrag[i].position.z=objectstodrag[i].position.z/4;
}
}
thingiview.updateObjectPostion(_selected.object.geometry);
return 1;
}
var intersects = raycaster.intersectObjects(_objects);
if (intersects.length > 0) {
_domElement.style.cursor = 'pointer';
} else {
_domElement.style.cursor = 'auto';
}
return intersects.length;
}
this.onDocumentMouseDown = function(event) {
// // Do not show cursor move for autonesting in orthogonal views
// if (document.getElementById('autonesting').value == "true" && selViewMode != "iso")
// return;
var elem = _domElement;
var rect = elem.getBoundingClientRect();
x = (event.clientX - rect.left) / rect.width;
y = (event.clientY - rect.top) / rect.height;
var vector = new THREE.Vector3((x) * 2 - 1, -(y) * 2 + 1, 0.5);
var ray = _projector.pickingRay(vector, _camera);
var intersects = ray.intersectObjects(_objects);
if (intersects.length > 0) {
if (intersects[0].object.material.materials[0].color.getHex() == selectedObjectColor)
{
_selected = intersects[0];
_offset.copy(_selected.point).sub(_selected.object.position);
_domElement.style.cursor = 'move';
objectstodrag.splice(0, objectstodrag.length);
objectstodrag = [];
for (var i = 0; i < _objects.length; i++) {
if (_objects[i].geometry.enabled && _objects[i].material.materials[0].color.getHex() == selectedObjectColor) {
objectstodrag.push(_objects[i]);
}
}
} else {
objectstodrag.splice(0, objectstodrag.length);
objectstodrag = [];
}
}
if (me.onHit)
me.onHit(intersects.length > 0);
if (intersects != undefined) {
if (intersects[0] != undefined) {
if (intersects[0].object.material.materials[0].color.getHex() == selectedObjectColor) {
return intersects.length;
}
}
}
return 0;
};
this.onDocumentMouseUp = function(event) {
if (_selected) {
if (document.getElementById("autonesting").value == "false") {
setPositionOnRotationInManualNest(true);
}
if (me.onDragged)
me.onDragged();
_selected = null;
}
_domElement.style.cursor = 'auto';
};
};

toggle image in canvas

This is a start to do assignment for Uni. But for now on I have problem to manage to toggle between images. This is meant to be start for turn around match game. It suppose to be images and words and match them but I have problem so far with this toggle function. I have this code so far:
var myButton = new Image();
var mouseX = 0;
var mouseY = 0;
var backgroundImage = new Image();
var nothing = "num/w/2.png";
var something = "num/w/3.png";
function drawButton(buttonObj)
{
canvasContext.drawImage(buttonObj, buttonObj.x, buttonObj.y);
}
function checkIfInsideButtonCoordinates(buttonObj, mouseX, mouseY)
{
if(((mouseX > buttonObj.x) && (mouseX < (buttonObj.x + buttonObj.width))) && ((mouseY > buttonObj.y) && (mouseY < (buttonObj.y + buttonObj.height))))
{return true;}
else
{return false;}
}
$(function() {
var canvas = $("#canvas").get(0);
canvasContext = canvas.getContext('2d');
backgroundImage.src = "num/back.jpg";
$(backgroundImage).load(function() {
canvasContext.drawImage(backgroundImage, 0, 0);
myButton.x = 100;
myButton.y = 100;
myButton.width = 100;
myButton.height = 100;
myButton.src = something;
drawButton(myButton);
});
$("#canvas").click(function(eventObject) {
mouseX = eventObject.pageX - this.offsetLeft;
mouseY = eventObject.pageY - this.offsetTop;
if(checkIfInsideButtonCoordinates(myButton, mouseX, mouseY))
{
if(myButton.src = something)
{
myButton.src = nothing;
}
else if(myButton.src = nothing)
{
myButton.src = something;
}
drawButton(myButton);
}
});
});
Any idea why?Thank you.
jsfiddle
You need to make your = in the if statements ==.
if (myButton.src == something) {
myButton.src = nothing;
}
else if (myButton.src == nothing) {
myButton.src = something;
}

Categories

Resources