How to crop image canvas/mask when hover? - javascript

Any react library or quick CSS way to crop the image's canvas when on hover?
Like this: https://imgur.com/A4x0DJ7.gif
Thank you

a simple clip-path can do it:
.box {
display: inline-block;
padding: 10px;
background: grey;
}
img {
display: block;
clip-path: inset(0);
transition: .5s all;
}
.box:hover img {
clip-path: inset(10px);
}
<div class="box">
<img src="https://picsum.photos/id/1069/200/200">
</div>

Here you go;
I just used the divs instead of images which i hope is ok.
#img {
height: 300px;
width: 300px;
background-color: grey;
display: flex;
align-items: center;
justify-content: center;
}
#image {
height: 280px;
width: 280px;
background-color: orange;
}
#image:hover {
transition: width 0.5s, height 0.5s;
width: 260px;
height: 260px;
}
<div id='img'>
<div id='image'></div>
</div>

Related

Overflow hidden on bottom of image

Im trying to hide the bottom of the girl image when the 3D background is triggered. I tried to add the overflow: hidden; to the test-imgplace class and it doesn't look right.
Is there a better way to fix it?
See what I did on JSFIDDLE
.card .image {
height: 275px;
width: 183px;
background-size: cover;
background-position: center center;
}
.imgtest {
position: absolute;
z-index: 1;
text-align: center;
top: 0;
left: 100px;
border: solid 1px;
pointer-events: none;
}
.test-imgplace {
margin: 0 auto;
position: relative;
overflow: hidden;
}
.card .text {
height: 20%;
margin: 0;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
text-transform: uppercase;
font-size: 50px;
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
}
.card {
width: 183px;
height: 275px;
margin: auto auto;
background: #383030;
border-radius: 5px;
overflow: hidden;
text-align: center;
}
.card-content {
transform-style: preserve-3d;
}
body {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.hover-in {
transition: .3s ease-out;
}
.hover-out {
transition: .3s ease-in;
}
.card-hover {
margin: 0;
}
<div class="test-imgplace">
<img src="https://christianluneborg.com/imgs/test-woman.png" class="imgtest">
<div class="card-hover">
<div class="card">
<div class="card-content">
<div class="image" style="background-image: url(https://christianluneborg.com/imgs/test-woman-bg.png);"></div>
</div>
</div>
</div>
</div>

Animate a sound Bar using vanilla js

I want soundbar effects i.e
I want the corresponding divs(bars) to increase/decrease height indefinetely like in the code snippet below. I want to acheive the same effect in Vanilla JS.
I want them to change height randomly i.e 5 bars will change height in 5 random ways.
The Element.animate() method is not doing the job and I am not allowed to use any external libraries or API's as well. I am unsure of using the CSS animate method.
The code written below is in jQuery. I am unable to decipher the same solution in Vanilla JS.
function fluctuate(bar) {
var amplitude = Math.random() * 42;
console.log(amplitude);
var height = amplitude * 4;
//Animate the equalizer bar repeatedly
bar.animate({
height: height
}, 1000, function() {
fluctuate($(this));
});
}
$(".bar").each(function(i) {
fluctuate($(this));
console.log($(this));
});
.inline-block-wrapper {
display: inline-block;
margin-right: -4px;
}
.bar-wrapper {
background-color: black;
height: 160px;
width: 135px;
display: block;
position: relative;
}
.bar {
/* background-color: green; */
width: 100%;
height: 160px;
position: absolute;
left: 0px;
bottom: 0px;
}
.bar-container {
margin: auto;
width: 50%;
height: 10rem;
border: 15px solid black;
}
timers {
display: flex;
}
.start {
display: inline;
background-color: green;
margin-right: 50px;
padding: 10px 10px;
color: white;
border: none;
width: 100px;
height: 35px;
justify-content: center;
}
.stop {
display: inline;
background-color: red;
margin-left: 50px;
padding: 10px 10px;
color: white;
border: none;
width: 100px;
height: 35px;
justify-content: center;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
</head>
<body>
<div class="bar-container">
<div class="inline-block-wrapper">
<div class="bar-wrapper">
<div class="bar" style="background-color:#754ab7"></div>
</div>
</div>
<div class="inline-block-wrapper">
<div class="bar-wrapper">
<div class="bar" style="background-color:#c640a5"></div>
</div>
</div>
<div class="inline-block-wrapper">
<div class="bar-wrapper">
<div class="bar" style="background-color:#f05386"></div>
</div>
</div>
<div class="inline-block-wrapper">
<div class="bar-wrapper">
<div class="bar" style="background-color:#f58169"></div>
</div>
</div>
<div class="inline-block-wrapper">
<div class="bar-wrapper">
<div class="bar" style="background-color:#f9c059"></div>
</div>
</div>
</div>
<div class="timers">
<button class="start" onClick=f luctuate()> Start</button>
<button class="stop" onClick=s topSequence()> Stop</button>
Took a whole lot of CSS but I worked out a solution to something close to what I wanted.
var clicks = 0
function fluctuate(){
clicks+=1
if(clicks>1){
stopFluctuation()
}else{
document.querySelector('.div-stop').classList.toggle('animate-bars')
var bar = document.getElementsByClassName('div-bar')
}
}
function stopFluctuation() {
let count = 1;
let bars = document.getElementsByClassName('div-bar');
for(bar of bars) {
bar.classList.toggle('paused-bars');
}
}
.container {
border: 20px solid black;
background-color: black;
}
.button-container {
display: flex;
}
.start {
display: inline;
background-color: green;
margin-right: 50px;
padding: 10px 10px;
color: white;
border: none;
width: 100px;
height: 35px;
justify-content: center;
}
.stop {
display: inline;
background-color: red;
margin-left: 50px;
padding: 10px 10px;
color: white;
border: none;
width: 100px;
height: 35px;
justify-content: center;
}
.div-stop {
display: flex;
align-items: center;
width: 550px;
height: 150px;
overflow: hidden;
}
.div-stop div {
flex: 10 auto;
height: 100%;
margin: 0;
}
.animate-bars div {
animation: animate-bar 500ms linear infinite alternate;
transform-origin: bottom;
}
.animate-bars div:first-child {
margin-left: 0;
}
.animate-bars div:last-child {
margin-right: 0;
}
.animate-bars div:nth-child(1) {
animation-duration: 2200ms;
animation-delay: 9ms;
position: relative;
top:22%;
}
.animate-bars div:nth-child(2) {
animation-duration: 1500ms;
animation-delay: 0ms;
position: relative;
top: 33%;
}
.animate-bars div:nth-child(3) {
animation-duration: 1789ms;
animation-delay: 5ms;
position: relative;
}
.animate-bars div:nth-child(4) {
animation-duration: 2786ms;
animation-delay: 7ms;
position: relative;
top: 10%;
}
.animate-bars div:nth-child(5) {
animation-duration: 1659ms;
animation-delay: 8ms;
position: relative;
top: 27%;
}
#keyframes animate-bar {
0% {
transform: scaleY(0);
}
100% {
transform: scaleY(100%);
}
}
body {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
body::after {
content: "";
position: absolute;
top: 50%;
right: 0;
left: 0;
width: 100%;
height: 1px;
}
.paused-bars {
-webkit-animation-play-state: paused;
animation-play-state: paused !important;
}
<div class = "container">
<div class="div-stop">
<div style="background-color:#754ab7" class="div-bar"></div>
<div style="background-color:#c640a5" class="div-bar"></div>
<div style="background-color:#f05386" class="div-bar"></div>
<div style="background-color:#f58169" class="div-bar"></div>
<div style="background-color:#f9c059" class="div-bar"></div>
</div>
</div>
<div class = "button-container">
<button id="start" class= "start" onClick="fluctuate()">Start</button>
<button id="stop" class = "stop" onClick="stopFluctuation()">Stop</button>
</div>

Jumping element during width animation

I am trying to animate width on my fixed element using calc simply because I can't make it relative. It's one of those nav bars that hide when scrolling down and appear back on the top when scrolling up.
For some reason the animation isn't smooth and the 'Settings' div jumps between the transitions. The weird or maybe not that weird bit is that it works fine in Chrome but not in IE...
I know having a div with a calculated width isn't the best idea here but I simply can't make it relative due to its constant disappearance on scroll. I have spent hours trying to figure it out for nothing. Try running it in IE and compare it with Chrome.
const sideMenu = document.querySelector('.side-menu');
sideMenu.addEventListener('click', function() {
sideMenu.classList.toggle('collapse');
});
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.side-menu {
width: 160px;
height: 100vh;
background-color: #ccc;
transition: ease-in-out 0.3s;
float: left;
cursor: pointer;
}
.side-menu.collapse {
width: 50px;
}
.side-menu.collapse + .right-panel > .top {
width: calc(100% - 50px);
}
.right-panel {
position: relative;
background-color: yellow;
display: flex;
flex-direction: column;
}
.top {
position: fixed;
height: 70px;
width: calc(100% - 160px);
background-color: #c3c3c3;
transition: ease-in-out 0.3s;
display: flex;
align-items: center;
}
.banner {
width: calc(100% - 20vw);
}
.settings {
width: 20vw;
display: flex;
justify-content: center;
}
<div class="side-menu">Click</div>
<div class="right-panel">
<div class="top">
<div class="banner">Banner</div>
<div class="settings">Settings</div>
</div>
</div>
I'm not certain why IE has those stuttering issues, but you can simplify your layout to not use calc, which appears to solve the problem.
As you're using fixed and want to cover the full width of the page, instead of the calc() you can use left and right.
E.g. In .top we change calc(100% - 160px); this to
right: 0;
left: 160px;
And in .side-menu.collapse + .right-panel > .top
width: calc(100% - 50px); becomes left: 50px;
const sideMenu = document.querySelector('.side-menu');
sideMenu.addEventListener('click', function() {
sideMenu.classList.toggle('collapse');
});
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.side-menu {
width: 160px;
height: 100vh;
background-color: #ccc;
transition: ease-in-out 0.3s;
float: left;
cursor: pointer;
}
.side-menu.collapse {
width: 50px;
}
.side-menu.collapse + .right-panel > .top {
left: 50px;
}
.right-panel {
position: relative;
background-color: yellow;
display: flex;
flex-direction: column;
}
.top {
position: fixed;
height: 70px;
right: 0;
left: 160px;
background-color: #c3c3c3;
transition: ease-in-out 0.3s;
display: flex;
align-items: center;
}
.banner {
width: calc(100% - 20vw);
}
.settings {
width: 20vw;
display: flex;
justify-content: center;
}
<div class="side-menu">Click</div>
<div class="right-panel">
<div class="top">
<div class="banner">Banner</div>
<div class="settings">Settings</div>
</div>
</div>

CSS Transitions for various style values

I'm working on getting better with CSS animations and transitions. What I'm trying to do is make the transition from a square to a circle and vice versa smoother. I know that I need to use the transition method in CSS to control this.
2 questions:
Why is the transition method not working in the below code snippet?
How do I go about making different transition properties for each changing value? i.e. 1 transition timing for changing the border radius, 1 transition timing for moving the circle to where the square is, etc.
.container-flex {
display: flex;
width: 500px;
height: 250px;
border: 1px solid black;
background-color: rgb(0,0,255);
}
.circle {
width: 200px;
height: 200px;
background-color: rgba(255,0,0,0.5);
border-radius: 100px;
transition: all 1s alternate;
}
.circle:hover {
border-radius: 0;
}
.square {
width: 200px;
height: 200px;
background-color: rgba(0,255,0,0.5);
transition: all 1s alternate;
}
.square:hover {
border-radius: 100px;
}
<html>
<body>
<div class="container-flex">
<div class="circle"></div>
<div class="square"></div>
</div>
</body>
</html>
.container-flex {
display: flex;
width: 500px;
height: 250px;
border: 1px solid black;
background-color: rgb(0,0,255);
}
.circle {
width: 200px;
height: 200px;
background-color: rgba(255,0,0,0.5);
border-radius: 100px;
transition: all 1s ease;
}
.circle:hover {
border-radius: 0;
}
.square {
width: 200px;
height: 200px;
background-color: rgba(0,255,0,0.5);
transition: all 1s ease;
}
.square:hover {
border-radius: 100px;
}
<html>
<body>
<div class="container-flex">
<div class="circle"></div>
<div class="square"></div>
</div>
</body>
</html>

How to keep a range slider within a div in a flex-container

Using Javascript, I am trying to create a grid of images, and I'd like to embed a range slider at the bottom of one of the images. To get the grid, I am using flex-container (below I just show two numbers, 1 and 2, as examples, but in the real application they are replaced by images):
<style>
.flex-container {
display: flex;
flex-wrap: wrap;
background-color: LightYellow;
}
.flex-item {
background-color: #f1f1f1;
width: 300px;
margin: 10px;
text-align: center;
line-height: 300px;
font-size: 30px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item"> 2 </div>
</div>
</body>
This part works ok - I get two images side by side, as I want:
Now, suppose I'd like to add a range slide to the second div. So I add this to my styles:
.slidecontainer {
flex: 0 1 auto;
order: 0;
position: relative;
align-items: center;
width: 100%;
}
.slider {
-webkit-appearance: none;
width: 100%;
height: 5px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider:hover {
opacity: 1;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 15px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 15px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
and then attempt to embed the slider into one of the flex-container divs, say the second one:
<div class="flex-item"> 2
<div class="slidercontainer">
<input type="range" min="1" max="100" value="50" class="slider" id="myRange">
<p>Value: <span id="demo"></span></p>
</div>
</div>
For reasons I don't understand the images explode. Here's what they look like now:
Is there a way to keep the dimensions of the images intact and just add the slider at the bottom of one of the images within its div?
Thanks!
Here is the HTML:
<div class="flex-container">
<div class="flex-item">
<img src="https://placeimg.com/300/150/any" alt="">
</div>
<div class="flex-item">
<img src="https://placeimg.com/300/150/any" alt="">
<div class="slidercontainer">
<input type="range" min="1" max="100" value="50" class="slider" id="myRange">
<p>Value: <span id="demo"></span></p>
</div>
</div>
</div>
And here is the CSS:
img {
max-width: 100%;
object-fit: cover;
}
.flex-container {
display: flex;
flex-wrap: wrap;
background-color: LightYellow;
}
.flex-item {
background-color: #f1f1f1;
width: 300px;
margin: 10px;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.slidecontainer {
flex: 0 1 auto;
order: 0;
position: relative;
align-items: center;
width: 100%;
}
.slider {
-webkit-appearance: none;
width: 100%;
height: 5px;
border-radius: 5px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider:hover {
opacity: 1;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 15px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 15px;
border-radius: 50%;
background: #4CAF50;
cursor: pointer;
}
It looks blown out of proportion because of the line-height: 300px; you have set on the .flex-item. Take that out and it should look more normal.
To keep the images in its native aspect ratio, simply just set the max-width to your width value then set width: 100%;. You probably want to have a div around the image too as IE11 tends to play funny with images as flex elements.

Categories

Resources