I've been searching around and still couldnt find a fix to how to keep this moving object within the borders of my canvas. We tried to put an if statement into each arrow key movement functions, but that didnt seem to work completely. I'm not sure whether or not this is the right way to go about handling game movement since the image that we are moving is defined in the HTML and not defined as a variable in the javascript.
var width = 80;
var height = 40;
function leftArrowPressed() {
var element = document.getElementById("image1");
element.style.left = parseInt(element.style.left) - 17+'px';
}
function rightArrowPressed() {
var element = document.getElementById("image1");
element.style.left = parseInt(element.style.left) + 25 +'px';
}
function upArrowPressed() {
var element = document.getElementById("image1");
element.style.top = parseInt(element.style.top) - 17 + 'px';
}
function downArrowPressed() {
var element = document.getElementById("image1");
element.style.top = parseInt(element.style.top) + 17 + 'px';
}
function moveSelection(evt) {
switch (evt.keyCode) {
case 37:
leftArrowPressed();
break;
case 39:
rightArrowPressed();
break;
case 38:
upArrowPressed();
break;
case 40:
downArrowPressed();
break;
}
};
function docReady()
{
window.addEventListener('keydown', moveSelection);
}
var canvas = new fabric.Canvas('c', { selection: false });
var grid = 50;
// create grid
for (var i = 0; i < (600 / grid); i++) {
canvas.add(new fabric.Line([ i * grid, 0, i * grid, 600], { stroke: '#ccc', selectable: false }));
canvas.add(new fabric.Line([ 0, i * grid, 600, i * grid], { stroke: '#ccc', selectable: false }))
}
// add objects
canvas.add(new fabric.Rect({
left: 100,
top: 100,
width: 50,
height: 50,
fill: '#faa',
originX: 'left',
originY: 'top',
centeredRotation: true
}));
canvas.add(new fabric.Circle({
left: 300,
top: 300,
radius: 50,
fill: '#9f9',
originX: 'left',
originY: 'top',
centeredRotation: true
}));
// snap to grid
canvas.on('object:moving', function(options) {
options.target.set({
left: Math.round(options.target.left / grid) * grid,
top: Math.round(options.target.top / grid) * grid
});
});
canvas.on('object:moving', function (e) {
var obj = document.getElementById("image1");
// if object is too big ignore
if(obj.currentHeight > obj.canvas.height || obj.currentWidth > obj.canvas.width){
return;
}
obj.setCoords();
// top-left corner
if(obj.getBoundingRect().top < 0 || obj.getBoundingRect().left < 0){
obj.top = Math.max(obj.top, obj.top-obj.getBoundingRect().top);
obj.left = Math.max(obj.left, obj.left-obj.getBoundingRect().left);
}
// bot-right corner
if(obj.getBoundingRect().top+obj.getBoundingRect().height > obj.canvas.height || obj.getBoundingRect().left+obj.getBoundingRect().width > obj.canvas.width){
obj.top = Math.min(obj.top, obj.canvas.height-obj.getBoundingRect().height+obj.top-obj.getBoundingRect().top);
obj.left = Math.min(obj.left, obj.canvas.width-obj.getBoundingRect().width+obj.left-obj.getBoundingRect().left);
}
});
body::-webkit-scrollbar {
width: 1em;
}
body::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
}
body::-webkit-scrollbar-thumb {
background-color: darkgrey;
outline: 1px solid slategrey;
}
body {
overflow
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="GridEXEMovement.js"></script>
<title>Test Move Object</title>
<link rel="stylesheet" href="dimRoom.css">
</head>
<body onload="docReady()" onkeydown="" onkeyup="">
<!-- uncomment this div when you want to implement the green desktop Div -->
<nav>
<ul>
<li><button id="zeldaDeskTop">deskTop</button></li>
<span>|</span>
<li><button id="zeldaBrowser">browser</button></li>
<span>|</span>
<li><button id="zeldaExe">.exe</button></li>
<span>|</span>
<li><button id="zeldaGrid">grid</button></li>
</ul>
</nav>
<div id="screen">
<div id="content"></div>
<style>
body::-webkit-scrollbar {
width: 1em;
}
body::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
}
html {
height: 100%;
}
body::-webkit-scrollbar-thumb {
background-color: darkgrey;
outline: 1px solid slategrey;
}
body {
overflow-x: hidden;
}
html {
height: 100%;
}
#content{
background-color: transparent;
background-image: linear-gradient(0deg, transparent 24%, rgba(255, 255, 255, .05) 25%, rgba(255, 255, 255, .05) 26%, transparent 27%, transparent 74%, rgba(255, 255, 255, .05) 75%, rgba(255, 255, 255, .05) 76%, transparent 77%, transparent), linear-gradient(90deg, transparent 24%, rgba(255, 255, 255, .05) 25%, rgba(255, 255, 255, .05) 26%, transparent 27%, transparent 74%, rgba(255, 255, 255, .05) 75%, rgba(255, 255, 255, .05) 76%, transparent 77%, transparent);
height:100%;
background-size:50px 50px;
}
.follow-me {
position:absolute;
bottom:10px;
right:10px;
text-decoration: none;
color: #FFFFFF;
}
</style>
</div>
<img id="image1" src="https://www.bigbluebubble.com/wp-content/uploads/2017/07/PixelDodggers_Classic8-bitExperience.png" style="position: absolute; right: 100; left:980; top:300; z-index: 2; margin:0;" height="50" width="50">
<img id="DigitalCave" src="http://pixelartmaker.com/art/8fb5394537feede.png" style="position:absolute; left:560; top:146; z-index: 1;" height="30" width="40">
<img id="DataNode" src="http://pixelart.studio/Gallery/Image/100b0c98-d22d-4ffc-868a-9862aad1da4a?type=png" style="position:absolute; left:360; top:544; z-index: 1;" height="30" width="40">
<img id="Fire" src="https://cdn.theatlantic.com/assets/media/mt/science/flame-330.png" style="position:absolute; left:510; top:537; z-index: 1;" height="30" width="40">
<script type="text/javascript" src="dimRoom.js"></script>
</body>
</html>
Create a variable for speed:
var yspeed = 17;
var xspeed = 25;
You made a mistake there by the way. You sideways speeds are different each way.
Sideways speed should be the same both ways 25px each way.
If you canvas width is on 50px then the player will move very quickly across the canvas with a speed of 17px and 25px.
Then check if the speed isn’t equal to zero
if (speed !== 0) { // you are moving your character
// put your JavaScript you just created for wish and height checking here
}
Also in order to check if you’ve pressed your arrows return a Boolean when they have been used like this:
function leftArrowPressed() {
var element = document.getElementById("image1");
element.style.left = parseInt(element.style.left) - xspeed+'px';
return true;
}
function rightArrowPressed() {
var element = document.getElementById("image1");
element.style.left = parseInt(element.style.left) + xspeed +'px';
return true;
}
function upArrowPressed() {
var element = document.getElementById("image1");
element.style.top = parseInt(element.style.top) - yspeed + 'px';
return true;
}
function downArrowPressed() {
var element = document.getElementById("image1");
element.style.top = parseInt(element.style.top) + yspeed + 'px';
return true;
}
I hope this helps.
I would make an x and y speed, and do something like this for the player:
player = {
x: 0,
y: 0,
width: 50,
height: 50,
xspeed: 0,
yspeed: 0
};
Then I would do an if statement like this:
if (player.x < 0 || player.x > canvas.width) {
player.x = 0;
player.xspeed = 0;
}
if (player.y < 0 || player.y > canvas.height) {
player.y = 0;
player.yspeed = 0;
}
That should keep the player visible. Correct me if I'm wrong.
Related
So, I am getting back into javascript coding, and I am resuming an older project. I am attempting to capture the mouse position in dedicated variables (mouseX and mouseY), for ease of use.
I have successfully managed to print out the mouse coordinates in real time, but when I try to place those coordinates into dedicated variables for ease of use, the program fails.
I believe this is most likely a simple syntax error, but I don't know where else to look for what I'm doing wrong.
This code fragment works correctly:
document.addEventListener('mousemove', (event) => {
document.getElementById("fiddleText").innerHTML = (`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`);
})
However, when I try to store the mouse position in two variables, like so:
document.addEventListener('mousemove', (event) => {
mouseX = event.ClientX;
mouseY = event.ClientY;
document.getElementByID("fiddleText").innerHTML = (`Mouse X: `+ mouseX + `Mouse Y: ` + mouseY);
})
the program fails.
Note: I've updated the second code fragment to fix a syntax error that was brought to my attention, but it still doesn't work.
The original second fragment looked like this:
document.addEventListener('mousemove', (event) => {
mouseX = ${event.clientX};
mouseY = ${event.clientY};
document.getElementByID("fiddleText").innerHTML = (`Mouse X: `+ mouseX + `Mouse Y: ` + mouseY);
})
I'd like to imagine that my question can be answered using only the code shown above, but last time I believed that, I was mistaken. As such, I have pasted my full javascript program below.
Note: This program is a work-in-progress, and there is a comment header stating "this is the problem area"; ignore this for now, that is an unrelated issue. Right now, I'm just trying to get the mouse to work.
//canvas elements
var canvas = document.getElementById("SnekGamCanvas");
var ctx = canvas.getContext("2d");
canvas.addEventListener('click', function () { }, false);
/*
//some code from stack overflow: (https://stackoverflow.com/questions/9880279/how-do-i-add-a-simple-onclick-event-handler-to-a-canvas-element)
var elem = document.getElementById('canvas'),
elemLeft = elem.offsetLeft + elem.clientLeft,
elemTop = elem.offsetTop + elem.clientTop,
context = elem.getContext('2d'),
elements = [];
// Add event listener for `click` events.
elem.addEventListener('click', function (event) {
var x = event.pageX - elemLeft,
y = event.pageY - elemTop;
// Collision detection between clicked offset and element.
elements.forEach(function (element) {
if (y > element.top && y < element.top + element.height
&& x > element.left && x < element.left + element.width) {
alert('clicked an element');
}
});
}, false);
// Add element.
elements.push({
colour: '#05EFFF',
width: 150,
height: 100,
top: 20,
left: 15
});
// Render elements.
elements.forEach(function (element) {
context.fillStyle = element.colour;
context.fillRect(element.left, element.top, element.width, element.height);
});
*/
//End of code from stack overflow
//some important variables
var px = canvas.width / 2;
var py = canvas.height / 2;
var snekColor = "#EC942D";
var clock = 0;
var mouseX = 0.5;
var mouseY = 0.5;
//classes
class clickButton {
constructor(text, color, width, height, radius) {
this.text = text;
this.color = color;
this.width = width;
this.height = height;
this.radius = radius;
}
drawButton(xpos, ypos) {
ctx.strokeStyle = "#000000"
ctx.fillStyle = this.color;
roundRect(xpos, ypos, this.width, this.height, this.radius, true, true, this.color);
ctx.fillStyle = "#000000";
ctx.strokeStyle = "#000000";
ctx.font = '40px san-serif';
ctx.strokeText(this.text, xpos + 10, ypos + 40);
ctx.fillText(this.text, xpos + 10, ypos + 40);
//draw_Ball(303, 500, 50, snekColor);
}
clickOnButton() {
}
}
//buttons
var startButton = new clickButton("Start Game", "#74B5ED", 200, 50, 20);
//images
var seel = new Image();
seel.onload = function () {
ctx.drawImage(seel, 0, 0, canvas.width, canvas.height);
}
seel.src = "https://assets.pokemon.com/assets/cms2/img/pokedex/full/086.png"
var snek_title = new Image();
snek_title.onload = function () {
ctx.drawImage(snek_title, 0, 0, canvas.width, canvas.height);
}
snek_title.src = "https://globin347.com/images/Snake%20Title.png"
//stuff about mouse moving
document.addEventListener('mousemove', (event) => {
//document.getElementById("fiddleText").innerHTML = (`Mouse X: ${event.clientX}, Mouse Y: ${event.clientY}`);
mouseX = event.ClientX;
mouseY = event.ClientY;
document.getElementByID("fiddleText").innerHTML = (`Mouse X: `+ mouseX + `Mouse Y: ` + mouseY);
})
//begin
var gameState = 0;
function draw() {
clock += 1;
ctx.clearRect(0, 0, canvas.width, canvas.height);
//document.getElementById("fiddleText").innerHTML = ("Clock: " + clock);
if (gameState == 0) {
//this hasn't been implemented yet
startMenu();
}
else if (gameState == 1) {
//this hasn't been implemented yet either
playGame();
}
else if (gameState == 2) {
//ditto
gameOver();
}
else {
//something's wrong
ctx.drawImage(seel, 0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#b30000";
ctx.strokeStyle = "#000000";
ctx.font = '140px san-serif';
ctx.fillText('OH NO', 120, 120);
ctx.strokeText('OH NO', 120, 120);
ctx.fillText('IT BLOKE', 200, 630);
ctx.strokeText('IT BLOKE', 200, 630);
}
}
setInterval(draw, 10);
function startMenu() {
ctx.drawImage(snek_title, 0, 0, canvas.width, canvas.height);
/***********************************************
*
*
* This is the problem area. When the next line, startButton.drawButton(100, 100) is commented out, the rest of the code workes normally.
* However, if the line is not commented out, draw_Ball doesn't run, indicating that the program crashed somewhere in the button code.
* I would like to reiterate that the button's functionality has not yet been implemented; I am only trying to get it to display.
*
*
**********************************************/
//startButton.drawButton((canvas.width / 2) - 100, (canvas.height * (4 / 5)));
//flashing lights
/*flashTime = timer % 100;
if (timer % 2) {
draw_Ball(200, 700, 50, snekColor);
}*/
draw_Ball(200, 700, 50, snekColor);
}
function playGame() {
draw_Ball(200, 700, 50, snekColor);
draw_Ball(400, 700, 50, snekColor);
draw_Ball(300, 500, 50, snekColor);
}
function gameOver() {
}
//this function was stolen from stack overflow
function showImage(width, height, image_source, alt_text) {
var img = document.createElement("img");
img.src = image_source;
img.width = width;
img.height = height;
img.alt = alt_text;
}
function draw_Ball(bx, by, size, ballColor) {
ctx.beginPath();
ctx.arc(bx, by, size, 0, (Math.PI * 2));
ctx.fillStyle = ballColor;
ctx.fill();
ctx.strokeStyle = "#000000";
ctx.stroke();
ctx.closePath();
}
//This next function was taken from stack overflow
function roundRect(x, y, width, height, radius, stroke, fill, color) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
if (stroke) {
ctx.stroke();
}
if (fill) {
ctx.fill();
}
ctx.closePath();
return;
}
And, for good measure, my HTML and CSS files:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - Portfolio</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body class="background_gradient">
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark dark-bg border-bottom box_shadow mb-0">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">Portfolio</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<!--
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
-->
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Resume">Resume</a>
</li>
<!----
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Art3D">3D Art</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Art2D">2D Art</a>
</li>
<!---->
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Snake">Snake</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="CodeExamples">Code Examples</a>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Ballad">Ballad of the Masked Bandits</a>
</li>
<!--
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="DataBaseHub">Database Hub</a>
</li>
--->
<!--
<li class="nav-item">
<a class="nav-link text-light" asp-area="" asp-controller="Home" asp-action="Unavailable">???</a>
</li>
-->
<!--Temporary Links-->
</ul>
</div>
</div>
</nav>
</header>
<div class="container-fluid" id="MainDiv">
<main role="main" class="pb-0" style="width:100%">
<!--Where the other code goes-->
#{
ViewData["Title"] = "Snake Game";
}
<div class="container-fluid purple_gradient text-center">
<h1>Snake Game</h1>
</div>
<div class="buffer"></div>
<div class="container">
<div class="fancy_text_box">
<div class="container buffer">
<div class="ghostly_text_box text-center">
<h1>By the power of Javascript, here is a playable snake game.</h1>
<div class="buffer"></div>
<h1 id="fiddleText">Give it a moment to load.</h1>
</div>
<div class="buffer"></div>
<div class="ghostly_text_box text-center">
<canvas onload="draw()" class="simple_text_box" id="SnekGamCanvas" width="1000" height="1000"></canvas>
</div>
</div>
</div>
<div class="text-center">
<div class="buffer"></div>
<a class="button glo_button big_r_button big_text" asp-area="" asp-controller="Home" asp-action="Index">Back to Home</a>
<div class="buffer"></div>
</div>
<!--The code be here but if you are reading this you probably already knew that-->
<script src="~/js/Snake.js"></script>
</div>
</main>
</div>
<footer class="border-top footer dark-bg text-light">
<div class="container">
© 2021 - Portfolio - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script src="../jsc3d-master/jsc3d/jsc3d.js"></script>
#RenderSection("Scripts", required: false)
</body>
</html>
...
/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
}
/* Provide sufficient contrast against white background */
a {
color: #0366d6;
}
.btn-primary {
color: #fff;
background-image: linear-gradient(30deg, #b6e2dd, #2a5efe);
border-color: #1861ac;
}
/*Link colors*/
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
/* Sticky footer styles
-------------------------------------------------- */
html {
font-size: 14px;
}
#media (min-width: 768px) {
html {
font-size: 16px;
}
}
.border-top {
border-top: 1px solid #e5e5e5;
}
.border-bottom {
border-bottom: 1px solid #e5e5e5;
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}
button.accept-policy {
font-size: 1rem;
line-height: inherit;
}
/* Sticky footer styles
-------------------------------------------------- */
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 60px;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px; /* Vertically center the text there */
}
/* My Stuff
--------------------------------------------------------------------------
--------------------------------------------------------------------------
--------------------------------------------------------------------------
*/
/*This gives me more control over the exact dark background color*/
.dark-bg
{
background-color: #161631;
}
.purple_gradient
{
/*The image used*/
background-image: linear-gradient(#4b1ac4, #fff);
height:100%;
width:100%;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.test_box_blue
{
/* A container with a solid color and an outline */
background-color: #2d1eb2;
width: 100%;
height: 100%;
margin: 0px;
}
.test_box
{
border:solid #000000;
}
#MainDiv
{
padding:0;
margin:0;
left:0;
top:0;
width:100%;
height:100%;
}
.tundra_backround
{
background-image: url('../images/Tundra_Fixed.png');
width:100%;
height:100%;
}
.white_space_box
{
height:50 px;
}
.background_gradient
{
background-image:linear-gradient(320deg, #fff, #96cbde);
}
.glo_button
{
min-width: 30%;
height: 20%;
border-radius: 25px;
padding: 20px;
margin: 10px;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
transition-duration: 0.4s;
border: 4px solid #000;
}
.big_r_button {
background-color: #a10000;
color: #fff;
}
.big_r_button:hover {
color: #fff;
background-color: #4e0505;
}
.big_b_button {
background-color: #080e9f;
color: #fff;
}
.big_b_button:hover {
color: #fff;
background-color: #161631;
}
.big_g_button {
background-color: #0a7727;
color: #fff;
}
.big_g_button:hover {
color: #fff;
background-color: #07340e;
}
.big_p_button {
background-color: #6f1cbf;
color: #fff;
}
.big_p_button:hover {
color: #fff;
background-color: #2a073e;
}
.buffer
{
padding: 20px;
}
.big_text
{
font-size: 60px;
font-family:'Times New Roman', Times, serif;
text-shadow: 2px 2px rgb(12 14 39 / 0.67);
}
.fancy_text_box{
background-image: linear-gradient(300deg, #ece1c4, #c99e69);
border-radius: 25px;
border: 4px solid #5d3c08;
}
.simple_text_box{
background-color: #fff;
border: 2px solid #000;
}
.ghostly_text_box{
background-color: rgb(255 255 255 / 0.60);
border-radius: 25px;
padding: 10px;
border: 3px solid #000;
}
.thick_border{
border: 4px solid #000;
}
.black_and_white_gradient{
background-image: linear-gradient(310deg, #fff, #000);
}
.red_border{
padding: 0px;
margin: 0px;
border: 4px solid #8f0000;
}
.model_box{
border: 4px solid #000;
background-color: #fff;
border-radius: 25px;
}
.image_box{
border: 4px solid #000;
background-color: #fff;
}
.chain_image_box {
border-top: 4px solid #000;
border-left: 4px solid #000;
border-right: 4px solid #000;
border-bottom: 0px;
background-color: #fff;
}
.margin_setter {
margin: 20px;
padding: 20px;
}
#model_display_1{
}
I apologize for asking such a simple question, but I don't know where to look to find an existing answer.
So, as I suspected, it was a simple syntax error.
Specifically, I wrote "getElementByID" instead of "getElementById". a capitalization error. (I also capitalized "clientX" and "clientY", which also broke stuff.)
I couldn't see it because I was using Visual Studio, and I couldn't find the output for the javascript. By copying the code and pasting it into JS Fiddle, I was able to actually see the errors being generated by the Javascript.
I guess that means that until I find a way to see javascript errors when running HTML code via Visual Studio, I will need to do some debugging via JS Fiddle.
I am writing my own Drag'n'drop functionality for one of my projects and I am running into an issue. All my "draggable" elements are inside a container with display:flex. On mousedown event on one of this elements I set the position to absolute so I would be able to set the left and top properties of the element when I am dragging. Here is what I am doing:
let container = document.querySelector("#big-container")
var dragging = false;
var draggedObject;
let shiftX=0;
let shiftY=0;
document.querySelectorAll(".draggable").forEach((draggable,index) => {
draggable.style.order = index;
draggable.draggable =false;
draggable.ondragstart = ()=>{return false}
draggable.addEventListener("mousedown",ev =>{
draggedObject = draggable;
shiftX = ev.offsetX+5;
shiftY = ev.offsetY+5;
draggable.style.position = "absolute";
draggable.style.left = (ev.clientX - shiftX) + 'px';
draggable.style.top = (ev.clientY - shiftY) + 'px';
dragging = true;
let placeholder = document.createElement("div");
placeholder.id = "placeholder";
placeholder.style.order = draggable.style.order;
container.appendChild(placeholder);
})
})
document.addEventListener("mousemove", ev =>{
if(dragging){
draggedObject.style.left = ev.clientX - shiftX + 'px';
draggedObject.style.top = ev.clientY - shiftY + 'px';
}
})
document.addEventListener("mouseup",ev =>{
if(dragging){
draggedObject.style.position = 'static'
let placeholder = document.querySelector("#placeholder");
container.removeChild(placeholder);
dragging = false
}
})
/* the :not(:last-of-type(div)) is there so the console doesn't get affected */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: black;
}
.draggable {
width: 90px;
height: 120px;
margin: 5px;
}
#placeholder {
width: 90px;
height: 120px;
margin: 5px;
background-color: rgba(0, 0, 0, 0.3);
border: dashed grey 5px;
}
<body draggable="false" ondragstart="return false;">
<div id = "big-container" style ="display: flex; background-color: rgb(76, 104, 95); width: 500px; height: 500px;">
<div style="background-color: rgb(204, 125, 111);" class="draggable"></div>
<div style="background-color: rgb(170, 214, 120);" class="draggable"></div>
<div style="background-color: rgb(129, 212, 167);" class="draggable"></div>
<div style="background-color: rgb(162, 137, 196);" class="draggable"></div>
</div>
</body>
What I am trying to achieve is that on mousedown the element should stay where it was and after that when I move my mouse to move the element as well.(the anchor point should be where I clicked the element)
I am doing shiftX = ev.offsetX+5; because I need to account for the element's margin.
The issue is when I click on a element(and don't move my mouse at all), you can see a little shift in the element's position. It is very minor(maybe 1 or 2px) and is not happening in all places(some zones in the element do not introduce this position shift)
Do you guys have any idea what might be causing it?
You can use getBoundingClientRect() to get the actual position.
let container = document.querySelector("#big-container");
var dragging = false;
var draggedObject;
let shiftX = 0;
let shiftY = 0;
document.querySelectorAll(".draggable").forEach((draggable, index) => {
draggable.style.order = index;
draggable.draggable = false;
draggable.ondragstart = () => {
return false;
};
draggable.addEventListener("mousedown", (ev) => {
draggedObject = draggable;
var x = draggable.getBoundingClientRect().top - 5;
var y = draggable.getBoundingClientRect().left - 5;
shiftX = ev.offsetX + 5;
shiftY = ev.offsetY + 5;
draggable.style.position = "absolute";
draggable.style.left = y + "px";
draggable.style.top = x + "px";
dragging = true;
let placeholder = document.createElement("div");
placeholder.id = "placeholder";
placeholder.style.order = draggable.style.order;
container.appendChild(placeholder);
});
});
document.addEventListener("mousemove", (ev) => {
if (dragging) {
draggedObject.style.left = ev.clientX - shiftX + "px";
draggedObject.style.top = ev.clientY - shiftY + "px";
}
});
document.addEventListener("mouseup", (ev) => {
if (dragging) {
draggedObject.style.position = "static";
let placeholder = document.querySelector("#placeholder");
container.removeChild(placeholder);
dragging = false;
}
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: black;
}
#big-container {
width: 500px;
height: 500px;
}
.draggable {
width: 90px;
height: 120px;
margin: 5px;
}
#placeholder {
width: 90px;
height: 120px;
margin: 5px;
background-color: rgba(0, 0, 0, 0.3);
border: dashed grey 5px;
}
<body draggable="false" ondragstart="return false;">
<div
id="big-container"
style="display: flex; background-color: rgb(76, 104, 95);"
>
<div
style="background-color: rgb(204, 125, 111);"
class="draggable"
></div>
<div
style="background-color: rgb(170, 214, 120);"
class="draggable"
></div>
<div
style="background-color: rgb(129, 212, 167);"
class="draggable"
></div>
<div
style="background-color: rgb(162, 137, 196);"
class="draggable"
></div>
</div>
</body>
Attached is full code of the application.
The problem is that the buttons of the session length section will only change the CLOCK.session properties and the #countdown span if the session length input is changed first. What is strange is that this code worked before I started to do CSS styling to the page, but no it doesn't (and there should't be any connection).
Thank you for the help!`
const canvas = document.querySelector('#timer-circle');
const context = canvas.getContext('2d');
const CLOCK = {
timerInit: function() {
context.beginPath();
context.strokeStyle = "#527A71";
context.lineWidth = 2;
context.arc(120, 120, 118, 0, 2 * Math.PI);
context.stroke();
},
drawStep: function() {
context.beginPath();
context.lineWidth = 4;
context.fillStyle = "#505000";
context.arc(120, 120, 115, Math.PI / 2 - Math.PI * CLOCK.whichSession().timeStep, Math.PI / 2 + Math.PI * CLOCK.whichSession().timeStep);
context.stroke();
context.fill();
document.querySelector('#countdown').innerText = Math.floor(CLOCK.whichSession().timeZero / 60).toString() + ':' + (CLOCK.whichSession().timeZero % 60).toString();
},
initCount: function(total) {
total *= 60
if(CLOCK.sessionSwitch) {
CLOCK.session.timeZero = total;
let localTimeZero = total;
CLOCK.session.timeStep = (total - localTimeZero) / total;
}
else if(!CLOCK.sessionSwitch) {
CLOCK.breakProp.timeZero = total;
let localTimeZero = total;
CLOCK.breakProp.timeStep = (total - localTimeZero) / total;
}
},
clockDisplay: function(total, zero) {
document.querySelector('#countdown').innerText = total.toString() + ':00';
},
timerReset: function() {
context.clearRect(0, 0, canvas.width, canvas.height);
//INITIALIZING FUNCTIONS AND BUTTONS
},
whichSession: function() {
return CLOCK.sessionSwitch ? CLOCK.session : CLOCK.breakProp;
},
timerCount: function() {
if(CLOCK.whichSession().timeStep <= 1) {
CLOCK.drawStep();
CLOCK.whichSession().timeZero--;
CLOCK.whichSession().timeStep = (60 * CLOCK.whichSession().timeTotal - CLOCK.whichSession().timeZero) / (60 * CLOCK.whichSession().timeTotal);
}
else if(CLOCK.whichSession().timeStep >= 1) {
if(CLOCK.sessionSwitch) {
// INITIALIZING BREAK COUNT
CLOCK.sessionSwitch = false;
document.querySelector('#label').innerText = 'Break!';
CLOCK.timerReset();
CLOCK.timerInit();
CLOCK.initCount(CLOCK.breakProp.timeTotal);
}
else if(!CLOCK.sessionSwitch) {
// INITIALIZING SESSION COUNT
CLOCK.sessionSwitch = true;
document.querySelector('#label').innerText = 'Session';
CLOCK.timerReset();
CLOCK.timerInit();
CLOCK.initCount(CLOCK.session.timeTotal);
}
//reset the circle
//switch the countdown to the correct time
CLOCK.drawStep();
CLOCK.whichSession().timeZero--;
CLOCK.whichSession().timeStep = (60 * CLOCK.whichSession().timeTotal - CLOCK.whichSession().timeZero) / (60 * CLOCK.whichSession().timeTotal);
}
},
timerSwitch: false,
sessionSwitch: true,
session: {
timeTotal: undefined,
timeZero: undefined,
timeStep: undefined
},
breakProp: {
timeTotal: undefined,
timeZero: undefined,
timeStep: undefined
},
timerInterval: undefined,
};
$(document).ready(function() {
CLOCK.timerInit()
CLOCK.clockDisplay(document.querySelector('#session-length input').value);
CLOCK.session.timeTotal = Number(document.querySelector('#session-length input').value)
CLOCK.breakProp.timeTotal = Number(document.querySelector('#break-length input').value)
$('button.increase').click(function() {
if($(this)['0'].nextElementSibling.value >= 1 && $(this)['0'].nextElementSibling.value < 99) {
if(this.parentNode.id == 'session-length') {
$(this)['0'].nextElementSibling.value++;
CLOCK.session.timeTotal++;
CLOCK.clockDisplay($(this)[0].nextElementSibling.value);
}
else if(this.parentNode.id = 'break-length') {
$(this)['0'].nextElementSibling.value++;
CLOCK.breakProp.timeTotal++;
}
}
});
$('button.decrease').click(function() {
if($(this)['0'].previousElementSibling.value > 1 && $(this)['0'].previousElementSibling.value <= 99) {
$(this)['0'].previousElementSibling.value--;
if(this.parentNode.id == 'session-length') {
CLOCK.session.timeTotal--;
CLOCK.clockDisplay($(this)[0].previousElementSibling.value);
}
else if(this.parentNode.id = 'break-length') {
CLOCK.breakProp.timeTotal--;
}
}
});
$('input').on('keyup', function() {
if(this.parentNode.id = 'session-length') {
CLOCK.session.timeTotal = Number(this.value);
CLOCK.clockDisplay(this.value);
}
else if(this.parentNode.id = 'break-length') {
CLOCK.breakProp.timeTotal = Number(this.value);
}
});
$('#timer-count').on('click', function() {
if(!CLOCK.timerSwitch) {
CLOCK.initCount(CLOCK.session.timeTotal);
CLOCK.timerInterval = setInterval(CLOCK.timerCount, 1000);
CLOCK.timerSwitch = true;
$('button, input').prop('disabled', true);
}
else if(CLOCK.timerSwitch) {
clearInterval(CLOCK.timerInterval);
CLOCK.timerSwitch = false;
CLOCK.sessionSwitch = true;
CLOCK.clockDisplay(CLOCK.session.timeTotal, )
CLOCK.timerReset();
CLOCK.timerInit();
$('button, input').prop('disabled', false);
}
});
});
body {
background: rgb(0, 0, 0);
background: -moz-linear-gradient(-45deg, rgba(0, 0, 0, 1) 0%, rgba(38, 36, 0, 1) 51%, rgba(81, 66, 0, 1) 100%);
background: -webkit-linear-gradient(-45deg, rgba(0, 0, 0, 1) 0%, rgba(38, 36, 0, 1) 51%, rgba(81, 66, 0, 1) 100%);
background: linear-gradient(135deg, rgba(0, 0, 0, 1) 0%, rgba(38, 36, 0, 1) 51%, rgba(81, 66, 0, 1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#514200', GradientType=1);
background-repeat: no-repeat;
background-attachment: fixed;
color: white;
}
#clock-container {
margin: 100px 20% 0 35%;
color: white;
}
input {
width: 65px;
background-color: transparent;
color: inherit;
border: solid 7px green;
border-radius: 20px;
text-align: center;
font-weight: 700;
font-size: 2em;
}
.input {
display: inline-block;
margin-right: 10%;
}
.clock-form {
display: flex;
padding: 0 5%;
}
.decrease {
margin-left: 0px;
}
#animation {
margin-top: 50px;
margin-left: 7%;
}
#timer-count {
position: absolute;
text-align: center;
width: 240px;
height: 240px;
z-index: 2;
padding: 80px 20px;
font-size: 25px;
font-weight: 600;
}
#timer-circle {
position: absolute;
z-index: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Alon's Pomodoro Clock</title>
<!-- =========JQUERY -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- ==============>BOOTSTRAP -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<!-- ============>FONT -->
<link href="https://fonts.googleapis.com/css?family=Gochi+Hand" rel="stylesheet">
<!-- ================>STYLESHEET -->
<link rel="stylesheet" href="stylesheet.css">
</head>
<body>
<div id="clock-container">
<h1>Alon's Pomodoro Clock</h1>
<div id="session-length" class="input">
<h3>Session Length</h3>
<div class="clock-form">
<button class="increase">+</button>
<input type="text" maxlength="2" value="25" />
<button class="decrease">-</button>
</div>
</div>
<div id="break-length" class="input">
<h3>Break Length</h3>
<div class="clock-form">
<button class="increase">+</button>
<input type="text" maxlength="2" value="5" />
<button class="decrease">-</button>
</div>
</div>
<div id="animation">
<canvas id="timer-circle" width="240" height="240">
</canvas>
<div id="timer-count">
<span id="label">Session</span>
<span id="countdown">01:00</span>
</div>
</div>
</div>
<script src="javascript.js"></script>
</body>
</html>
`
SOLVED!
problem was that I added a div with class .clock-form while editing the css, therefore $(this)['0'].parentNode.id refered to .clock-form instead of either session-input or break-input. though I still haven't figured out why the buttons worked after inserting a value to the inputs manually.
So I'm trying to make simple animation. When you press somewhere inside blue container, a circle should be created in this place and then go up. After some research I found how to put JS values into keyframes, but it's changing values for every object not just for freshly created. If you run snipped and press somewhere high and then somewhere low you will see what I'm talking about.
I found some AWESOME solution with Raphael library, but I'm a beginner and I'm trying to make something like this in JS. Is it even possible? How?
var bubble = {
posX: 0,
posY: 0,
size: 0
};
var aquarium = document.getElementById("container");
var ss = document.styleSheets;
var keyframesRule = [];
function findAnimation(animName) { //function to find keyframes and insert replace values in them
for (var i = 0; i < ss.length; i++) {
for (var j = 0; j < ss[i].cssRules.length; j++) {
if (window.CSSRule.KEYFRAMES_RULE == ss[i].cssRules[j].type && ss[i].cssRules[j].name == animName) {
keyframesRule.push(ss[i].cssRules[j]);
}
}
}
return keyframesRule;
}
function changeAnimation (nameAnim) { //changing top value to cursor position when clicked
var keyframesArr = findAnimation(nameAnim);
for (var i = 0; i < keyframesArr.length; i++) {
keyframesArr[i].deleteRule("0%");
keyframesArr[i].appendRule("0% {top: " + bubble.posY + "px}");
}
}
function createBubble(e) {
"use strict";
bubble.posX = e.clientX;
bubble.posY = e.clientY;
bubble.size = Math.round(Math.random() * 100);
var bubbleCircle = document.createElement("div");
aquarium.appendChild(bubbleCircle);
bubbleCircle.className = "bubble";
var bubbleStyle = bubbleCircle.style;
bubbleStyle.width = bubble.size + "px";
bubbleStyle.height = bubble.size + "px";
bubbleStyle.borderRadius = (bubble.size / 2) + "px";
//bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";
changeAnimation("moveUp");
bubbleCircle.className += " animate";
}
aquarium.addEventListener("click", createBubble);
//console.log(bubble);
body {
background-color: red;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
position: fixed;
top: 80px;
left: 0;
background-color: rgb(20,255,200);
}
#surface {
width: 100%;
height: 40px;
position: fixed;
top: 40px;
opacity: 0.5;
background-color: rgb(250,250,250);
}
.bubble {
position: fixed;
border: 1px solid blue;
}
.animate {
animation: moveUp 5s linear;//cubic-bezier(1, 0, 1, 1);
-webkit-animation: moveUp 5s linear;//cubic-bezier(1, 0, 1, 1);
}
#keyframes moveUp{
0% {
top: 400px;
}
100% {
top: 80px;
}
}
#-webkit-keyframes moveUp{
0% {
top: 400px;
}
100% {
top: 80px;
}
}
<body>
<div id="container">
</div>
<div id="surface">
</div>
</body>
Here is a possible solution. What I did:
Remove your functions changeAnimation () and findAnimation() - we don't need them
Update the keyframe to look like - only take care for the 100%
#keyframes moveUp { 100% {top: 80px;} }
Assign top of the new bubble with the clientY value
After 5 seconds set top of the bubble to the offset of the #container(80px) - exactly when animation is over to keep the position of the bubble, otherwise it will return to initial position
var bubble = {
posX: 0,
posY: 0,
size: 0
};
var aquarium = document.getElementById("container");
function createBubble(e) {
"use strict";
bubble.posX = e.clientX;
bubble.posY = e.clientY;
bubble.size = Math.round(Math.random() * 100);
var bubbleCircle = document.createElement("div");
aquarium.appendChild(bubbleCircle);
bubbleCircle.className = "bubble";
var bubbleStyle = bubbleCircle.style;
bubbleStyle.width = bubble.size + "px";
bubbleStyle.height = bubble.size + "px";
bubbleStyle.borderRadius = (bubble.size / 2) + "px";
bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";
bubbleCircle.className += " animate";
// The following code will take care to reset top to the top
// offset of #container which is 80px, otherwise circle will return to
// the position of which it was created
(function(style) {
setTimeout(function() {
style.top = '80px';
}, 5000);
})(bubbleStyle);
}
aquarium.addEventListener("click", createBubble);
body {
background-color: red;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
position: fixed;
top: 80px;
left: 0;
background-color: rgb(20, 255, 200);
}
#surface {
width: 100%;
height: 40px;
position: fixed;
top: 40px;
opacity: 0.5;
background-color: rgb(250, 250, 250);
}
.bubble {
position: fixed;
border: 1px solid blue;
}
.animate {
animation: moveUp 5s linear;
/*cubic-bezier(1, 0, 1, 1);*/
-webkit-animation: moveUp 5s linear;
/*cubic-bezier(1, 0, 1, 1);*/
}
#keyframes moveUp {
100% {
top: 80px;
}
}
#-webkit-keyframes moveUp {
100% {
top: 80px;
}
}
<body>
<div id="container"></div>
<div id="surface"></div>
</body>
The problem about your code was that it is globally changing the #keyframes moveUp which is causing all the bubbles to move.
The problem with your code is that you're updating keyframes which are applied to all bubbles. I tried another way of doing it by using transition and changing the top position after the element was added to the DOM (otherwise it wouldn't be animated).
The main problem here is to wait the element to be added to the DOM. I tried using MutationObserver but it seems to be called before the element is actually added to the DOM (or at least rendered). So the only way I found is using a timeout which will simulate this waiting, although there must be a better one (because it may be called too early, causing the bubble to directly stick to the top), which I would be happy to hear about.
var bubble = {
posX: 0,
posY: 0,
size: 0
};
var aquarium = document.getElementById("container");
function createBubble(e) {
"use strict";
bubble.posX = e.clientX;
bubble.posY = e.clientY;
bubble.size = Math.round(Math.random() * 100);
var bubbleCircle = document.createElement("div");
aquarium.appendChild(bubbleCircle);
bubbleCircle.classList.add("bubble");
var bubbleStyle = bubbleCircle.style;
bubbleStyle.width = bubble.size + "px";
bubbleStyle.height = bubble.size + "px";
bubbleStyle.borderRadius = (bubble.size / 2) + "px";
bubbleStyle.top = bubble.posY - (bubble.size / 2) + "px";
bubbleStyle.left = bubble.posX - (bubble.size / 2) + "px";
setTimeout(function() {
bubbleCircle.classList.add("moveUp");
}, 50);
}
aquarium.addEventListener("click", createBubble);
body {
background-color: red;
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100%;
position: fixed;
top: 80px;
left: 0;
background-color: rgb(20, 255, 200);
}
#surface {
width: 100%;
height: 40px;
position: fixed;
top: 40px;
opacity: 0.5;
background-color: rgb(250, 250, 250);
}
.bubble {
position: fixed;
border: 1px solid blue;
transition: 5s;
}
.moveUp {
top: 80px !important;
}
<body>
<div id="container">
</div>
<div id="surface">
</div>
</body>
Also, I used the classList object instead of className += ... because it is more reliable.
I'm practicing my Javascript, so i made a follow-mouse function. I got it working, but now i have a new idea, which i'm not sure is possible.
Is there a way, to make a '' orb of vision '' follow the mouse, so that everything in that area gets visible?. Kind of like using a torch, to see a small area where your mouse is.
NOTE : I'm not asking for someone to code it for me, but rather a explanation, since i'm curious to learn it myself, but i do need a guide-line!**
function mouseMovement(e) {
var x = document.getElementById('x_show');
var y = document.getElementById('y_show');
x.innerHTML = e.clientX;
y.innerHTML = e.clientY;
document.getElementById("followDiv").style.left = event.clientX - 15 + "px";
document.getElementById("followDiv").style.top = event.clientY - 15 + "px";
}
document.onmousemove = mouseMovement;
#followDiv {
background-color: lightblue;
height: 30px;
width: 30px;
position: absolute;
}
<p id="x_show">0</p>
<p id="y_show">0</p>
<div id="followDiv"></div>
A non-canvas way would be :
Set page background to black
Round the borders of #followDiv using 'border-radius: 50%;'
Set the background of this div to image
Play with the background-position to move opposite to mouse
Edit:
A final touch by softening the edges using box-shadow
function mouseMovement(e) {
var x = document.getElementById('x_show');
var y = document.getElementById('y_show');
x.innerHTML = e.clientX;
y.innerHTML = e.clientY;
var followDiv = document.getElementById("followDiv");
followDiv.style.left = event.clientX - 60 + "px";
followDiv.style.top = event.clientY - 60 + "px";
followDiv.style.backgroundPositionX = (-event.clientX) + 'px';
followDiv.style.backgroundPositionY = (-event.clientY) + 'px';
}
document.onmousemove = mouseMovement;
body {
background: black;
}
#followDiv {
background-color: lightblue;
height: 120px;
width: 120px;
position: absolute;
border-radius: 50%;
box-shadow: 0 0 12px 12px black inset, /* workaround for a soft edge issue :
http://stackoverflow.com/a/37460870/5483521
*/
0 0 2px 2px black inset, 0 0 2px 2px black inset, 0 0 2px 2px black inset;
background: url(https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg) no-repeat;
}
<p id="x_show">0</p>
<p id="y_show">0</p>
<div id="followDiv"></div>
#Bulent Vural, this was my solution. But i can't get the circle ' smaller ' since i have to re-size it to fit the screen, which won't work with %'s.
The only way this works, is adding alot of " black, black, black ". Which isn't very pleasing.
function mouseMovement(e)
{
var x = document.getElementById('x_show');
var y = document.getElementById('y_show');
x.innerHTML = e.clientX;
y.innerHTML = e.clientY;
document.getElementById("followDiv").style.left = event.clientX-2000+"px";
document.getElementById("followDiv").style.top = event.clientY-2000+"px";
}
document.onmousemove = mouseMovement;
</script>
html, body {margin: 0; height: 100%; overflow: hidden}
#followDiv {
/* background-color: lightblue; */
height: 4000px;
width: 4000px;
position: absolute;
background: -webkit-radial-gradient(circle, rgba(248, 255, 252, 0),black);
background: -o-radial-gradient(circle, rgba(248, 255, 252, 0),black);
background: -moz-radial-gradient(circle, rgba(248, 255, 252, 0),black);
background: radial-gradient(circle, rgba(248, 255, 252, 0),black);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p id="x_show">0</p>
<p id="y_show">0</p>
<div id="followDiv"></div>
</body>
i think this could help you what you want.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
$("#canvas").mousemove(function(e){handleMouseMove(e);});
var radius=30;
var img=new Image();
img.onload=function(){
draw(150,150,30);
}
img.src='https://dl.dropboxusercontent.com/u/139992952/multple/annotateMe.jpg'
function draw(cx,cy,radius){
ctx.save();
ctx.clearRect(0,0,cw,ch);
var radialGradient = ctx.createRadialGradient(cx, cy, 1, cx, cy, radius);
radialGradient.addColorStop(0, 'rgba(0,0,0,1)');
radialGradient.addColorStop(.65, 'rgba(0,0,0,1)');
radialGradient.addColorStop(1, 'rgba(0,0,0,0)');
ctx.beginPath();
ctx.arc(cx,cy,radius,0,Math.PI*2);
ctx.fillStyle=radialGradient;
ctx.fill();
ctx.globalCompositeOperation='source-atop';
ctx.drawImage(img,0,0);
ctx.globalCompositeOperation='destination-over';
ctx.fillStyle='black';
ctx.fillRect(0,0,cw,ch);
ctx.restore();
}
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
draw(mouseX,mouseY,30);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Move mouse to reveal image with "flashlight"</h4>
<canvas id="canvas" width=300 height=300></canvas>