Javascript - Point object towards mouse - javascript

I'm trying to get this player character to point towards the mouse pointer, but it doesn't move at all. I have no idea where to start, can somebody please help me?
Here is the full code:
The part which I need help with is in the updatevalues() function in the player object (javascript)
var canvas = document.getElementById("tanks-canvas");
var game = canvas.getContext("2d");
canvas.height = screen.height / 1.175;
canvas.width = screen.width / 1.05;
game.translate(canvas.width / 2, canvas.height / 2);
clear();
txt(0, 0, "Loading...", "100px georgia", "rgb(0, 0, 0)");
var mousex = 0;
var mousey = 0;
var angle;
var mode = "menu";
var key = [];
var scale = 1;
for (i = 0; i <= 255; i += 1) {
key[i] = false;
}
/*
Class Definition:
*/
// Bodies:
var circle_body = {
x: 0,
y: 0,
radius: 100,
draw: function() {
this.setvals();
circ(this.x, this.y, this.radius, "rgb(0, 150, 255)");
},
setvals: function() {
this.radius = 25 * scale;
}
};
// Turrents:
var rect_turrent = {
x: 0,
y: 0,
width: 0,
height: 0,
offset: 0,
draw: function() {
this.setvals();
rect(this.x + this.offset, this.y, this.width, this.height, "rgb(150, 150, 150)");
},
setvals: function() {
this.offset = 35 * scale;
this.width = 30 * scale;
this.height = 15 * scale;
}
};
// Classes:
var base = {
draw: function() {
rect_turrent.draw();
circle_body.draw();
}
};
/*
Functions & Objects
*/
function txt(x, y, content, font, color) {
game.fillStyle = color;
game.textAlign = "center";
game.font = font;
game.fillText(content, x, y);
}
function rect(x, y, width, height, color) {
x -= width / 2;
y -= height / 2;
game.fillStyle = color;
game.strokeStyle = color.black;
game.fillRect(x, y, width, height);
game.strokeRect(x, y, width, height);
}
function img(x, y, img) {
x -= img.width / 2;
y -= img.height / 2;
game.drawImage(img, x, y);
}
function circ(x, y, radius, color) {
game.fillStyle = color;
game.strokeStyle = color.black;
game.beginPath();
game.arc(x, y, radius, 0, Math.PI * 2);
game.fill();
game.stroke();
}
function clear() {
rect(0, 0, canvas.width + 10, canvas.height + 10, "rgb(200, 200, 200)");
}
/*
IMPORTANT: Player Character:
*/
var player = {
// Variables
x: 0,
y: 0,
type: "base",
angle: 0,
autorotate: false,
// Functions
update: function() {
this.updatevalues();
game.save();
game.rotate(this.angle);
this.draw();
game.restore();
txt(0, -100, "Mouse x: " + mousex + " | Mouse y: " + mousey + " | Angle: " + this.angle, "20px georgia", "rgb(0, 0, 0)");
},
draw: function() {
if (this.type == "base") {
base.draw();
}
},
updatevalues: function() {
this.offsetY = mousex - this.x;
this.offsetX = mousey - this.y;
this.angle = Math.atan(mousex / mousey);
}
};
function menu() {
player.update();
}
function update() {
if (mode == "menu") {
menu();
}
clear();
player.update();
}
/*
Intervals:
*/
game.interval = setInterval(update, 50);
/*
Event Listeners
*/
document.addEventListener("keydown", function(event) {
for (i = 0; i <= 255; i++) {
if (event.keyCode == i) {
key[i] = true;
}
}
});
document.addEventListener("keyup", function(event) {
for (i = 0; i <= 255; i++) {
key[i] = false;
}
});
document.addEventListener("mousemove", function(event) {
mousex = event.offsetX - (canvas.width / 2);
mousey = (canvas.height / 2) - event.offsetY;
});
/* Everything */
* {
transition: 1s;
}
body {
background-color: rgb(100, 100, 100);
}
/* Flexbox: */
.flex-container {
display: flex;
flex-direction: column;
padding: 5vw;
}
#header {
flex-direction: row;
background-color: rgb(200, 0, 0);
}
#main {
background-color: rgb(200, 150, 50);
}
#navbar {
z-index: 1;
overflow: hidden;
background-color: rgb(200, 200, 200);
position: fixed;
top: 0;
width: 100%
}
/* Images */
img {
display: block;
margin-left: auto;
margin-right: auto;
}
.imgcontainer {
position: relative;
width: 50%
}
.imgoverlay {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 100, 200, 0.75);
overflow: hidden;
width: 100%;
height: 0;
}
.imgtext {
text-align: center;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: rgba(200, 200, 200, 0.75);
}
.imgcontainer:hover .imgoverlay {
height: 100%;
}
.image {
width: 100%;
height: auto;
}
/* Navigation Menu */
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.75);
overflow-x: hidden;
padding-top: 5vw;
}
/* The navigation menu links */
.sidenav a {
padding: 1vw 1vw 1vw 4vw;
text-decoration: none;
overflow-x: hidden;
font-size: 2vw;
color: rgba(150, 150, 150, 0.75);
display: block;
}
/* When you mouse over the navigation links, change their color */
.sidenav a:hover {
color: rgb(255, 255, 255);
}
/* Position and style the close button (top right corner) */
.sidenav .closebtn {
position: absolute;
top: 0;
right: 1vw;
font-size: 5vw;
margin-left: 50px;
}
/* Styles: */
h1 {
font: 10vw courier;
color: rgb(0, 0, 200);
text-align: center;
padding: none;
}
h2 {
font: 9vw courier;
color: rgb(0, 0, 150);
text-align: center;
padding: none;
}
h3 {
font: 8vw courier;
color: rgb(0, 0, 150);
text-align: center;
padding: none;
}
h4 {
font: 7vw courier;
color: rgb(0, 0, 150);
text-align: center;
padding: none;
}
h5 {
font: 6vw courier;
color: rgb(0, 0, 150);
text-align: center;
padding: none;
}
h6 {
font: 5vw courier;
color: rgb(0, 0, 150);
text-align: center;
padding: none;
}
p {
font: 2vw georgia;
color: rgb(0, 100, 0);
text-align: justify;
}
/* Other */
.link {
color: rgb(150, 150, 150);
}
.link:hover {
color: rgb(255, 255, 255);
}
code {
font-family: courier;
}
canvas {
padding: none;
margin-left: auto;
margin-right: auto;
margin-top: auto;
margin-bottom: auto;
display: block;
background-color: rgb(255, 255, 255);
border: 5px solid rgb(0, 0, 0);
}
<!DOCTYPE html>
<html>
<head>
<title>Game Goods</title>
<link rel="stylesheet" href="style.css">
<script src="functions.js"></script>
</head>
<body>
<!-- Game -->
<canvas id="tanks-canvas"></canvas>
<script src="tanks-script.js"></script>
</body>
</html>
(If you run it, hit "full page", or it won't work.)
Edit 10-30-18: I've changed the code according to Helder's answer. At least the mousex works now...
Edit 10-31-18: I changed mousex and mousey to also be at coordinates 0, 0 when the mouse is at the middle. The canvas works like a coordinate plane now. I also added debugging text (you can see it if you run the snippet).

Your calculations for the angle are incorrect, take a look at this sample...
This is by no means the exact solution but should get you moving on the right direction, I'm only using mousex in my calculation.
var canvas = document.getElementById("tanks-canvas");
var game = canvas.getContext("2d");
canvas.height = canvas.width = 170;
game.translate(canvas.width / 2, canvas.height / 2);
clear();
var mousex = 0;
var mousey = 0;
var angle;
var mode = "menu";
var key = [];
var scale = 1;
for (i = 0; i <= 255; i += 1) {
key[i] = false;
}
var player = {
x: 0, y: 0,
type: "base",
angle: 0,
autorotate: false,
update: function() {
this.updatevalues();
game.save()
game.rotate(this.angle);
this.draw();
game.restore();
},
updatevalues: function() {
this.offsetY = mousex - this.x;
this.offsetX = mousey - this.y;
this.angle = 360 * Math.sin(mousex/30000);
},
draw: function() {
if (this.type == "base") {
base.draw();
}
}
};
/*
Class Definition:
*/
// Bodies:
var circle_body = {
x: 0,
y: 0,
radius: 100,
draw: function() {
this.setvals();
circ(this.x, this.y, this.radius, "rgb(0, 150, 255)");
},
setvals: function() {
this.radius = 25 * scale;
}
};
// Turrents:
var rect_turrent = {
x: 0,
y: 0,
width: 0,
height: 0,
offset: 0,
draw: function() {
this.setvals();
rect(this.x + this.offset, this.y, this.width, this.height, "rgb(150, 150, 150)");
},
setvals: function() {
this.offset = 35 * scale;
this.width = 30 * scale;
this.height = 15 * scale;
}
};
// Classes:
var base = {
draw: function() {
rect_turrent.draw();
circle_body.draw();
}
};
/*
Functions & Objects
*/
function rect(x, y, width, height, color) {
x -= width / 2;
y -= height / 2;
game.fillStyle = color;
game.strokeStyle = color.black;
game.fillRect(x, y, width, height);
game.strokeRect(x, y, width, height);
}
function circ(x, y, radius, color) {
game.fillStyle = color;
game.strokeStyle = color.black;
game.beginPath();
game.arc(x, y, radius, 0, Math.PI * 2);
game.fill();
game.stroke();
}
function clear() {
rect(0, 0, canvas.width + 10, canvas.height + 10, "rgb(200, 200, 200)");
}
function update() {
clear();
player.update();
}
game.interval = setInterval(update, 50);
document.addEventListener("mousemove", function(event) {
mousex = event.offsetX;
mousey = event.offsetY;
});
<canvas id="tanks-canvas"></canvas>

I found out the formula with help from my math teacher & a different question.
The formula is
Math.atan2(-y, x);

Related

How to Draw on rotated canvas using mouse?

I want to draw on img its work fine but when i rotate the image its drawing axis is total change and it not draw on the right area
https://codepen.io/ali-shahzil/project/editor/AddPLW
var canvas;
var ctx;
var SCALE_MIN = 1,
SCALE_MAX = 25;
var currScale = 0; // def pic width=600px, 100px=1scale unit
var xscale = 1.0;
var scaleFactor = 1.00;
var painting = false,
mark = true,
lastX = 0,
lastY = 0,
lineThickness = 0.3,
width = 600,
height = 600;
var img = new Image();
img.src = 'img.JPG';
img.onload = function() {
canvas = document.getElementById("canvas1"),
ctx = canvas.getContext("2d");
canvas.height = height;
canvas.width = width;
ctx.drawImage(img, 5, 40, canvas.width, canvas.height);
canvas = document.getElementById("canvas2"),
ctx = canvas.getContext("2d");
canvas.height = height;
canvas.width = width;
ctx.drawImage(img, 5, 40, canvas.width, canvas.height);
canvas = ctx = ''; //reset
}
function doMarking() {
var checkBox = document.getElementById("mark");
if (checkBox.checked == true) {
mark = true;
if (canvas != null)
canvas.style.cursor = "pointer";
//currImgId = '';
} else {
mark = false;
if (canvas != null);
canvas.style.cursor = "";
}
lastX = 0,
lastY = 0,
painting = false;
}
function mouseDown(e) {
if (!mark)
return;
painting = true;
ctx.fillStyle = "#ffffff";
lastX = e.pageX - (e.target).offsetLeft;
lastY = e.pageY - (e.target).offsetTop;
//Calculating the scale how much it increase
var rect = canvas.getBoundingClientRect(); // abs. size of element
scaleX = canvas.width / rect.width; // relationship bitmap vs. element for X
scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y
lastX = lastX * scaleX;
lastY = lastY * scaleY;
//console.log('Before lasX=' + lastX + ' lastY=' + lastY+',currScale='+currScale);
//lastX=transformSimple(lastX);
// lastY=transformSimple(lastY);
//console.log('After lasX=' + lastX + ' lastY=' + lastY+', currScale='+currScale);
//console.log('offleft=' + (e.target).offsetLeft + ', offsetTop=' + (e.target).offsetTop);
// console.log('e=' + e);
}
/*
canvas1.onmousedown=function (e) {
console.log('mousedown2 id=' + e);
if (!mark)
return;
painting = true;
ctx.fillStyle = "#ffffff";
lastX = e.pageX - this.offsetLeft;
lastY = e.pageY - this.offsetTop;
console.log('lasX=' + lastX + ' lastY=' + lastY);
}
*/
function mouseUp(e) {
if (!mark)
return;
painting = false;
}
function mouseMove(e) {
if (!mark)
return;
if (painting) {
mouseX = e.pageX - (e.target).offsetLeft;
mouseY = e.pageY - (e.target).offsetTop;
//Calculating the scale how much it increase
var rect = canvas.getBoundingClientRect(); // abs. size of element
scaleX = canvas.width / rect.width; // relationship bitmap vs. element for X
scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y
mouseX = mouseX * scaleX;
mouseY = mouseY * scaleY;
// mouseX=transformSimple(mouseX);
// mouseY=transformSimple(mouseY);
//console.log('mx=' + mouseX + ', my=' + mouseY);
// find all points between
var x1 = mouseX,
x2 = lastX,
y1 = mouseY,
y2 = lastY;
var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
if (steep) {
var x = x1;
x1 = y1;
y1 = x;
var y = y2;
y2 = x2;
x2 = y;
}
if (x1 > x2) {
var x = x1;
x1 = x2;
x2 = x;
var y = y1;
y1 = y2;
y2 = y;
}
var dx = x2 - x1,
dy = Math.abs(y2 - y1),
error = 0,
de = dy / dx,
yStep = -1,
y = y1;
if (y1 < y2) {
yStep = 1;
}
lineThickness = 5 - Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) / 10;
if (lineThickness < 1) {
lineThickness = 1;
}
for (var x = x1; x < x2; x++) {
if (steep) {
// translate(y,x);
ctx.fillRect(y, x, lineThickness, lineThickness);
//ctx.fillRect(transformSimple(y), transformSimple(x), lineThickness, lineThickness);
} else {
ctx.fillRect(x, y, lineThickness, lineThickness);
}
error += de;
if (error >= 0.5) {
y += yStep;
error -= 1.0;
}
// console.log('x=' + x + ', y=' + y );
}
lastX = mouseX;
lastY = mouseY;
}
}
/*
canvas.addEventListener('click', function (event) {
if (mark)
return;
//get the img of convas
});*/
//-------------- img zooms
function zoomin_canvas() {
if (canvas != null) {
var currWidth = canvas.clientWidth;
//console.log('zoomin currWidth='+currWidth);
if (currWidth >= 1500) return false;
else {
canvas.style.width = (currWidth + 100) + "px";
//if (currScale < SCALE_MAX)
// currScale++;
//console.log('scale=' + currScale);
}
}
}
function zoomout_canvas() {
if (canvas != null) {
var currWidth = canvas.clientWidth;
if (currWidth <= 100) return false;
else {
canvas.style.width = (currWidth - 100) + "px";
//if (currScale > SCALE_MIN)
// currScale--;
//console.log('scale=' + currScale);
}
}
}
var currImgId = null;
function selectImg(e) {
if (currImgId != null) {
document.getElementById(currImgId).style.border = "none";
}
e.target.style.border = "2px solid orange";
currImgId = (e.target).getAttribute('id');
if (typeof canvas !== 'undefined') {
// the variable is defined
canvas = e.target;
ctx = canvas.getContext("2d");
}
//ctx.drawImage(img, 5, 40, canvas.width, canvas.height);
}
function rotate() {
if (currImgId != null) {
document.getElementById(currImgId).setAttribute("class", "rotated-image");
}
}
var degrees = 0;
function rotateRight() {
console.log('currimgid=' + currImgId);
var img = document.getElementById(currImgId);
degrees = parseInt(img.getAttribute("rotate"));
degrees = (degrees + 90) % 360;
img.style.setProperty('-ms-transform', 'rotate(' + degrees + 'deg)');
img.style.setProperty('-webkit-transform', 'rotate(' + degrees + 'deg)');
img.style.setProperty('transform', 'rotate(' + degrees + 'deg)');
img.setAttribute("rotate", degrees);
}
function rotateLeft() {
var img = document.getElementById(currImgId);
degrees = parseInt(img.getAttribute("rotate"));
degrees = (degrees - 90) % 360;
img.style.setProperty('-ms-transform', 'rotate(' + degrees + 'deg)');
img.style.setProperty('-webkit-transform', 'rotate(' + degrees + 'deg)');
img.style.setProperty('transform', 'rotate(' + degrees + 'deg)');
img.setAttribute("rotate", degrees);
}
function translate(X, Y) {
console.log('untransformed x=' + X + ', y=' + Y);
// const point = {x: 0, y: 0};
const matrix = ctx.getTransform();
const transformedPoint = {
x: matrix.a * X + matrix.c * Y + matrix.e,
y: matrix.b * X + matrix.d * Y + matrix.f,
};
console.log('transformed x=' + transformedPoint.x + ', y=' + transformedPoint.y);
}
function translateSimple(X, Y) {
//console.log('scalefactor='+scaleFactor);
console.log('untransformed x=' + X + ', y=' + Y);
if (scaleFactor >= 1.0)
console.log('transformed x=' + X / scaleFactor + ', y=' + Y / scaleFactor);
else
console.log('transformed x=' + X * scaleFactor + ', y=' + Y * scaleFactor);
}
function transformSimple(a) {
//return (parseInt(a/(scaleFactor*scaleFactor)));
if (currScale == 0)
return (a);
else
return (a - 16 * (currScale));
}
function draw() {
for (var x = 100; x < 102; x++)
ctx.fillRect(100, x, 4.9, 4.9);
}
.main_bottom {
background-color: #e8e9eb;
display: flex;
align-items: center;
justify-content: space-around;
border: 10px solid #e8e9eb;
border-top: 30px solid #e8e9eb;
height: 90vh;
}
form {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
margin-bottom: 5px;
}
.scrollit {
/*overflow-y: auto;*/
/* overflow-y: scroll;*/
height: 300px;
overflow-x: hidden;
overflow-y: auto;
}
.first {
display: flex;
flex-direction: row;
visibility: hidden;
}
.submit {
display: flex;
flex-direction: row;
}
img {
width: 100%;
max-width: 800px;
height: auto;
display: block;
margin-left: auto;
margin-right: auto;
}
.fix {
height: 300px;
margin-top: 200px;
}
body,
html {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
}
#left_panel {
display: flex;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 700px;
background-color: white;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
flex-direction: column;
overflow: scroll;
}
#right_panel {
display: flex;
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 700px;
margin-right: 15px;
background-color: white;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
flex-direction: column;
overflow: scroll;
}
#drag {
position: absolute;
left: -4px;
top: 0;
bottom: 0;
width: 8px;
cursor: w-resize;
}
/*img zooms*/
#navbar {
overflow: hidden;
background-color: #099;
position: fixed;
top: 0;
width: 100%;
padding-top: 3px;
padding-bottom: 3px;
padding-left: 20px;
}
#navbar a {
float: left;
display: block;
color: #666;
text-align: center;
padding-right: 20px;
text-decoration: none;
font-size: 17px;
}
#navbar a:hover {
background-color: #ddd;
color: black;
}
#navbar a.active {
background-color: #4caf50;
color: white;
}
.main {
padding: 16px;
margin-top: 30px;
width: 100%;
height: 100vh;
overflow: auto;
cursor: grab;
cursor: -o-grab;
cursor: -moz-grab;
cursor: -webkit-grab;
}
.main img {
height: auto;
width: auto;
}
.button {
width: 300px;
height: 60px;
}
/*---- toggle switch*/
.switch {
position: relative;
display: inline-block;
width: 30px;
height: 17px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: 0.4s;
transition: 0.4s;
}
.slider:before {
position: absolute;
content: "";
height: 13px;
width: 13px;
left: 4px;
bottom: 2px;
background-color: white;
-webkit-transition: 0.4s;
transition: 0.4s;
}
input:checked+.slider {
background-color: #2196f3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196f3;
}
input:checked+.slider:before {
-webkit-transform: translateX(13px);
-ms-transform: translateX(13px);
transform: translateX(13px);
}
/* Rounded sliders */
.slider.round {
border-radius: 17px;
}
.slider.round:before {
border-radius: 50%;
}
.both {
margin-top: 50px;
display: flex;
justify-content: center;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./styles.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<title>Order by Picture</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<div id="navbar">
<button type="button" onclick="zoomin_canvas()">+</button>
<button type="button" onclick="zoomout_canvas()">-</button>
<button id="rotateRight" onclick="rotateRight()">Right</button>
<button id="rotateLeft" onclick="rotateLeft()">Left</button>
<button id="Button1" onclick="draw()">draw</button
<label> Marking</label>
<label class="switch">
<input type="checkbox" checked onclick="doMarking()" id="mark">
<span class="slider round"></span>
</label>
</div>
<div class="both">
<div class="canvas1">
<canvas id="canvas1" rotate="0" onclick="selectImg(event)" onmousedown="mouseDown(event)" onmouseup="mouseUp(event)" onmousemove="mouseMove(event)">
Your browser does not support the HTML5 canvas tag.
</canvas>
</div>
<div class="canvas2">
<canvas id="canvas2" rotate="0" onclick="selectImg(event)" onmousedown="mouseDown(event)" onmouseup="mouseUp(event)" onmousemove="mouseMove(event)">
Your browser does not support the HTML5 canvas tag.
</canvas>
</div>
</div>
</body>
</html>
Don't rotate the canvas
Draw the rotated image on the canvas, rather than rotate the canvas.
When you draw image on the canvas, rotate it, then you can draw over it using the normal mouse coords.
Rotating image on canvas
The code below will draw an image rotated by any amount. The image will be scaled down if needed to ensure it fits the canvas. The function will rotate the image any angle you want.
// ctx is canvas 2D context
// deg in degrees rotated CW from 3 O-clock
// img to render. NOTE image must be loaded first
function drawRotatedImage(ctx, deg, img) {
const w = img.naturalWidth;
const h = img.naturalHeight;
const cw = ctx.canvas.width;
const ch = ctx.canvas.height;
// convert deg to radians
const rad = deg * Math.PI / 180;
// Get vector for rotated xAxis ax, ay. With aax, aay in first quadrant
const ax = Math.cos(rad), aax = Math.abs(ax);
const ay = Math.sin(rad), aay = Math.abs(ay);
// get the rotated width and height of image
const tw = aax * w + aay * h;
const th = aay * w + aax * h;
// get scale so that image fits the canvas. Dont enlarge only reduce if to big
const scale = Math.min(1, cw / tw, ch / th);
// set canvas transform to center of canvas, rotated and scaled to fit
ctx.setTransform(ax * scale, ay * scale, -ay * scale, ax * scale, cw / 2, ch / 2);
// draw image on canvas offset by half its width and height
ctx.drawImage(img, -w / 2, -h / 2);
// restore canvas transform to default
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
Example
Example using the above function to render image to canvas and then use mouse to draw over the image. Click rotate to rotate the image.
const ctx = canvas.getContext("2d");
const mouse = {x: 0, y: 0, b: false, ox: 0, oy: 0};
var rot = 90;
const img = new Image;
img.src = "https://i.stack.imgur.com/C7qq2.png?s=420&g=1";
img.onload = () => rotImage(ctx, rot, img);
resize();
addEventListener("resize", resize);
rotBtn.addEventListener("click", () => img.complete && rotImage(ctx, rot += 90, img));
addEventListener("mousemove", mouseEvent);
addEventListener("mousedown", mouseEvent);
addEventListener("mouseup", mouseEvent);
addEventListener("mouseout", mouseEvent);
function resize() {
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.strokeStyle = "#00F";
img.complete && rotImage(ctx, rot, img);
}
function mouseEvent(e) {
mouse.ox = mouse.x;
mouse.oy = mouse.y;
mouse.x = e.pageX;
mouse.y = e.pageY;
if (e.type === "mousedown") { mouse.b = true }
else if (e.type === "mouseup" || e.type === "mouseout") { mouse.b = false }
mouse.b && drawWithMouse(ctx, mouse);
}
function drawWithMouse(ctx, mouse) {
ctx.beginPath();
ctx.lineTo(mouse.ox, mouse.oy);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
}
function rotImage(ctx, deg, img) {
const cw = ctx.canvas.width, ch = ctx.canvas.height;
const w = img.naturalWidth, h = img.naturalHeight;
const rad = deg * Math.PI / 180;
const ax = Math.cos(rad), aax = Math.abs(ax);
const ay = Math.sin(rad), aay = Math.abs(ay);
const tw = aax * w + aay * h;
const th = aay * w + aax * h;
const sc = Math.min(1, cw / tw, ch / th);
ctx.clearRect(0, 0, cw, ch);
ctx.setTransform(ax * sc, ay * sc, -ay * sc, ax * sc, cw / 2, ch / 2);
ctx.drawImage(img, -w / 2, -h / 2);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
* {font-family: arial;}
button { position: absolute; top: 10px; left: 10px }
canvas { position: absolute; top: 0px; left: 0px }
<canvas id="canvas"></canvas>
<button id="rotBtn">Rotate</button>

How do i add a link to this animated button

Essentially i found this button that i wanted to add to my wixsite that links to a store. I have gotten the button animation to work and this button exists as a html element on wix. But all the button does currently is do the animation and dosent link. Could someone edit this code so after the animation plays the user will be redirected to a certain link.
I've tried looking up link code and inserting it in logical places to determine where it might work but obviously i dident find anything. And even if it did it likely would have redirected before the animation finished.
Here is the code without any of my attempts to try and fix this problem.
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
Math.randMinMax = function (min, max, round) {
var val = min + (Math.random() * (max - min));
if (round) val = Math.round(val);
return val;
};
Math.TO_RAD = Math.PI / 180;
Math.getAngle = function (x1, y1, x2, y2) {
var dx = x1 - x2,
dy = y1 - y2;
return Math.atan2(dy, dx);
};
Math.getDistance = function (x1, y1, x2, y2) {
var xs = x2 - x1,
ys = y2 - y1;
xs *= xs;
ys *= ys;
return Math.sqrt(xs + ys);
};
var FX = {};
(function () {
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
lastUpdate = new Date(),
mouseUpdate = new Date(),
lastMouse = [],
width, height;
FX.particles = [];
setFullscreen();
document.getElementById('button').addEventListener('mousedown', buttonEffect);
function buttonEffect() {
var button = document.getElementById('button'),
height = button.offsetHeight,
left = button.offsetLeft,
top = button.offsetTop,
width = button.offsetWidth,
x, y, degree;
for (var i = 0; i < 40; i = i + 1) {
if (Math.random() < 0.5) {
y = Math.randMinMax(top, top + height);
if (Math.random() < 0.5) {
x = left;
degree = Math.randMinMax(-45, 45);
} else {
x = left + width;
degree = Math.randMinMax(135, 225);
}
} else {
x = Math.randMinMax(left, left + width);
if (Math.random() < 0.5) {
y = top;
degree = Math.randMinMax(45, 135);
} else {
y = top + height;
degree = Math.randMinMax(-135, -45);
}
}
createParticle({
x: x,
y: y,
degree: degree,
speed: Math.randMinMax(100, 150),
vs: Math.randMinMax(-4, -1)
});
}
}
window.setTimeout(buttonEffect, 100);
loop();
window.addEventListener('resize', setFullscreen);
function createParticle(args) {
var options = {
x: width / 2,
y: height / 2,
color: 'hsla(' + Math.randMinMax(160, 290) + ', 100%, 50%, ' + (Math.random().toFixed(2)) + ')',
degree: Math.randMinMax(0, 360),
speed: Math.randMinMax(300, 350),
vd: Math.randMinMax(-90, 90),
vs: Math.randMinMax(-8, -5)
};
for (key in args) {
options[key] = args[key];
}
FX.particles.push(options);
}
function loop() {
var thisUpdate = new Date(),
delta = (lastUpdate - thisUpdate) / 1000,
amount = FX.particles.length,
size = 2,
i = 0,
p;
ctx.fillStyle = 'rgba(15,15,15,0.25)';
ctx.fillRect(0, 0, width, height);
ctx.globalCompositeStyle = 'lighter';
for (; i < amount; i = i + 1) {
p = FX.particles[i];
p.degree += (p.vd * delta);
p.speed += (p.vs);// * delta);
if (p.speed < 0) continue;
p.x += Math.cos(p.degree * Math.TO_RAD) * (p.speed * delta);
p.y += Math.sin(p.degree * Math.TO_RAD) * (p.speed * delta);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.degree * Math.TO_RAD);
ctx.fillStyle = p.color;
ctx.fillRect(-size, -size, size * 2, size * 2);
ctx.restore();
}
lastUpdate = thisUpdate;
requestAnimFrame(loop);
}
function setFullscreen() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
};
})();
body {
margin: 0;
overflow: hidden;
}
#myCanvas {
display: block;
}
#button {
font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
position: absolute;
font-size: 1.5em;
text-transform: uppercase;
padding: 7px 20px;
left: 50%;
width: 200px;
margin-left: -100px;
top: 50%;
border-radius: 10px;
color: white;
text-shadow: -1px -1px 1px rgba(0,0,0,0.8);
border: 5px solid transparent;
border-bottom-color: rgba(0,0,0,0.35);
background: hsla(260, 100%, 50%, 1);
cursor: pointer;
outline: 0 !important;
animation: pulse 1s infinite alternate;
transition: background 0.4s, border 0.2s, margin 0.2s;
}
#button:hover {
background: hsla(220, 100%, 60%, 1);
margin-top: -1px;
animation: none;
}
#button:active {
border-bottom-width: 0;
margin-top: 5px;
}
#keyframes pulse {
0% {
margin-top: 0px;
}
100% {
margin-top: 6px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<button id="button">Donate</button>
<canvas id="myCanvas" width="500" height="500"></canvas>
</body>
</html>
So again the expected result is to play the animation for the button then redirect to another page and the current result is the button simply playing the animation when clicked. If anyone could please write this code it would be super helpful.
Try changing your button to a href link. You may have to add some extra styling to the id class, but this should work.
<a id="button" href="https://www.linktosite.com">Link Button</a>
Put this on the button html tag onclick="location.href='http://www.link.com'"
You should add an activity when click on button. For example:
<button id="button" onclick="window.location.href = 'https://www.google.com';">Donate</button>
Demo:
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
Math.randMinMax = function (min, max, round) {
var val = min + (Math.random() * (max - min));
if (round) val = Math.round(val);
return val;
};
Math.TO_RAD = Math.PI / 180;
Math.getAngle = function (x1, y1, x2, y2) {
var dx = x1 - x2,
dy = y1 - y2;
return Math.atan2(dy, dx);
};
Math.getDistance = function (x1, y1, x2, y2) {
var xs = x2 - x1,
ys = y2 - y1;
xs *= xs;
ys *= ys;
return Math.sqrt(xs + ys);
};
var FX = {};
(function () {
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
lastUpdate = new Date(),
mouseUpdate = new Date(),
lastMouse = [],
width, height;
FX.particles = [];
setFullscreen();
document.getElementById('button').addEventListener('mousedown', buttonEffect);
function buttonEffect() {
var button = document.getElementById('button'),
height = button.offsetHeight,
left = button.offsetLeft,
top = button.offsetTop,
width = button.offsetWidth,
x, y, degree;
for (var i = 0; i < 40; i = i + 1) {
if (Math.random() < 0.5) {
y = Math.randMinMax(top, top + height);
if (Math.random() < 0.5) {
x = left;
degree = Math.randMinMax(-45, 45);
} else {
x = left + width;
degree = Math.randMinMax(135, 225);
}
} else {
x = Math.randMinMax(left, left + width);
if (Math.random() < 0.5) {
y = top;
degree = Math.randMinMax(45, 135);
} else {
y = top + height;
degree = Math.randMinMax(-135, -45);
}
}
createParticle({
x: x,
y: y,
degree: degree,
speed: Math.randMinMax(100, 150),
vs: Math.randMinMax(-4, -1)
});
}
}
window.setTimeout(buttonEffect, 100);
loop();
window.addEventListener('resize', setFullscreen);
function createParticle(args) {
var options = {
x: width / 2,
y: height / 2,
color: 'hsla(' + Math.randMinMax(160, 290) + ', 100%, 50%, ' + (Math.random().toFixed(2)) + ')',
degree: Math.randMinMax(0, 360),
speed: Math.randMinMax(300, 350),
vd: Math.randMinMax(-90, 90),
vs: Math.randMinMax(-8, -5)
};
for (key in args) {
options[key] = args[key];
}
FX.particles.push(options);
}
function loop() {
var thisUpdate = new Date(),
delta = (lastUpdate - thisUpdate) / 1000,
amount = FX.particles.length,
size = 2,
i = 0,
p;
ctx.fillStyle = 'rgba(15,15,15,0.25)';
ctx.fillRect(0, 0, width, height);
ctx.globalCompositeStyle = 'lighter';
for (; i < amount; i = i + 1) {
p = FX.particles[i];
p.degree += (p.vd * delta);
p.speed += (p.vs);// * delta);
if (p.speed < 0) continue;
p.x += Math.cos(p.degree * Math.TO_RAD) * (p.speed * delta);
p.y += Math.sin(p.degree * Math.TO_RAD) * (p.speed * delta);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.degree * Math.TO_RAD);
ctx.fillStyle = p.color;
ctx.fillRect(-size, -size, size * 2, size * 2);
ctx.restore();
}
lastUpdate = thisUpdate;
requestAnimFrame(loop);
}
function setFullscreen() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
};
})();
body {
margin: 0;
overflow: hidden;
}
#myCanvas {
display: block;
}
#button {
font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
position: absolute;
font-size: 1.5em;
text-transform: uppercase;
padding: 7px 20px;
left: 50%;
width: 200px;
margin-left: -100px;
top: 50%;
border-radius: 10px;
color: white;
text-shadow: -1px -1px 1px rgba(0,0,0,0.8);
border: 5px solid transparent;
border-bottom-color: rgba(0,0,0,0.35);
background: hsla(260, 100%, 50%, 1);
cursor: pointer;
outline: 0 !important;
animation: pulse 1s infinite alternate;
transition: background 0.4s, border 0.2s, margin 0.2s;
}
#button:hover {
background: hsla(220, 100%, 60%, 1);
margin-top: -1px;
animation: none;
}
#button:active {
border-bottom-width: 0;
margin-top: 5px;
}
#keyframes pulse {
0% {
margin-top: 0px;
}
100% {
margin-top: 6px;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
</head>
<body>
<button id="button" onclick="window.location.href = 'https://www.google.com';">Donate</button>
<canvas id="myCanvas" width="500" height="500"></canvas>
</body>
</html>

circle progressbar doesn't start from the middle

I have a circular progress bar that must start from 0 degree - middle of a top part of the circle. But I've noticed that it starts not in the middle, but a little to the left. How do I fix that?
Here's the code:
var bar = document.getElementById('progressbar'),
createProgressBar = function(bar) {
var options = {
start: 0,
width: bar.getAttribute('data-width'),
height: bar.getAttribute('data-height'),
percent: 90,
lineWidth: bar.getAttribute('data-linewidth')
},
canvas = document.createElement('canvas'),
paper = canvas.getContext('2d'),
span = document.createElement('span'),
radius = (options.width - options.lineWidth) / 2,
color = paper.createLinearGradient(0, 0, options.width, 0),
step = 1.5;
span.style.width = bar.style.width = options.width + 'px';
span.style.height = bar.style.height = options.height + 'px';
canvas.width = options.width;
canvas.height = options.height;
span.style.lineHeight = options.height + 'px';
color.addColorStop(0, "red");
color.addColorStop(0.5, "red");
color.addColorStop(1.0, "red");
bar.appendChild(span);
bar.appendChild(canvas);
(function animat() {
span.textContent = options.start + '%';
createCircle(options, paper, radius, color, Math.PI * 1.5, Math.PI * step);
console.log(step);
options.start++;
step += 0.02;
if (options.start <= options.percent) {
setTimeout(animat, 10);
}
})();
},
createCircle = function(options, paper, radius, color, start, end) {
paper.clearRect(
options.width / 2 - radius - options.lineWidth,
options.height / 2 - radius - options.lineWidth,
radius * 2 + (options.lineWidth * 2),
radius * 2 + (options.lineWidth * 2)
);
paper.beginPath();
paper.arc(options.width / 2, options.height / 2, radius, 0, Math.PI * 2, false);
paper.strokeStyle = '#dbd7d2';
paper.lineCap = 'round';
paper.lineWidth = options.lineWidth;
paper.stroke();
paper.closePath();
paper.beginPath();
paper.arc(options.width / 2, options.height / 2, radius, start, end, false);
paper.strokeStyle = color;
paper.lineCap = 'square';
paper.lineWidth = options.lineWidth;
paper.stroke();
paper.closePath();
};
createProgressBar(bar);
#progressbar {
position: fixed;
top: 50%;
left: 50%;
margin-top: -150px;
margin-left: -150px;
}
canvas {
position: absolute;
display: block;
left: 0;
top: 0
}
span {
display: block;
color: #222;
text-align: center;
font-family: "sans serif", tahoma, Verdana, helvetica;
font-size: 30px
}
<div id="progressbar" data-width="320" data-height="320" data-linewidth="16"></div>
That's what the progress bar looks like: https://jsfiddle.net/ue20b8bd/
P.S. I've modified the code from github: https://github.com/su-ning/html5-circle-progressbar
The problem was with the lineCap property. Using 'butt' as a lineCap fixed the problem!

Is there a way to make an element disappear BEFORE the mousedown event activates?

In the following snippet, you'll notice that an overlay asks you to 'Click Anywhere', and will add circles to the canvas on mousedown and mouseup events. Although the overlay text disappears on mousedown, If you click anywhere on the overlay element the canvas doesn't get the mousedown event to draw the start circle.
var canvas = document.getElementById('target'),
context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.addEventListener('mousedown', addStartNode);
canvas.addEventListener('mouseup', addEndNode);
document.body.addEventListener('mousedown', hideOverlay);
document.body.addEventListener('mouseup', showOverlay);
function hideOverlay() {
document.getElementById('overlay').style.display = 'none';
}
function showOverlay() {
document.getElementById('overlay').style.display = 'block';
}
function addStartNode(evt) {
drawCircle(evt.clientX, evt.clientY, 10, 'green');
}
function addEndNode(evt) {
drawCircle(evt.clientX, evt.clientY, 10, 'blue');
}
function drawCircle(x, y, r, c) {
context.beginPath();
context.arc(x, y, r, 0, 2 * Math.PI, false);
context.fillStyle = c;
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
}
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#overlay {
position: absolute;
top: 10%;
left: 1em;
right: 1em;
font-size: 4em;
text-align: center;
z-index: 10;
background: rgba(255, 255, 255, 0.7);
}
#target {
position: relative;
width: 100%;
height: 100%;
background: aqua;
}
.node {
position: absolute;
background: blue;
width: 20px;
height: 20px;
transform: translate(-50%, -50%);
}
<div id="overlay">
Click Anywhere
</div>
<canvas id="target"></canvas>
I thought of just moving the event handler onto a container element or on the body element, which would catch the event as it propagates, but sometimes that's just not possible, such as when you're using an HTML5 game engine to process interactions.
Does anyone have any clever solutions for this?
EDIT:
What I really had in mind was a situation where translating the mouse position to the canvas was much more complicated, such as when a game engine or other canvas library is being used. In the following snippet I use PIXI.js. Note how you can drag the top left and middle bottom nodes, but not the node on the right which is covered by the text.
document.body.addEventListener('mousedown', hideOverlay);
document.body.addEventListener('mouseup', showOverlay);
function hideOverlay() {
document.getElementById('overlay').style.display = 'none';
}
function showOverlay() {
document.getElementById('overlay').style.display = 'block';
}
var nodeRadius = 50;
function Node(x, y) {
this.g = new PIXI.Graphics();
this.position.x = x;
this.position.y = y;
this.g.node = this;
this.drawCircle();
this.g.pivot = new PIXI.Point(nodeRadius / 2, nodeRadius / 2);
this.g.interactive = true;
this.defaultPos = new PIXI.Point(this.position.x, this.position.y);
this.g.on('mousedown', selectNode);
this.g.on('mouseup', connectNode);
this.g.on('mousemove', moveNode);
}
Node.prototype = {
reset: function() {
this.position.x = this.defaultPos.x;
this.position.y = this.defaultPos.y;
},
drawCircle: function() {
this.g.clear();
this.g.beginFill(0x3333FF, 1);
this.g.drawCircle(0, 0, nodeRadius);
this.g.endFill();
},
connectTo: function(node) {
this.drawCircle();
this.g.moveTo(0, 0);
this.g.lineStyle(5, 0xDDEEFF);
this.g.lineTo(node.position.x - this.position.x, node.position.y - this.position.y);
},
get position() {
return this.g.position;
},
set position(p) {
this.g.position = p;
}
};
var renderer = PIXI.autoDetectRenderer(600, 400),
container = new PIXI.Container(),
selectedNode = null;
container.position.x = -150;
container.position.y = 200;
container.scale.x = 0.3;
container.scale.y = 0.3;
var nodes = [
new Node(700, -500),
new Node(2200, 50),
new Node(1500, 450)
];
for (var i = 0; i < nodes.length; i++) {
container.addChild(nodes[i].g);
}
document.getElementById('content').appendChild(renderer.view);
requestAnimationFrame(animate);
function animate() {
renderer.render(container);
requestAnimationFrame(animate);
}
function selectNode() {
this.node.drawCircle();
selectedNode = this.node;
}
function connectNode() {
if (selectedNode) {
selectedNode.reset();
selectedNode = null;
}
}
function moveNode() {
if (selectedNode) {
var mousePos = renderer.plugins.interaction.mouse.getLocalPosition(container);
selectedNode.position.x = mousePos.x;
selectedNode.position.y = mousePos.y;
checkCollision();
}
}
function checkCollision() {
if (selectedNode) {
for (var i = 0; i < nodes.length; i++) {
if (nodes[i] !== selectedNode && dist(selectedNode.position, nodes[i].position) < nodeRadius * 2) {
selectedNode.reset();
selectedNode.connectTo(nodes[i]);
selectedNode = null;
break;
}
}
}
}
function dist(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#overlay {
position: absolute;
top: 100px;
left: 10px;
width: 580px;
font-size: 4em;
text-align: center;
z-index: 100;
background: rgba(255, 255, 255, 0.5);
}
#content {
display: inline-block;
position: relative;
margin: 1em;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/3.0.8/pixi.min.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/3.0.8/pixi.js"></script>
</head>
<body>
<div id="content">
<div id="overlay">
Drag one node to another
</div>
<script src="script.js"></script>
</div>
</body>
</html>
I purposefully moved and scaled the container, because that happens often in games. The canvas itself may be offset from the page and may not even share the same parent as the overlay, which further complicates translating a mouse position to game coordinates.
This is why I was thinking it would be nice to somehow remove the overlay element before the mousedown event fires, because then we wouldn't have to worry about it.
Here is a fiddle.
Adding an eventlistener to the overlay as well should fix your problem:
document.getElementById("overlay").addEventListener('mousedown', addStartNode);
var canvas = document.getElementById('target'),
context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.addEventListener('mousedown', addStartNode);
canvas.addEventListener('mouseup', addEndNode);
document.getElementById("overlay").addEventListener('mousedown', addStartNode);
document.body.addEventListener('mousedown', hideOverlay);
document.body.addEventListener('mouseup', showOverlay);
function hideOverlay() {
document.getElementById('overlay').style.display = 'none';
}
function showOverlay() {
document.getElementById('overlay').style.display = 'block';
}
function addStartNode(evt) {
drawCircle(evt.clientX, evt.clientY, 10, 'green');
}
function addEndNode(evt) {
drawCircle(evt.clientX, evt.clientY, 10, 'blue');
}
function drawCircle(x, y, r, c) {
context.beginPath();
context.arc(x, y, r, 0, 2 * Math.PI, false);
context.fillStyle = c;
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
}
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#overlay {
position: absolute;
top: 10%;
left: 1em;
right: 1em;
font-size: 4em;
text-align: center;
z-index: 10;
background: rgba(255, 255, 255, 0.7);
}
#target {
position: relative;
width: 100%;
height: 100%;
background: aqua;
}
.node {
position: absolute;
background: blue;
width: 20px;
height: 20px;
transform: translate(-50%, -50%);
}
<div id="overlay">
Click Anywhere
</div>
<canvas id="target"></canvas>
Events bubble up in the hierarchy of the dom. Since your 'hideOverlay' is an event on the body, the top most element, it won't bubble up to canvas. It would have to bubble down, which it doesn't. Since the overlay is positioned absolute, it's not inside the canvas, so a click on it won't bubble up to the canvas.
In short, the simple solution is to just have one event handler on a mousedown, eg body.mousedown which means you want to do the same thing where-ever the event takes place on the screen, namely hiding the overlay and drawing a circle on the canvas, so don't complicate things by having two event handlers. In body.mousedown, hide the overlay, and draw a circle.
Btw your code would also work as expected if you just call addStartNode from hideOverlay, but why would you?
You may simply use a unique event detection for each mouse event.
So first dropping the canvas.addEventListener()s, then gathering show/hide overlay and draw blue/green circle, like this:
var canvas = document.getElementById('target'),
context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.addEventListener('mousedown', mouseDown);
document.body.addEventListener('mouseup', mouseUp);
function mouseDown(evt) {
document.getElementById('overlay').style.display = 'none';
drawCircle(evt.clientX, evt.clientY, 10, 'green');
}
function mouseUp(evt) {
drawCircle(evt.clientX, evt.clientY, 10, 'blue');
document.getElementById('overlay').style.display = 'block';
}
function drawCircle(x, y, r, c) {
context.beginPath();
context.arc(x, y, r, 0, 2 * Math.PI, false);
context.fillStyle = c;
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
}
nus' comment about using dispatchEvent does the trick.
document.getElementById('overlay').addEventListener('mousedown', function(evt) {
setTimeout(function() {
renderer.view.dispatchEvent(evt);
},0);
});
document.body.addEventListener('mousedown', hideOverlay);
document.body.addEventListener('mouseup', showOverlay);
function hideOverlay() {
document.getElementById('overlay').style.display = 'none';
}
function showOverlay() {
document.getElementById('overlay').style.display = 'block';
}
var nodeRadius = 50;
function Node(x, y) {
this.g = new PIXI.Graphics();
this.position.x = x;
this.position.y = y;
this.g.node = this;
this.drawCircle();
this.g.pivot = new PIXI.Point(nodeRadius / 2, nodeRadius / 2);
this.g.interactive = true;
this.defaultPos = new PIXI.Point(this.position.x, this.position.y);
this.g.on('mousedown', selectNode);
this.g.on('mouseup', connectNode);
this.g.on('mousemove', moveNode);
}
Node.prototype = {
reset: function() {
this.position.x = this.defaultPos.x;
this.position.y = this.defaultPos.y;
},
drawCircle: function() {
this.g.clear();
this.g.beginFill(0x3333FF, 1);
this.g.drawCircle(0, 0, nodeRadius);
this.g.endFill();
},
connectTo: function(node) {
this.drawCircle();
this.g.moveTo(0, 0);
this.g.lineStyle(5, 0xDDEEFF);
this.g.lineTo(node.position.x - this.position.x, node.position.y - this.position.y);
},
get position() {
return this.g.position;
},
set position(p) {
this.g.position = p;
}
};
var renderer = PIXI.autoDetectRenderer(600, 400),
container = new PIXI.Container(),
selectedNode = null;
document.getElementById('overlay').addEventListener('mousedown', function(evt) {
setTimeout(function() {
renderer.view.dispatchEvent(evt);
}, 0);
});
container.position.x = -150;
container.position.y = 200;
container.scale.x = 0.3;
container.scale.y = 0.3;
var nodes = [
new Node(700, -500),
new Node(2200, 50),
new Node(1500, 450)
];
for (var i = 0; i < nodes.length; i++) {
container.addChild(nodes[i].g);
}
document.getElementById('content').appendChild(renderer.view);
requestAnimationFrame(animate);
function animate() {
renderer.render(container);
requestAnimationFrame(animate);
}
function selectNode() {
this.node.drawCircle();
selectedNode = this.node;
}
function connectNode() {
if (selectedNode) {
selectedNode.reset();
selectedNode = null;
}
}
function moveNode() {
if (selectedNode) {
var mousePos = renderer.plugins.interaction.mouse.getLocalPosition(container);
selectedNode.position.x = mousePos.x;
selectedNode.position.y = mousePos.y;
checkCollision();
}
}
function checkCollision() {
if (selectedNode) {
for (var i = 0; i < nodes.length; i++) {
if (nodes[i] !== selectedNode && dist(selectedNode.position, nodes[i].position) < nodeRadius * 2) {
selectedNode.reset();
selectedNode.connectTo(nodes[i]);
selectedNode = null;
break;
}
}
}
}
function dist(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#overlay {
position: absolute;
top: 100px;
left: 10px;
width: 580px;
font-size: 4em;
text-align: center;
z-index: 100;
background: rgba(255, 255, 255, 0.5);
}
#content {
display: inline-block;
position: relative;
margin: 1em;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/3.0.8/pixi.min.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/3.0.8/pixi.js"></script>
</head>
<body>
<div id="content">
<div id="overlay">
Drag one node to another
</div>
<script src="script.js"></script>
</div>
</body>
</html>
Note that it needs to be done in a timeout or you get an InvalidStateError since "the event is already being dispatched".

Why is this codepen demo not working locally?

I just stumbled upon a codepen demo http://codepen.io/timohausmann/pen/icCer
Then code works fine in codepen window. When, I copied it in a local HTML file it stopped working.
Here is the code all combined in one .html file
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
overflow: hidden;
}
#myCanvas {
display: block;
}
#button {
font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
position: absolute;
font-size: 1.5em;
text-transform: uppercase;
padding: 7px 20px;
left: 50%;
width: 200px;
margin-left: -100px;
top: 50%;
border-radius: 10px;
color: white;
text-shadow: -1px -1px 1px rgba(0,0,0,0.8);
border: 5px solid transparent;
border-bottom-color: rgba(0,0,0,0.35);
background: hsla(260, 100%, 50%, 1);
cursor: pointer;
animation: pulse 1s infinite alternate;
transition: background 0.4s, border 0.2s, margin 0.2s;
}
#button:hover {
background: hsla(220, 100%, 60%, 1);
margin-top: -1px;
animation: none;
}
#button:active {
border-bottom-width: 0;
margin-top: 5px;
}
#keyframes pulse {
0% {
margin-top: 0px;
}
100% {
margin-top: 6px;
}
}
</style>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
Math.randMinMax = function(min, max, round) {
var val = min + (Math.random() * (max - min));
if( round ) val = Math.round( val );
return val;
};
Math.TO_RAD = Math.PI/180;
Math.getAngle = function( x1, y1, x2, y2 ) {
var dx = x1 - x2,
dy = y1 - y2;
return Math.atan2(dy,dx);
};
Math.getDistance = function( x1, y1, x2, y2 ) {
var xs = x2 - x1,
ys = y2 - y1;
xs *= xs;
ys *= ys;
return Math.sqrt( xs + ys );
};
var FX = {};
(function() {
var canvas = document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
lastUpdate = new Date(),
mouseUpdate = new Date(),
lastMouse = [],
width, height;
FX.particles = [];
setFullscreen();
document.getElementById('button').addEventListener('mousedown', buttonEffect);
function buttonEffect() {
var button = document.getElementById('button'),
height = button.offsetHeight,
left = button.offsetLeft,
top = button.offsetTop,
width = button.offsetWidth,
x, y, degree;
for(var i=0;i<40;i=i+1) {
if( Math.random() < 0.5 ) {
y = Math.randMinMax(top, top+height);
if( Math.random() < 0.5 ) {
x = left;
degree = Math.randMinMax(-45,45);
} else {
x = left + width;
degree = Math.randMinMax(135,225);
}
} else {
x = Math.randMinMax(left, left+width);
if( Math.random() < 0.5 ) {
y = top;
degree = Math.randMinMax(45,135);
} else {
y = top + height;
degree = Math.randMinMax(-135, -45);
}
}
createParticle({
x: x,
y: y,
degree: degree,
speed: Math.randMinMax(100, 150),
vs: Math.randMinMax(-4,-1)
});
}
}
window.setTimeout(buttonEffect, 100);
loop();
window.addEventListener('resize', setFullscreen );
function createParticle( args ) {
var options = {
x: width/2,
y: height/2,
color: 'hsla('+ Math.randMinMax(160, 290) +', 100%, 50%, '+(Math.random().toFixed(2))+')',
degree: Math.randMinMax(0, 360),
speed: Math.randMinMax(300, 350),
vd: Math.randMinMax(-90,90),
vs: Math.randMinMax(-8,-5)
};
for (key in args) {
options[key] = args[key];
}
FX.particles.push( options );
}
function loop() {
var thisUpdate = new Date(),
delta = (lastUpdate - thisUpdate) / 1000,
amount = FX.particles.length,
size = 2,
i = 0,
p;
ctx.fillStyle = 'rgba(15,15,15,0.25)';
ctx.fillRect(0,0,width,height);
ctx.globalCompositeStyle = 'lighter';
for(;i<amount;i=i+1) {
p = FX.particles[ i ];
p.degree += (p.vd * delta);
p.speed += (p.vs);// * delta);
if( p.speed < 0 ) continue;
p.x += Math.cos(p.degree * Math.TO_RAD) * (p.speed * delta);
p.y += Math.sin(p.degree * Math.TO_RAD) * (p.speed * delta);
ctx.save();
ctx.translate( p.x, p.y );
ctx.rotate( p.degree * Math.TO_RAD );
ctx.fillStyle = p.color;
ctx.fillRect( -size, -size, size*2, size*2 );
ctx.restore();
}
lastUpdate = thisUpdate;
requestAnimFrame( loop );
}
function setFullscreen() {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
};
})();
</script>
<button id="button">click me</button>
<canvas id="myCanvas" width="500" height="500"></canvas>
</body>
</html>
This is code from all three codepen windows put together but it doesn't seem to work?
Add jQuery library
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

Categories

Resources