set width and height of an image after transform: rotate - css

i have a div with width: 190px and height: 260px, i assign img tag on that div, when i upload an image that shows how the image before, after that i rotate the image but the width and height of the image didnt change like the div, i have used inherit, everything about position and display, but no good at all..

I have figured out an automated way as below:
First, I am getting natural height and width of the image (from onload trigger):
var naturalWidth = event.currentTarget.naturalWidth
var naturalHeight = event.currentTarget.naturalHeight
Then I am computing a transform scale using aspect-ratio and generating transform style as below (pseudo-code):
For 90deg (y-shift):
const scale = naturalWidth > naturalHeight ? naturalHeight / naturalWidth : 1;
const yshift = -100 * scale;
const style = `transform:rotate(90deg) translateY(${yshift}%) scale(${scale}); transform-origin: top left;`
For 270deg (x-shift):
const scale = naturalWidth > naturalHeight ? naturalHeight / naturalWidth : 1;
const xshift = -100 * scale;
const style = `transform:rotate(270deg) translateX(${xshift}%) scale(${scale}); transform-origin: top left;`
Hope this helps.

Inherit will not work.
Because you have to make the set the width of your image as the height of your parent. Then it will get completely resize in the parent element.
image-width = parent-height
Because after applying transform property width and height property will also get rotate in its respect.
Sol 1:
change the width of your image along with the transform property. (If it is variable then you can use the SCSS variables to assign the same values to the image-width and parent height.)
Sol 2:
This is not the perfect solution but will work in many cases. Add scale property to your transform property like this
transform: rotate(90deg) scale(.7);
Adjust the scale values according to you.

Hey,
Please Try this code.
var $=jQuery.noConflict();
$(document).ready(function(){
$('#RotateButton').click(function(){
$('.col').toggleClass("afterRot");
});
});
/* ----- IE Support CSS Script ----- */
var userAgent, ieReg, ie;
userAgent = window.navigator.userAgent;
ieReg = /msie|Trident.*rv[ :]*11\./gi;
ie = ieReg.test(userAgent);
if(ie) {
$(".col").each(function () {
var $container = $(this),
imgUrl = $container.find("img").prop("src");
if (imgUrl) {
$container.css("backgroundImage", 'url(' + imgUrl + ')').addClass("custom-object-fit");
}
});
}
body { padding: 0; margin: 0; }
.col { position: relative; display: block; width:100vh; height: 100vh; }
.afterRot{ transform: rotate(90deg); object-fit: cover; }
.col img { position: absolute; top: 0; left: 0; right: 0; width: 100%; height: 100%; object-fit: cover; }
.custom-object-fit { position: relative; background-size: cover; background-position: center center; }
.custom-object-fit img { opacity: 0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="mob">
<button type="button" id="RotateButton"> Rotate </button>
<div class="col">
<img class="nor" id="rowImg" src="https://cdn-images-1.medium.com/max/1600/1*tSyuv3ZRCfsSD5aXB7v8DQ.png">
</div>
</div>

I think this is because you are not removing the class already associated with the Image. Try adding this to your button
$(document).ready(function(){
$('#RotateButton').click(function(){
$('#rowImg').removeClass("normalx").addClass("afterRot");
});
});
for a css like
.col {
width:260px;
height:190px:
border: solid 1px #6c757d;
padding: 10px;
}
.nor{
width:250px;
height:150px;
}
.afterRot{
width:inherit;
transform: rotate(90deg);
}
I have a sample here

Related

How to run more than one css transition with a click on a button?

I am building an animated hamburger menu with html css js. I now know how to start a css transition with javascript. See https://jsfiddle.net/ralphsmit/byaLfox5/. My problem now is that I need to run more than one transition with a click on my button. I've put my code here https://jsfiddle.net/ralphsmit/v980ouwj/16/.
A short explanation of my code. I have made a button (for the sake of clarity I made it green with a low opacity) and when that button is clicked, the background .dsgn-header-background will appear. Now I also want the two rectangle for the menu to animate into a cross and that the the .dsgn-header-menu-opened-menuitems also fade in.
My question is, how do I modify this js code, so that more than one transition will be started? So all transitions are a different element. You'll find the full code in the JS fiddle above (feel free to edit this).
Javascript:
const background = document.querySelector('.dsgn-header-background');
const button = document.querySelector('.dsgn-header-button');
let open = false;
button.addEventListener('click', onClickPlay);
function onClickPlay(){
if(background.classList.contains('on')){
background.classList.remove('on');
}else{
background.classList.add('on');
}
}
Check this out.
function onClickPlay(){
if(background.classList.contains('on')){
background.classList.remove('on');
element.classList.remove('anotherClassWithDifferentTransitions');
}else{
background.classList.add('on');
element.classList.add('anotherClassWithDifferentTransitions');
}
}
Cheers!
You can try this , The changes is i have added 2 more constant variable which adding on class when menu open and remove on class when menu closes.
const background = document.querySelector('.dsgn-header-background');
const button = document.querySelector('.dsgn-header-button');
const menu_up = document.querySelector('.dsgn-header-rectangle-up');
const menu_down = document.querySelector('.dsgn-header-rectangle-down');
let open = false;
button.addEventListener('click', onClickPlay);
function onClickPlay(){
if(background.classList.contains('on')){
background.classList.remove('on');
menu_up.classList.remove('on');
menu_down.classList.remove('on');
}else{
background.classList.add('on');
menu_up.classList.add('on');
menu_down.classList.add('on');
}
}
hope this will help you .
const content = document.querySelector('.content');
const button = document.querySelector('.dsgn-header-button');
function onClickPlay() {content.classList.toggle('on');}
button.addEventListener('click', onClickPlay);
fiddle: https://jsfiddle.net/s24mbakf/
Add the other elements to your onClickPlay function as you did with demo.
const demo = document.querySelector('.demo');
const demo2 = document.querySelector('.demo2');
const buttondemo = document.querySelector('.buttondemo');
let open = false;
buttondemo.addEventListener('click', onClickPlay);
function onClickPlay(){
if(demo.classList.contains('on')){
demo.classList.remove('on');
demo2.classList.remove('on');
} else {
demo.classList.add('on');
demo2.classList.add('on');
}
}
.demo {
width: 0;
height: 100vh;
background-color: black;
position: absolute;
right: 0;
transition: width 4s;
}
.demo.on {
width: 100vw;
}
.demo2 {
width: 0;
height: 50vh;
background-color: red;
position: absolute;
right: 0;
transition: width 8s;
}
.demo2.on {
width: 100vw;
background-color: yellow;
}
.buttondemo {
position: absolute;
top: 0px;
right: 0px;
width: 100px;
height: 100px;
background-color: green;
}
<div class="demo"><div>
<div class="demo2"><div>
<div class="buttondemo"><div>

Issue with 100% high Mapbox map when rendering with React

I am rendering a map using Mapboxgl, Bootstrap 4 and React.
I need the map to take 100% of the height of the page and to display in the first column of a two column grid.
However, when using React, the width of the map extends over to 100% of the width of the row - overlapping underneath the 2nd column.
The best thing would be to check my examples on jsfidle to understand what I mean.
Map correctly showing (when using pure HTML and no React)
https://jsfiddle.net/apphancer/jhxy5c63/
Map showing width issue (when using React)
https://jsfiddle.net/apphancer/9g71ovn6/
In order to have the 100% height working I am using this CSS:
.map-wrapper {
position: fixed;
width: 100%;
height: 100%;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
}
I suspect this might have something to do with how the map gets rendered with React as the problem does not happen when using the pure HTML solution.
Is anyone able to point in the right direction?
HTML
<div id="app"></div>
CSS
body, html {
height: 100%;
}
#app, .row, .col-9 {
height: 100%;
}
.col-3 {
background-color: rgba(0, 0, 0, 0.5);
border: 1px solid red;
}
.map-wrapper {
position: fixed;
width: 100%;
height: 100%;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
}
JS
mapboxgl.accessToken = 'pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4M29iazA2Z2gycXA4N2pmbDZmangifQ.-g_vE53SD2WrJ6tFX7QHmA';
class Application extends React.Component {
componentDidMount() {
const map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/light-v9', // stylesheet location
center: [13.392, 52.523], // starting position [lng, lat]
zoom: 9 // starting zoom
});
map.addControl(new mapboxgl.NavigationControl());
map.resize(); // tried with this to see if it would help
}
render() {
return (
<div className="row no-gutters">
<div className="col-9">
<div className="map-wrapper">
<div ref={el => this.mapContainer = el} id="map"/>
</div>
</div>
<div className="col-3">
2 of 2
</div>
</div>
)
}
}
ReactDOM.render(<Application/>, document.getElementById('app'));
If you use position fixed with 100% width in wrapper, it will cover all width. But if you set position to relative, it will cover just remaining width.
.map-wrapper {
position: relative;
width: 100%;
height: 100%;
}
This worked in your react-jsfiddle. Please try.
If you are using position fixed in your project you can cover whole area so for that you have 2 solution
1st solution
give 75% width to the #map so it will behave like col-9 and no need to give position: absolute;
#map {
width: 75%;
height: 100%;
}
2nd Solution
give it relative position to the parent of your element so it cant leave it area, for that you can change position: fixed to position: relative
.map-wrapper {
position: relative;
width: 100%;
height: 100%;
}
both solution is good solution but i prefer 2nd solution, from my side.
const [viewport, setViewport] = useState({
width: '100%',
height: 'calc(100vh - 162px)', // 162px is size height of all elements on top of map
latitude: 0,
longitude: 0,
zoom: 12,
bearing: 0,
pitch: 0,
transitionDuration: 2000,
transitionInterpolator: new FlyToInterpolator(),
});
I migrated to React 18, and updated a bunch of dependencies, included the map library.
The only thing that resolved my problem was this. It has a tic, when the map resizes, but it's a start.
useEffect(() => {
map.on("load", () => map.resize());
}, [])

Blurry image after scale in Safari and Chrome

I have a big image as background-image, and I reduce the size on scroll, and in the same time I modify the background-position too.
Unfortunately I found problems in Chrome and Safari. In these browsers as soon as I start to scroll the image become blurry.
I tried many solutions for that problem, but no luck. Do you have idea what's wrong, or an other method what can help to achieve the same effect?
JS
function promo_scroll() {
var current_scroll = jQuery(window).scrollTop();
var scale = 5;
var window_height = jQuery(window).height();
var window_width = jQuery(window).width();
var correction = jQuery('#header-wrapper').height()-500;
if(scale*((1-(current_scroll/window_height))) > 1 && (window_width/window_height >= 198/119)) {
jQuery('#custom-header').removeAttr('data-top');
jQuery('.container').css({
'position' : 'fixed',
'display' : 'block',
'top': 0,
'left': 0,
'transform' : 'scale(' + scale*((1-(current_scroll/window_height))) + ')',
});
jQuery('.container:not(.content)').css('background-position', '0 ' + correction + 'px');
} else if(window_width/window_height >= 198/119) {
if (typeof jQuery('#custom-header').attr('data-top') == 'undefined'){
jQuery('#custom-header').attr('data-top',jQuery('#custom-header').offset().top);
jQuery('#content-wrapper').css('padding-top',jQuery('#custom-header').offset().top);
}
jQuery('.container').css({
top : jQuery('#custom-header').attr('data-top')-current_scroll,
'transform' : 'scale(1)',
});
}
else{
jQuery('#custom-header').removeAttr('data-top');
jQuery('#content-wrapper').css('padding-top',0);
jQuery('.container').css({
'background-position': 'center top',
'position' : 'absolute',
'top': 0,
'left': 0,
'transform' : 'scale(1)',
});
jQuery('.container.content').css({
'position' : 'absolute'
});
}
}
jQuery(document).on('click','#custom-header', function(){
jQuery('html, body').animate({'scrollTop': jQuery('.l-grid-row').offset().top - jQuery('#main-header').outerHeight()},2500);
});
jQuery(document).ready(function(){
promo_scroll();
});
jQuery(window).on('scroll', function(){
jQuery('.container.content')[0].style.setProperty('background-position', jQuery(window).scrollTop() + 'px 50%', 'important');
promo_scroll();
});
jQuery(window).on('resize', function(){
jQuery('#custom-header').removeAttr('data-top');
promo_scroll();
});
CSS
body {
-webkit-font-smoothing: antialiased;
}
.container {
height: 100%;
width: 100%;
z-index: 6;
will-change: transform;
filter: none;
-webkit-filter: blur(0px);
-moz-filter: blur(0px);
-ms-filter: blur(0px);
filter:progid:DXImageTransform.Microsoft.Blur(PixelRadius='0');
}
.container.content{
z-index: 5;
background-image:url('http://i.imgur.com/f68DPZG.jpg');
background-position: left center;
background-repeat: repeat-x;
}
#header-wrapper {
display: none;
}
#media screen and (min-width: 767px) {
#header-wrapper {
display: block;
}
}
#media screen and (min-aspect-ratio: 198/119) {
.container {
-webkit-transform: scale(5);
-moz-transform: scale(5);
transform: scale(5);
background-size: 100% auto !important;
background-position: center center !important;
}
}
.spacing {
height: 2000px;
}
HTML
<div id="header-wrapper" data-full-height-header="true">
<div id="custom-header" class="container"></div>
<div class="container content"></div>
</div>
<div class="spacing">
</div>
The effect is visible only with a specific aspect ratio, so please check the link in full screen: https://jsfiddle.net/4eod1ng5/3/embedded/#Result
Update: After several testing it looks like the problem occurs only in OSX (Safari and Chrome)
Update 2: After I updated my chrome to 51 in linux the problem appeared.
unfortunately your fiddle does not work well for me, i can see some kind of weirdness, but i cannot run the fiddle when i edit it. however, running the code in my head:
you are using scale in combination with a blur effect. when you use scale 5, it will not re-initialize the effect, but only scale up the object. i would try starting with a big size (width + height = 500%) and rather scaling it down (scale < 1) than up.
you can also try transforming the container instead of the object with the background image. that helped for me occasionaly when dealing with problems like this.
I tried the jsFidle. the problem I see here is because the images are low resolution, try to use higher resolutions images

Zooming in overflow: scroll

I am trying to implement correctly scaling and zooming in css way. I created an example with scaled view. When click, the view should be zoomed and then to be able to scroll.
https://jsfiddle.net/opb5tcy8/4/
I have several issues with it:
Can I somehow get rid of the margin-left and margin-top on the .zoomed class? I did not manage to scale it without necessity to shift it with these margins.
When clicked, I can get the click position by clientX. I would like to use it to fluently scroll to the clicked position during zooming. However I can't manage the scroll to be fluent and when removing the margin-left it is kind of jumpy and not nice.
When you zoom in and move the scroll to the center and then zoom out, you can see the zoom is not nice as it first scrolls to the right. Is there a way to prevent it?
When you scroll to corners in Chrome on OSX it tends do navigate back/forward in browser. Is there a way to prevent this behaviour?
UPDATE:
The first part can be solved with transform-origin: 0 0. The other issues stays mostly the same as it is demonstrated.
Hm... I could say it is impossible to satisfy point 2 your condition with current browsers' support. The other are possible, as in this demo:
$(document).ready(function() {
var windowHalfWidth = $("#window").width() / 2;
var scalingFactor = 0.55;
var throtte = false;
$("#slider").click(function(event) {
//Simple event throtte to prevent click spamming breaking stuff up
if (throtte) return false;
throtte = true;
setTimeout(function() {
throtte = false;
}, 1000);
var xSelf = event.pageX - $("#window").offset().left + $("#window").scrollLeft();
if ($(this).hasClass("zoomed")) {
$("#window").animate({
scrollLeft: (xSelf / scalingFactor - windowHalfWidth)
}, 1000, "linear");
} else {
$("#window").animate({
scrollLeft: (xSelf * scalingFactor - windowHalfWidth)
}, 1000, "linear");
}
$("#slider").toggleClass("zoomed");
});
});
body {
background-color: #eee;
margin-top: 10px; /*reduced margin for easier view in SO */
}
#window {
width: 500px;
height: 200px;
margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;
border: 1px solid #999;
position: relative;
background-color: white;
}
#slider {
width: 900px;
height: 600px;
background-color: #fff;
position: absolute;
transition: 1s linear;
top: 0;
left: 0;
transform-origin: 0 0;
}
#slider.zoomed {
transform: scale(0.55);
}
#slider div {
width: 50px;
height: 50px;
line-height: 50px;
position: absolute;
top: 75px;
background-color: #eee;
text-align: center;
}
#obj1 {
left: 10px;
}
#obj2 {
left: 210px;
}
#obj3 {
left: 410px;
}
#obj4 {
left: 610px;
}
#obj5 {
left: 810px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="window">
<div id="slider" class="zoomed">
<div id="obj1">1</div>
<div id="obj2">2</div>
<div id="obj3">3</div>
<div id="obj4">4</div>
<div id="obj5">5</div>
</div>
</div>
As you can see, the zooming & scrolling is quite laggy, especially when the far right size is zoomed in.
The reason is simple, because jQuery and css both have their own animation loop, and they are not in sync. In order to solve this we'll need to somehow manage to do both scrolling & scaling animations with only one system, either jQuery or CSS.
Problem is: jQuery don't have a scaling feature, and css can't scroll elements. Wonderful.
If your scaling can be done with width/height though, it would be possible, using jquery width&height animate(). But if the #slider consists of many components I guess it can't be done.
So um writing an answer just to say it's impossible is kind of a let down, so I think maybe I can suggest an alternative, using dragging to scroll content (similar to the way Google map work):
var windowHalfWidth, startX, startLeft, minLeft, dragging = false,
zooming = false;
var zoomElement = function(event) {
var xSelf = event.pageX - $("#window").offset().left - parseFloat($("#slider").css("left"));
if ($("#slider").hasClass("zoomed")) {
minLeft = windowHalfWidth * 2 - 900;
var newLeft = Math.min(Math.max((-(xSelf / 0.55 - windowHalfWidth)), minLeft), 0);
$("#slider").css("left", newLeft + "px");
} else {
minLeft = windowHalfWidth * 2 - 900 * 0.55;
var newLeft = Math.min(Math.max((-(xSelf * 0.55 - windowHalfWidth)), minLeft), 0);
$("#slider").css("left", newLeft + "px");
}
$("#slider").toggleClass("zoomed");
}
$(document).ready(function() {
windowHalfWidth = $("#window").width() / 2;
minLeft = windowHalfWidth * 2 - 900 * 0.55;
$("#slider").on({
mousedown: function(event) {
dragging = true;
startX = event.pageX;
startLeft = parseFloat($(this).css("left"));
},
mousemove: function(event) {
if (dragging && !zooming) {
var newLeft = Math.min(Math.max((startLeft + event.pageX - startX), minLeft), 0);
$("#slider").css("left", newLeft + "px");
}
},
mouseup: function(event) {
dragging = false;
if (Math.abs(startX - event.pageX) < 30 && !zooming) {
// Simple event throtte to prevent click spamming
zooming = true;
$("#slider").css("transition", "1s");
setTimeout(function() {
zooming = false;
$("#slider").css("transition", "initial");
}, 1000);
zoomElement(event);
}
},
mouseleave: function() {
dragging = false;
}
});
});
body {
background-color: #eee;
margin-top: 10px; /*reduced margin for easier view in SO */
}
#window {
width: 500px;
height: 200px;
margin: 0 auto;
overflow: hidden;
border: 1px solid #999;
position: relative;
background-color: white;
}
#slider {
width: 900px;
height: 600px;
background-color: #fff;
position: absolute;
top: 0;
left: 0;
transform-origin: 0 0;
}
#slider.zoomed {
transform: scale(0.55);
}
#slider div {
width: 50px;
height: 50px;
line-height: 50px;
position: absolute;
top: 75px;
background-color: #eee;
text-align: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#obj1 {
left: 10px;
}
#obj2 {
left: 210px;
}
#obj3 {
left: 410px;
}
#obj4 {
left: 610px;
}
#obj5 {
left: 810px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="window">
<div id="slider" class="zoomed">
<div id="obj1">1</div>
<div id="obj2">2</div>
<div id="obj3">3</div>
<div id="obj4">4</div>
<div id="obj5">5</div>
</div>
</div>
This variation manages to get CSS to do both animation, by sacrificing the scrollbar (which is pretty ugly imo, who needs it?) and use css left instead.
So I hope if in the end you can't find a good solution, at least you have this to consider as fall back version.
I'll address the points individually and then give an example at the end.
When clicked, I can get the click position by clientX. I would like to
use it to fluently scroll to the clicked position during zooming.
In my opinion scroll animations during transitions can be a bit choppy in webkit browsers. Try balancing the animation time of the jQuery effect with the animation time of the css transition.
When you zoom in and move the scroll to the centre and then zoom out, you can see the zoom is not nice as it first scrolls to the right. Is there a way to prevent it?
Bring the scrollLeft property of the div#window back to 0px. Again, tweaking the animation times will make this less jerky.
When you scroll to corners in Chrome on OSX it tends do navigate back/forward in browser. Is there a way to prevent this behaviour?
You could use the mouseover and mouseout events to toggle a overflow:hidden css on the body.
Here's an example change to your code:
var slider = $("#slider").on('click', function(event) {
if (!slider.hasClass('zoomed')) {
// zoom back to left position
$('#window').animate({scrollLeft:'0px'});
}else{
// zoom to click position within slider
$('#window').animate({scrollLeft:event.clientX + 'px'}, 2000);
}
slider.toggleClass("zoomed");
});
/* stop window scrolling when using slider */
slider
.on('mouseover', function () {
$(document.body).css({overflow:'hidden'});
})
.on('mouseout', function () {
$(document.body).css({overflow:'auto'});
});
And an updated fiddle.

Coderwall blurred background effect with canvas

How is coderwall.com doing this background effect, where they take a small image, blur it, and size it up to 100% of the viewport. Here is an example: https://coderwall.com/p/on5ojq
I tried:
<canvas class="blur" src="https://d3levm2kxut31z.cloudfront.net/assets/locations/Mexico-1c39f581666a50a97c5130e13837ff20.jpg" width="300" height="200"></canvas>
Then added the following css:
.blur {
min-width: 100%;
min-height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: -2;
opacity: 0.7;
}
But it is not working.
See the following jsFiddle http://jsfiddle.net/RDdbt/1/
Try this:
var CanvasImage=function(e,t){
this.image=t,
this.element=e,
this.element.width=this.image.width,
this.element.height=this.image.height;
var n=navigator.userAgent.toLowerCase().indexOf("chrome")>-1,
r=navigator.appVersion.indexOf("Mac")>-1;
n&&r&&(this.element.width=Math.min(this.element.width,300),this.element.height=Math.min(this.element.height,200)),
this.context=this.element.getContext("2d"),
this.context.drawImage(this.image,0,0)
};
CanvasImage.prototype={
blur:function(e){
this.context.globalAlpha=.5;
for(var t=-e;t<=e;t+=2)
for(var n=-e;n<=e;n+=2)
this.context.drawImage(this.element,n,t),
n>=0&&t>=0&&this.context.drawImage(this.element,-(n-1),-(t-1));
this.context.globalAlpha=1
}
},
$(function(){
var image,canvasImage,canvas;
$(".blur").each(function(){
canvas=this,
image=new Image,
image.onload=function(){
canvasImage=new CanvasImage(canvas,this),
canvasImage.blur(4)
},
image.src=$(this).attr("src");
});
});
http://jsfiddle.net/RDdbt/6/

Resources