Image clip centre - javascript

I want my image to be clipped in the centre and be able to move around left right up down while being on cover to fit the whole screen
The user should be able to see only a certain portion of the image and be able to move around just like the link below but his viewpoint is the little rectangle in a fit to screen perspective
What i get so far is just the clipped upleft of my image
In case i am not clear what I am trying to achieve this effect but the user can't see move than the square
https://www.w3schools.com/howto/howto_js_image_zoom.asp
I will soon close this ticket if you happen to stumble on this check out this q I believe I am as as clear as I can here
How to clip your image freely
<style>
img {
background-position: cover;
position: absolute;
clip:rect(0px,500px,500px,0px);
}
.image1 {
background: url(images/bg.jpg) no-repeat center center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
</style>
</head>
<body>
<div class='clipper-div'>
<img class='image1' src='office.gif'/>
</div>

The kind you were looking for is an inset clipping:
clip-path: inset(top bottom left right);
You can listen to the mouse move event to update the clipping. In the example below, I used CSS custom properties I added to the clipper-element style definition.
These custom properties are used as CSS variables for the clipping definition.
// Globals variables (we could store them into an object,
// which would be a cleaner way
var clipperDiv = document.getElementById("clipper-div");
var hoveringClippedImg = document.getElementById("hovering-clipped");
var imgBoundingRect = hoveringClippedImg.getBoundingClientRect();
var clippingSize = 40;
// Surrouding DIV element mouse move event callback
clipperDiv.onmousemove = clipHoveredArea;
// Update image clipping
function clipHoveredArea(e) {
// First step: getting clipping coordinates from mouse position
var pos = getMousePos(e);
var top = (pos.y - clippingSize / 2);
var bottom = (imgBoundingRect.height - pos.y - (clippingSize / 2));
var left = (pos.x - clippingSize / 2);
var right = (imgBoundingRect.width - pos.x - clippingSize / 2);
// Second step: CSS custom properties
hoveringClippedImg.style.setProperty("--top", top + "px");
hoveringClippedImg.style.setProperty("--bottom", bottom + "px");
hoveringClippedImg.style.setProperty("--left", left + "px");
hoveringClippedImg.style.setProperty("--right", right + "px");
};
// Get mouse position relative to an element
// Source: //stackoverflow.com/a/42111623/4375327
function getMousePos(e) {
// e = Mouse click event.
var rect = e.currentTarget.getBoundingClientRect();
var x = e.clientX - Math.round(rect.left);
var y = e.clientY - Math.round(rect.top);
return {
x: x,
y: y
};
}
#clipper-div {
border: 2px solid black;
width: 200px;
height: 200px;
}
#hovering-clipped {
padding: 0;
margin: 0;
width: 200px;
height: 200px;
clip-path: inset(var(--top) var(--right) var(--bottom) var(--left));
--top: 0px;
--right: 0px;
--bottom: 0px;
--left: 0px;
cursor: crosshair;
}
<div id='clipper-div'>
<img id="hovering-clipped"
src="//placehold.it/200x200/d0d8f8/000000" />
</div>
Note: I used Clippy. It's a handy tool to design the clipping you want.

Related

CSS-HTML: Put an image above another one with html and css

I'm very newbie to webdev, but I need to draft a landingpage with some trick effects.
I need to put a "stencil image" (png with transp) over a moving (mouse hover) background.
Basically, I managed to do that, but I having a big issue: If I resize browser, the background shows behind first plane image, (because I can't rezise background to browser size).
So, the main codes are:
html code:
<div id="bkg-image" class="blur"></div>
<div>
<img src="./imgs/stencil.png" class="firstPlane" />
</div>
CSS code:
#bkg-image {
background: url('./imgs/background.jpg') no-repeat center center fixed;
position: absolute;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
width: 75%;
height: 75%;
z-index: 0;
-webkit-filter: brightness(1.7);
}
.firstPlane {
display: block;
position: absolute;
top: 0px;
left: 0px;
max-width: 100%;
height: auto;
width: auto;
z-index: 2;
}
JS code:
$(document).ready(function() {
var movementStrength = 75;
var height = movementStrength / $(window).height();
var width = movementStrength / $(window).width();
$(".firstPlane").mousemove(function(e) {
var pageX = e.pageX - ($(window).width() / 2);
var pageY = e.pageY - ($(window).height() / 2);
var newvalueX = width * pageX * -1;
var newvalueY = height * pageY * -1;
$('#bkg-image').css("background-position", newvalueX + "px " + newvalueY + "px");
});
});
Any idea how to crop the excess background or how to rescale it to fit behind firstplane image?
note: blur class is just for an animated blur effect, not relevant to this.
I took the java script from a net tutorial.
My first aproach was using webkit mask-image, but seens it don't works, now I'm trying this method.
Thanks a lot for any help
You are doing it upside down. This is how it should be.
$(document).ready(function() {
$("#bkg-image").mousemove(function(e) {
$('.firstPlane').css({left: e.pageX + "px", top: e.pageY + "px"});
});
});
I need invert the selection: I need read the mouse position on first plane and apply movement to the bkg image. (your script only works if I switch #bkg-image and .firstPlane). My issue isn't read the movement, but crop bkg-image to not show it bellow 1st plane when I have a small and tall browser window.
The solution would be a mask/clip image, but its not working for svg graphics or PNG for me, so I give up and tried with a big black PNG with transp on it to show background.
Something like this: (https://codepen.io/caraujo/pen/rVOZKJ) but with a logo (vector or png), but mask/image clip is not working for me :/

Why element getBoundingClientRect() values condition is not working properly?

I have .square element when I move my mouse it should be moved with the mouse. Almost everything is good when I move my mouse normally but when I move my mouse fastly on the right and bottom side, Then the .square box goes to the down or right side and makes the scrollbar.
How can I make my code better than now OR How to fix the problem?
[NOTE]: Transition should have
let square = document.querySelector(".square");
document.addEventListener("mousemove", function (e) {
if (square !== null) {
let x = e.pageX;
let y = e.pageY;
square.setAttribute("style", `top: ${y}px; left: ${x}px`);
let getBottom = square.getBoundingClientRect().bottom;
let getRight = square.getBoundingClientRect().right;
if (getBottom > window.innerHeight) {
square.setAttribute("style", `bottom: 0; left: ${x}px`);
}
if (getRight > window.innerWidth) {
square.setAttribute("style", `top: ${y}px; right: 0`);
}
if (getRight > window.innerWidth && getBottom > window.innerHeight) {
square.setAttribute("style", `bottom: 0; right: 0`);
}
}
});
*,
*::before,
*::after{
box-sizing: border-box;
}
body{
margin: 0;
border: 1px solid blue;
}
.square {
position: absolute;
height: 50px;
width: 50px;
border: 5px solid red;
transition: .01s ease-in-out;
}
<div class="square"></div>
The problem is caused by defining a transition on the square element's position in CSS, combined with setting the position of the square before reading its current position:
Setting the position immediately to the mouse move position:
square.setAttribute("style", `top: ${y}px; left: ${x}px`);
can move the square out of the viewport and create scroll bars if the mouse is less than the length of the square's side away from the bottom or right of the browser window.
Reading the position of the square next:
let getBottom = square.getBoundingClientRect().bottom;
let getRight = square.getBoundingClientRect().right;
returns the updated position of the square if there is no transition, but with the transition returns where the square is now, before the transition starts. Since the square is not outside the window yet, none of the conditional statements using its old position detect that it will end up outside the window.
The easiest solution is to remove the CSS transition - keeping it at 0.01 second is less than monitor update refresh time and not particularly useful.
Getting the square's position once, before updating its position is another solution.
In either case it may be smoother to update the position of the square at most once, with the position where it transition to.
In this code used to find an answer, the html element's clientWidth and clientHeight properties are a special case of these properties and reflect the size of the view port excluding scroll bars. The transition timing is set to 0.05 seconds to avoid stroboscopic effect from screen refresh:
let square = document.querySelector(".square");
const HTML = document.firstElementChild;
document.addEventListener("mousemove", function (e) {
if (square !== null) {
let domRect = square.getBoundingClientRect()
let x = e.pageX;
let y = e.pageY;
x = Math.min( HTML.clientWidth - domRect.width, x);
y = Math.min( HTML.clientHeight - domRect.height, y);
square.style.top = `${y}px`;
square.style.left = `${x}px`;
//square.setAttribute("style", `top: ${y}px; left: ${x}px`);
}
});
*,
*::before,
*::after{
box-sizing: border-box;
}
body{
margin: 0;
border: 1px solid blue;
}
.square {
position: absolute;
height: 50px;
width: 50px;
border: 5px solid red;
transition: .05s ease-in-out;
}
<div class="square"></div>

Why does the circle in this code snippet lag behind the actual mouse cursor?

I am new to JavaScript and taking JavaScript Training course. The js code is supposed to render a circle at the mouse pointer location and listen for any changes.
const AREA = document.body;
const CIRCLE = document.querySelector('.circle');
function mouseCoordinates(e) {
var horizontalPosition = e.clientX - 26;
var verticalPosition= e.clientY - 26;
// Set horizontal and vertical position.
CIRCLE.style.left = horizontalPosition + 'px';
CIRCLE.style.top = verticalPosition + 'px';
}
AREA.addEventListener('mousemove', mouseCoordinates, false);
body {
width: 100vw;
height: 100vh;
}
.circle {
position: absolute;
top: 1px;
width: 50px;
height: 50px;
color: transparent;
border: 2px solid red;
border-radius: 50%;
}
<div class="circle"></div>
Initially the mouse pointer stays at the center of the circle, but when I am slightly increasing the speed of mouse movement the circle seems to "lag" behind.
Why does this happen?
Is this related to the performance of my system?
Isn't the listener supposed to run as and when the mouse moves and draw the circle exactly over the current position of the mouse?

How to adjust the mouse position after rotating an object?

I am trying to create an eye that follows cursor movement.
I got the horizontal and vertical coordinate of the mouse and the browser width and height.
Everything works perfectly. Except that I used rotate(45 deg) on the design of the eye so now the ball is not moving in the right position.
I was thinking about a math equation that finds the distance between the old and new coords, but I am not sure how to implement it.
Here is the full code:
https://jsfiddle.net/Mr_MeS/3ym6kuec/3/
so this is the .eye where its rotated
.eye {
width: 37.5px;
height: 37.5px;
background: white;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(45deg);
border-radius: 75% 0;
overflow: hidden;
cursor: pointer;
}
.ball {
width: 7.5px;
height: 7.5px;
background: #222f3e;
border-radius: 50%;
border: 5px solid #576574;
position: relative;
top: 50%;
left: 50%;
}
and here is the JS that does the work and needs to be edited.
var balls = document.getElementsByClassName("ball");
document.onmousemove = function () {
var x = event.clientX * 100 / window.innerWidth + "%";
var y = event.clientY * 100 / window.innerHeight + "%";
//event.clientX => get the horizontal coordinate of the mouse
//event.clientY => get the Vertical coordinate of the mouse
//window.innerWidth => get the browser width
//window.innerHeight => get the browser height
for (var i = 0; i < 2; i++) {
balls[0].style.left = x;
balls[0].style.top = y;
balls[0].style.transform = "translate(-" + x + ",-" + y + ")";
}
}
Now, if I remove the rotation from the .eye, it works perfectly, expect that the whole shape doesn't look to be in position.
If I keep the 45deg rotation, the shape is good, but the ball moves wrongly.
You could try to put the eye-background (the white part that needs to rotate 45 degrees) into a div (or pseudo-element) that's inside the .eye element. In that way you don't need to rotate the container element, so the coordination of the ball element stays the same.
Another point, why are you using that for-loop? I think running the code once will be sufficient :)
EDIT: I've been playing around with your example a bit and fixed it. What happens is that if you rotate an element, the direction in which things will transform (and top/left positioning) will also change. So moving the element 10px to the left, will go 10px to the left, under a 45 degree angle, because it's rotated 45 degrees.
What I did now was to put an element (.inner) inside the eye div, which I gave a counter-rotation of -45 degrees. In this way, the container element of the ball has the correct orientation again, which fixes the problem: https://jsfiddle.net/bxprjvgL/
HTML:
<div class="eye">
<div class="inner">
<div class="shut"><span></span></div>
<div class="ball"></div>
</div>
</div>
CSS:
.inner {
width: 100%;
height: 100%;
transform: rotate(-45deg);
}

background position issue in parallax scrolling in javascript

I have this common pattern of parallax scrolling with plain javascript that uses custom data attributes and scrolls the background image in the oposite direction.
HTML:
<header id="home" class="section" data-type="background" data-speed="3"></header>
<section id="portfolio" class="section"></section>
<section id="about" class="section"></section>
<section id="contact" class="section"></section>
CSS:
#home {
background-color: grey;
height: 100%;
width: 100%;
background-image: linear-gradient(to bottom, rgba(#000, 0.5), rgba(#000, 0.5)), url("../bg.jpg");
background-attachment: fixed;
background-repeat: repeat;
background-position: 50%;
background-size: cover;
position: relative;
}
JAVASCRIPT:
{
function parallax() {
Array.from(document.querySelectorAll('*[data-type="background"]')).forEach(e => {
let yPos = -(window.pageYOffset / e.dataset.speed);
var coords = `50% ${yPos}px`;
e.style.backgroundPosition = coords;
});
}
document.addEventListener('scroll', function () {
parallax();
});
}
The issue is that this code calculates the Ypos variable and assigns it to the background position-y property. Actually it overrides the css which is set to 50% before you start scrolling. As a result the image goes from the center to the bottom once you start scrolling. I have included a codepen to see the problem.
https://codepen.io/anon/pen/pLvjqR
Is there any way to add the yPos variable to the initialized background position 50% 50%, which means make it 50% 50%+ypos instead of 50% ypos.
Thanks.
I changed the speed of 3 -> .02 and javascript, you have to start at 50% and reduce this percentage rather than applying values in pixels.
// let yPos = -(window.pageYOffset / e.dataset.speed);
let yPos = (e.getBoundingClientRect().top - window.pageYOffset) * e.dataset.speed + 50;
// var coords = `50% ${yPos}px`;
var coords = `50% ${yPos}%`;
You can view changes here :
https://codepen.io/anon/pen/mxyVBV

Categories

Resources