Im trying to build a game where enemies jump out of the water and you fire water at them...
When the user clicks to fire I want the img src to point in the direction of the click, to achieve what I have so far I have css and js script (code below) however it looks to static, I feel having the water point in the direction of the users input would help a lot however Im not sure how to achieve this?
//bind to gun events
this.playfield.on('gun:out_of_ammo',_.bind(function(){this.outOfAmmo();},this));
this.playfield.on('gun:fire',_.bind(function(){
this.flashScreen();
},this));
...
flashScreen : function(){
$(".theFlash").css("display","block");
setTimeout(function(){
$('.theFlash').css("display","none");
},400);
}
CSS
.theFlash{
background-color : transparent;
width:900px;
height:500px;
position:relative;
margin:0 auto;
z-index:10;
display:none;
}
I put together an example below that will hopefully help you out.
You just have to specify the source from where the shoot is fired (sourceX,sourceY), calculate the angle to where the mouse is clicked (done below, so should just be to copy/paste) and adjust the transform: rotate(Xdeg); to the new angle.
Make sure to set the orgin in css with transform-origin, so that the flame rotates around the source and not the flame itself.
Try it out at the bottom.
var game,
flame,
sourceX = 310,
sourceY = 110;
window.onload = function() {
game = document.getElementById('game');
flame = document.getElementById('flame');
game.addEventListener('click', function(e) {
var targetX = e.pageX,
targetY = e.pageY,
deltaX = targetX - sourceX,
deltaY = targetY - sourceY,
rad = Math.atan2(deltaY, deltaX),
deg = rad * (180 / Math.PI),
length = Math.sqrt(deltaX*deltaX+deltaY*deltaY);
fire(deg,length);
}, false);
};
function fire(deg,length) {
flame.style.opacity = 1;
flame.style.transform = 'rotate(' + deg + 'deg)'
flame.style.width = length + 'px';
setTimeout(function() {
flame.style.opacity = 0;
},300);
};
#game {
position: relative;
width: 400px;
height: 200px;
background-color: #666;
overflow: hidden;
}
#source {
border-radius: 50%;
z-index: 101;
width: 20px;
height: 20px;
background-color: #ff0000;
position: absolute;
left: 300px;
top: 100px;
}
#flame {
width: 300px;
height: 3px;
background-color: #00ff00;
position: absolute;
left: 310px;
top: 110px;
opacity: 0;
transform-origin: 0px 0px;
transform: rotate(180deg);
transition: opacity .2s;
}
<div id="game">
<div id="source">
</div>
<div id="flame">
</div>
</div>
I would not recommend building games in this manner, Canvas and SVG are the preferred methods of building browser games, with that said it can be done.
Try this
https://jsfiddle.net/b77x4rq4/
$(document).ready(function(){
var middleOfElementTop = 250; // margin from top + half of height
var middleOfElementLeft = 125; // margin from left + half of width
$("#main").mousemove(function(e){
var mouseX = e.offsetX;
var mouseY = e.offsetY;
var angle = Math.atan2(mouseY - middleOfElementTop, mouseX - middleOfElementLeft) * 180 / Math.PI;
$(".box").css({"transform": "rotate(" + angle + "deg)"})
})
});
Related
I have been trying to make an application like open-board. For that, I am using canvas API. The problem is that the lines are drawn below the clicked point. I have already subtracted offset top and offset left but still facing the issue.
Also, one thing that I have noticed, the distance between the clicked point and the drawn figure increases as the clicked point goes farther away from the origin. Like this: image
here is my code:
canvas.addEventListener("mousedown",(e)=>{
let x = drawArea.offsetTop
let y = drawArea.offsetLeft
if(lineToolSelected == false)
{
lineToolSelected = true;
tool.beginPath()
tool.moveTo(e.clientX-y,e.clientY-x)
}else if( lineToolSelected == true){
lineToolSelected = false
tool.lineTo(e.clientX-y,e.clientY-x)
tool.stroke()
}
})
.draw-area{
/* position: fixed; */
position: absolute;
top:0rem;
left:0rem;
height: 175px;
width: 350px;
background:white;
}
.draw-area-cont{
/* position: fixed; */
position: absolute;
top:10rem;
left:2rem;
width:74rem;
background:#eeeded;
height: 37rem;
overflow: hidden;
/* z-index:1; */
}
#canvas{
/* position: fixed; */
height: 100%;
background-color: white;
width: 100%;
color: white;
}
<div class="draw-area-cont">
<div class="draw-area">
<canvas id="canvas"></canvas>
</div>
</div>
If anyone encounters the same problem, I did this:
var scale = 2;
canvas.height = canvas.offsetHeight * scale;
canvas.width = canvas.offsetwidth * scale;
I don't think you even need to multiply with scale, just doing this should work too:
canvas.height = canvas.offsetHeight;
canvas.width = canvas.offsetwidth;
I multiplied with scale to increase the resolution of the image.
I need to increase height actually to increase bottom and top of div each for 25px also left and right side each for 25px.I don't now is that even possible.
So this is just example but it is similar to my code:
function increaseDiv() {
var myDiv = document.querySelector(".box")
var currWidth = myDiv.clientWidth;
myDiv.style.width = currWidth + 100 + "px";
}
.box {
width: 300px;
height: 200px;
position: absolute;
left: 100px;
background: black;
}
<div class="box"></div>
<button onclick="increaseDiv()">Click</button>
Here is demo https://jsfiddle.net/SutonJ/0pdwm39a/14/
The problem is that position of your div are related to left side and this is why it looks like you increase only the right side; try to add positioning with transform by center or make it by flex(align-items + justify-content)
.box {
width: 300px;
height: 200px;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
background: black;
}
If I am understanding you correctly, I think if you changed
var currWidth = myDiv.clientWidth;
myDiv.style.width = currWidth + 100 + "px";
to
var currWidth = myDiv.getBoundingClientRect().width;
myDiv.style.width = currWidth + 50 + "px";
and also added
var currHeight = myDiv.getBoundingClientRect().height;
myDiv.style.height = currHeight + 50 + "px";
I also noticed that your div is using absolute positioning, so you may also need to offset the left and top according to the size change. If you are getting an issue with the actual position when the size changes let me know.
What about CSS scale?
That will keep the actual position of the element and expand it in all directions, unless you specify a transform-origin value.
Edited with an ever growing effect...
let myDiv = document.querySelector(".box");
let orgiSize = myDiv.getBoundingClientRect().width;
let increments = 0;
function increaseDiv() {
increments += 50; // That is 25px on both sides...
// Make the math here
var percentage = Math.floor((orgiSize + increments) / orgiSize * 100) / 100
console.log(percentage);
myDiv.style.transform = `scale(${percentage})`; // That is a percentage value
}
.box {
width: 300px;
height: 200px;
position: absolute;
left: 100px;
background: black;
}
/* for the demo */
button {
position: absolute;
z-index: 9999;
}
<div class="box"></div>
<button onclick="increaseDiv()">Click</button>
function drawAll() {
// Upper zone, 8 grey transparent buttons
let canvas0 = document.getElementById("layer0");
canvas0.width = 1000;
canvas0.height = 100;
let bandeau = canvas0.getContext("2d");
bandeau.fillStyle = "rgba(128,128,80,0.3)";
for (var i = 0; i < 8; i++) {
bandeau.beginPath;
bandeau.arc(50 + 110 * i, 50, 45, 0, 2 * Math.PI);
bandeau.fill();
}
// Lower zone, a red rectangle partially under the buttons
let canvas1 = document.getElementById("layer1");
canvas1.width = 1000;
canvas1.height = 1000;
let dessin = canvas1.getContext("2d");
dessin.fillStyle = "red";
dessin.fillRect(30, 50, 800, 200);
canvas0.style.visibility = "visible";
canvas1.style.visibility = "visible";
}
drawAll()
body {
background-color: rgb(249, 249, 250);
}
.container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
z-index: -10;
}
.scrollable {
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
}
.fixed {
position: absolute;
top: 0px;
left: 0px;
z-index: 2;
}
<div class="container">
<canvas id="layer0" class="scrollable"></canvas>
<canvas id="layer1" class="fixed"></canvas>
</div>
Hello
I'm stuck on a superposition problem of two canvas. Here is a simplified example. Note that in the real application, buttons and drawings are far more complicated and that I want to keep the structure with html5 / css / javascript.
I suppose that I miss something in the css to succeed to have these two canvas superposed, buttons partially covering the red rectangle, but what ?
Thanks if somebody can help.
The problem is that <body> doesn't have any height, which makes the .container height of 100% equally zero.
Absolutely positioned elements do no contribute to their parent's height. As soon as you start giving .container an actual height, you can see its content. In the example below, I went for 100vw and 100vh for width and height, but since your canvases are 1000px wide, you could also use that or any other value.
An absolutely positioned element no longer exists in the normal document layout flow. Instead, it sits on its own layer separate from everything else.
Source: MDN Web Docs
The other option is to remove overflow: hidden; from .container and show everything outside of it.
function drawAll() {
// Upper zone, 8 grey transparent buttons
let canvas0 = document.getElementById("layer0");
canvas0.width = 1000;
canvas0.height = 100;
let bandeau = canvas0.getContext("2d");
bandeau.fillStyle = "rgba(128,128,80,0.3)";
for (var i = 0; i < 8; i++) {
bandeau.beginPath;
bandeau.arc(50 + 110 * i, 50, 45, 0, 2 * Math.PI);
bandeau.fill();
}
// Lower zone, a red rectangle partially under the buttons
let canvas1 = document.getElementById("layer1");
canvas1.width = 1000;
canvas1.height = 1000;
let dessin = canvas1.getContext("2d");
dessin.fillStyle = "red";
dessin.fillRect(30, 50, 800, 200);
canvas0.style.visibility = "visible";
canvas1.style.visibility = "visible";
}
drawAll()
body {
background-color: rgb(249, 249, 250);
}
.container {
position: relative;
overflow: hidden;
z-index: -10;
height: 100vh;
width: 100vw;
}
.scrollable {
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
}
.fixed {
position: absolute;
top: 0px;
left: 0px;
z-index: 2;
}
<div class="container">
<canvas id="layer0" class="scrollable"></canvas>
<canvas id="layer1" class="fixed"></canvas>
</div>
I'm making a website that I wanted to be a white page that you could stamp to make another image appear under. So when you click, you make a holepunch.
Like this exemple :
So I managed to have a randomized image in the background as I click which is fine for what I want, and to be able to .append() the holepunches.
But I don't know how to do the mask thing I've been digging online for a few things and help, and managed to make it work in certain cases but not that one...
It should be like that (I guess) :
image in the background
white shape in front
the star shape is making a holepunch in the white shape
For now, the only thing I managed to do is to have the picture besides a bigger holepunch (which is my original img) but when I click it doesn't make any holepunch, it justs add the stamp.
Here is the code :
var images = ["https://icatcare.org/app/uploads/2018/07/Thinking-of-getting-a-cat.png", "https://ichef.bbci.co.uk/news/1024/cpsprodpb/151AB/production/_111434468_gettyimages-1143489763.jpg"];
$(document.body).click(function(c) {
var tw = 100 / 2;
var th = 30 / 2;
var x = Math.floor((Math.random() * images.length));
document.getElementById('random').src = images[x];
$("#random").css({
position: 'absolute',
display: "block",
left: 0,
top: 0
});
var tw = 50 / 2;
var th = tw;
$('#holepunch:last').clone().appendTo(this).css({
position: 'absolute',
display: "block",
left: c.pageX - tw - $(this).position().left,
top: c.pageY - th + $(this).scrollTop()
});
});
body{
background: lightgrey;
width: 100vw;
height: 100vh;
z-index: 1;
opacity: 1;
}
.fauxbody{
z-index: 100;
position: fixed;
width: 100vw;
height: 100vh;
background-color: white;
top: 0;
left: 0;
-webkit-mask:
-moz-element(#holepunch) 1vw 1vh no-repeat,
linear-gradient(#fff 0 0);
mask-composite:exclude;
}
#random{
z-index: -100;
width: 100vw;
height: auto;
}
#holepunch{
width: 50px;
height: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<img id="random">
<div class ="fauxbody">
<img id="holepunch" src="https://oshi.at/iimtXg/Jqtz.png">
</div>
</body>
Here is an idea using multiple mask and CSS variables. The trick is to add an extra layer on each click. I removed the code related to background generation since it's irrelevant and quite easy to be added
var mask = "";
w = 60;
h = 60;
document.documentElement.addEventListener("click", function (c) {
mask+="url(https://i.ibb.co/FzmCjLL/Jqtz.png)"+(c.pageX-w/2)+"px "+(c.pageY-h/2)+"px/"+w+"px "+h+"px no-repeat,";
document.documentElement.style.setProperty("--mask", mask)
});
html {
background:url(https://picsum.photos/800/800) center/cover;
}
html::before {
content:"";
position: fixed;
background-color: #f3f3f3;
inset: 0;
-webkit-mask:
var(--mask)
linear-gradient(#fff 0 0);
-webkit-mask-reepat: no-repeat;
-webkit-mask-composite: destination-out;
mask-composite: exclude;
}
Also like below without mask-composite:
var mask = "";
w = 60;
h = 60;
document.documentElement.addEventListener("click", function(c) {
if (mask != "")
mask += ",";
mask += "url(https://i.ibb.co/FzmCjLL/Jqtz.png)" + (c.pageX - w / 2) + "px " + (c.pageY - h / 2) + "px/" + w + "px " + h + "px no-repeat";
document.documentElement.style.setProperty("--mask", mask)
});
html::before {
content: "";
position: fixed;
background: url(https://picsum.photos/800/800) center/cover;
inset: 0;
-webkit-mask: var(--mask, linear-gradient(#0000 0 0));
}
I would try to use canvas with white background and add a mouseclick event listener, which cuts out the canvas. I found another question on stack overflow what may can help you:
HTML5 Cut out circle from previous drawn strokes
I've created a button, when you hover over it a div with a background image enlarges. The background should follow the cursor's movements. Meaning that the background image follows your cursor as you hover over the button.
When I hover over the bottom right part of the button, the image will zoom in to the top left before moving to the cursor's location. Check out the example below to see what I mean. I'd like to make it zoom directly to the cursor's location, any ideas?
var imgZoomIn = 1.2; //% of how much the image will enlarge
function buttonImgResize(x, e){
//Location of the cursor (as percentage of the container's size)
var imgContPosition = x.getBoundingClientRect();
var mousePosX = (e.clientX - imgContPosition.left) / x.offsetWidth;
var mousePosY = (e.clientY - imgContPosition.top) / x.offsetHeight;
//Finding how far to move the image from top and left
var leftImgOverlap = x.offsetWidth * (imgZoomIn - 1) * mousePosX;
var topImgOverlap = x.offsetHeight * (imgZoomIn - 1) * mousePosY;
//implementing changes
x.firstElementChild.style.left = 0 - leftImgOverlap + "px";
x.firstElementChild.style.top = 0 - topImgOverlap + "px";
}
//Reseting values
function buttonImgDownsize(x){
x.firstElementChild.style.left = "0";
x.firstElementChild.style.top = "0";
}
/*Container*/
.showCaseBtn{
overflow: hidden;
position: relative;
width: 500px; height: 300px;
}
/*div with background image*/
.showcaseBtn_Back{
position: absolute; top: 0; left: 0;
width: 100%; height: 100%;
background: black no-repeat center center / cover;
transition: 0.4s;
}
.showCaseBtn:hover .showcaseBtn_Back{
height: 120%; width: 120%;
}
<div class="showCaseBtn" onmousemove="buttonImgResize(this, event)" onmouseout="buttonImgDownsize(this)">
<div class="showcaseBtn_Back" style="background-image: url(https://media.contentapi.ea.com/content/dam/need-for-speed/common/2017/10/nfs-payback-jaguar-f-type-2x.jpg.adapt.1920w.jpg);"></div>
</div>
The problem is caused by the css transition. If you remove it, the zooming works but no fancy scaling will happen.
var imgZoomIn = 1.2;
function buttonImgResize(x, e){
var imgContPosition = x.getBoundingClientRect();
var mousePosX = (e.clientX - imgContPosition.left) / imgContPosition.width;
var mousePosY = (e.clientY - imgContPosition.top) / imgContPosition.height;
var leftImgOverlap = imgContPosition.width * (imgZoomIn - 1) * mousePosX;
var topImgOverlap = imgContPosition.height * (imgZoomIn - 1) * mousePosY;
x.firstElementChild.style.left = - leftImgOverlap + "px";
x.firstElementChild.style.top = - topImgOverlap + "px";
}
function buttonImgDownsize(x){
x.firstElementChild.style.left = "0";
x.firstElementChild.style.top = "0";
}
.showCaseBtn{
overflow: hidden;
position: relative;
width: 500px; height: 300px;
}
.showcaseBtn_Back{
position: absolute; top: 0; left: 0;
width: 100%; height: 100%;
background: black no-repeat center center / cover;
}
.showCaseBtn:hover .showcaseBtn_Back{
height: 120%; width: 120%;
}
<div class="showCaseBtn" onmousemove="buttonImgResize(this, event)" onmouseout="buttonImgDownsize(this)">
<div class="showcaseBtn_Back" style="background-image: url(https://media.contentapi.ea.com/content/dam/need-for-speed/common/2017/10/nfs-payback-jaguar-f-type-2x.jpg.adapt.1920w.jpg);"></div>
</div>