Background zooms in incorrectly when following mouse movement - javascript

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>

Related

How to increase width and height on click of a button

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>

Use an image as a mask for another image

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

Text content disappears in div as scrolling

I am trying to expand a child element to the very top of its parent with the following code. However, the text disappears after a while of scrolling downward in the child element. How do I fix this?
function setHeight() {
var panel = document.getElementById("panel");
var container = document.getElementById("container");
var panelHeight = container.offsetHeight;
var y = panel.scrollTop;
// YOU MUST SET THE PERCENTAGE, OR A MAX HEIGHT
maxHeight = panelHeight * 0.9;
var targetHeight = Math.min(maxHeight, 0.7 * panelHeight + y);
panel.style.height = targetHeight + "px";
document.getElementById("panelContent").style.marginTop = Math.min(y, panelHeight - maxHeight) + "px";
}
document.getElementById('panel').addEventListener("scroll", setHeight);
#container {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: red;
}
#panel {
position: fixed;
width: 100%;
height: 70%;
bottom: 0;
background-color: green;
overflow-y: scroll;
}
<div id="container">
Scroll up to here
<div id="panel">
<div id="panelContent">
As user scroll downs here in this div, expand this div to the top but only as much as the user has scrolled down: asdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasda<br>sdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasda<br>sdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasda<br>sdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasd<br>sdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasda<br>sdasdasdasdasdasdasdasdasdasdasdasdassdasdasdasdasdasd
</div>
</div>
</div>
https://jsfiddle.net/1ekpx3sd/

Slider handle needs to restricted inside the container, should not go beyond the container

In the custom slider i have created, the handle is moving beyond the container. But i want it to stay within the container limits. We could just do it simple by setting margin-left as offset in CSS. But My requirement is when the handle right end detect the container's end the handle should not be allowed to move anymore. Any help is appreciated. Thanks.
Demo Link: https://jsfiddle.net/mohanravi/1pbzdyyd/30/
document.getElementsByClassName('contain')[0].addEventListener("mousedown", downHandle);
function downHandle() {
document.addEventListener("mousemove", moveHandle);
document.addEventListener("mouseup", upHandle);
}
function moveHandle(e) {
var left = e.clientX - document.getElementsByClassName('contain')[0].getBoundingClientRect().left;
var num = document.getElementsByClassName('contain')[0].offsetWidth / 100;
var val = (left / num);
if (val < 0) {
val = 0;
} else if (val > 100) {
val = 100;
}
var pos = document.getElementsByClassName('contain')[0].getBoundingClientRect().width * (val / 100);
document.getElementsByClassName('bar')[0].style.left = pos + 'px';
}
function upHandle() {
document.removeEventListener("mousemove", moveHandle);
document.removeEventListener("mouseup", upHandle);
}
.contain {
height: 4px;
width: 450px;
background: grey;
position: relative;
top: 50px;
left: 40px;
}
.bar {
width: 90px;
height: 12px;
background: transparent;
border: 1px solid red;
position: absolute;
top: calc(50% - 7px);
left: 0px;
cursor: ew-resize;
}
<div class='contain'>
<div class='bar'></div>
</div>
You need to change
this
document.getElementsByClassName('bar')[0].style.left = pos + 'px';
to this
if(pos > 90){
document.getElementsByClassName('bar')[0].style.left = pos - 90 + 'px';
}
else{
document.getElementsByClassName('bar')[0].style.left = 0 + 'px';
}
since width of your bar is 90px I am subtracting 90.
See this updated fiddle

Image angle changes depending position of mouse

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)"})
})
});

Categories

Resources