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
Related
I have a worry with wp video shortcode (for a video on loop and autoplay), which plays fine on firefox, but who doesn't in chrome.
This is my code:
<div class="fullscreen-button-only">
[video mp4="https://www.underthedeepdeepsea.com/wp-content/uploads/videos/NUM-still-life.mp4" poster="" muted="true" loop="true" autoplay="true"]
</div>
The div here allows to apply a class to the video, with a css which hides all controls except the fullscreen button, which appear when you hover the video.
Usually I would resolve this by using a more classical videotag, like this one:
<div class="fullscreen-button-only">
<video src="https://www.underthedeepdeepsea.com/wp-content/uploads/videos/NUM-still-life.mp4" preload="true" autoplay="true" muted="true" loop="true" playsinline width="100%" poster=""></video>
</div>
It works on chrome, but it's far more difficult to make appear the fullcscreen button alone on it.
Is there a solution to make the traditional [wp video] shortcode work with loop and autoplay?
UPDATE : HERE IS THE SOLUTION for video with only a full-screen button, with the last fixes needed (thanks to my brother!) added to the great code proposed by VC.One. Here is the code working.
HTML :
<div id="animatedgif_1" class="fx_fadeIn" style="position: relative; width: 100%; text-indent: 0px; ">
<video class="centrer-verticalement" width="100%" style="" muted playsinline loop autoplay>
<source src="https://www.underthedeepdeepsea.com/wp-content/uploads/videos/NUM-wish.mp4" type="video/mp4"></video>
<div id="btn_fs" onclick="go_FullScreen( this )" style="position: absolute;">
<img id="img_btn_fs" width="40" src="https://i.stack.imgur.com/dI5kS.png">
</div>
</div>
<div id="animatedgif_2" class="fx_fadeIn" style="position: relative; width: 100%; text-indent: 0px; padding-bottom:0em !important; ">
<video class="centrer-verticalement" width="100%" style="" muted playsinline loop autoplay>
<source src="https://www.underthedeepdeepsea.com/wp-content/uploads/videos/NUM-hobbit-1280crf.mp4" type="video/mp4"></video>
<div id="btn_fs" onclick="go_FullScreen( this )" style="position: absolute;">
<img id="img_btn_fs" width="40" src="https://i.stack.imgur.com/dI5kS.png">
</div>
</div>
CSS :
.fx_fadeIn img {
opacity: 00%;
transition: opacity 0.5s;
}
.fx_fadeIn:hover img {
opacity: 100%;
transition: opacity 1s;
}
.centrer-verticalement[style*="background: transparent"]+#btn_fs img {
opacity: 20%;
transition: opacity 0.5s;
}
.centrer-verticalement[style*="background: transparent"]+#btn_fs img:hover {
opacity: 100%;
transition: opacity 0.5s;
}
.fx_fadeIn .centrer-verticalement[class*="background: none"]+#btn_fs img {
opacity: 0%;
transition: opacity 0.5s;
}
.fx_fadeIn:hover .centrer-verticalement[style*="background: none"]+#btn_fs img {
opacity: 100%;
transition: opacity 1s;
}
#btn_fs {
bottom: 1em;
right: 1em;
}
Note that if you put the HTML code on wordpress, it will add a <p> after the video tag, which will need an adaptation of a part of the CSS, like that:
.centrer-verticalement[style*="background: black"]+p+#btn_fs img {
opacity: 20%;
transition: opacity 0.5s;
}
.centrer-verticalement[style*="background: black"]+p+#btn_fs img:hover {
opacity: 100%;
transition: opacity 0.5s;
}
.fx_fadeIn .centrer-verticalement[class*="background: #010101"]+p+#btn_fs img {
opacity: 0%;
transition: opacity 0.5s;
}
.fx_fadeIn:hover .centrer-verticalement[style*="background: #010101"]+p+#btn_fs img {
opacity: 100%;
transition: opacity 1s;
}
And finally, you can add this CSS code at the end of all that, if you want the fullscreen icon to always appear for smartphones and ipad :
#media only screen and (max-width: 768px) {
.fx_fadeIn img {
opacity: 20% !important
}
}
#media only screen and (hover: none) and (pointer: coarse) {
.fx_fadeIn img {
opacity: 20% !important
}
}
JAVASCRIPT (updated) :
var bool_isFullscreen = false;
//# access DIV that is container for [ video + button image ].
var myVideoGIF; //# = document.getElementById("animatedgif");
//# access DIV that is a click "hotspot" to enter fullscreen.
var myBtn_FS; //# = document.getElementById("btn_fs");
//# access IMG for button that will change mode to fullscreen.
//var img_myBtn_FS; //# = document.getElementById("img_btn_fs");
window.addEventListener('fullscreenchange', on_FS_Change, false);
function on_FS_Change(evt) {
//######################################
//# detect event for screen mode change
//#is "null" when page/element is not in Fullscreen
if (document.fullscreenElement != null) {
bool_isFullscreen = true;
}
//# assume is already in Fullscreen mode
else {
bool_isFullscreen = false;
exit_FullScreen();
}
}
function go_FullScreen(input) {
//# NOTE : child elements are in order of appearance in setup
//# Parent == DIV as container
//# children[0] == VIDEO tag is first child element
//# children[1] == DIV for button icon is second child element
//##############################################################
//## Get access to the specific clicked item's Parent (container)
myVideoGIF = document.getElementById(input.parentNode.id);
myBtn_FS = myVideoGIF.children[1];
//########################################
//## Check if screen mode is : Fullscreen
//## If already Fullscreen then just do the "on exit fullscreen" code
//## then quit (RETURN) from this function (ignores rest of code below)
if (bool_isFullscreen == true) {
exit_FullScreen(); //# handle on exit fullscreen
return; //# quit/exit code here...
}
//##############################################################
//## Will continue onto code below if NOT Fullscreen (no return)
function openFullscreen(elem) {
//# for most browsers
if (elem.requestFullscreen) {
elem.requestFullscreen();
}
//# for Safari (older versions)
else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen();
}
//# for Safari (newer versions)
else if (elem.webkitEnterFullscreen) {
elem.webkitEnterFullscreen();
}
//# for Safari iPhone (where only the Video tag itself can be fullscreen)
else if (elem.children[0].webkitEnterFullscreen) {
elem.children[0].webkitEnterFullscreen();
//toggle_controls(); //# your own function to show/hide iOS media controls
}
//# for Internet Explorer 11
else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen();
}
}
openFullscreen(myVideoGIF);
myVideoGIF.children[0].style.width = "100%"
myVideoGIF.children[0].style.height = "100%"
myVideoGIF.children[0].style.background = "black"
//# set to true (helps "exit_FullScreen" function )
bool_isFullscreen = true;
}
var videoContainer = document.getElementByClassName('fx_fadeIn');
var video = videoContainer.getElementsByTagName('video');
function toggleVideoFullscreen() {
if (video.webkitEnterFullScreen) {
// Toggle fullscreen in Safari for iPad
video.webkitEnterFullScreen();
} else {
// Toggle fullscreen for other OS / Devices / Browsers
}
}
function exit_FullScreen() {
if (bool_isFullscreen == true) {
bool_isFullscreen = false;
//#########################################
//# check IF browser can use this method...
if (document.exitFullscreen) {
document.exitFullscreen()
.then(() => console.log("Document Exited from Full screen mode"))
.catch((err) => console.error(err));
myVideoGIF.children[0].style.background = "#010101"
}
//## OR ELSE try other browser options
/* for Safari */
else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
/* for IE11 */
else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
}
Here is the full jsfiddle: https://jsfiddle.net/TB54/keLy49z8/19/
Finally, note that those multiple videos won't autoplay on Xiaomi Mi browser, but that's another problem not related to the code.
"Usually I would resolve this by using a more classical video tag... But it's far more difficult to make appear the fullscreen button alone on it."
Update:
Here is some example code you can study, then also apply the same logic into your WordPress. (eg: put Styles/Scripts wherever these Styles/Scripts are put when creating WP articles or pages).
The code below uses an image to create a custom fullscreen button. This should work in all browsers because it is just an <img> tag inside a <div> with a "click" listener.
PS: You can download (and customize) a free fullscreen icon here: icons8.com.
(Another good site for customized PNG icons, but you cannot remove their big advert. You must scroll down by a small amount until you see the "Edit Vector" option next to the icon (is at bottom left of icon).
code example (updated 19/01/2022):
<!DOCTYPE html>
<html>
<style>
/* .fade-in-image { animation: fadeIn 4s; } */
.fx_fadeIn img
{ opacity: 30%; transition: opacity 2s; }
.fx_fadeIn:hover img
{
opacity: 100%;
transition: opacity 1s;
}
</style>
<body>
<div id="animatedgif_1" class="fx_fadeIn" style="position: relative; width: 640px; height: 360px;" >
<video width="100%" style="position: absolute; top: 0px" muted playsinline loop autoplay><source src="https://www.underthedeepdeepsea.com/wp-content/uploads/videos/NUM-Amandiers4.mp4" type="video/mp4"></video></p>
<div id="btn_fs" onclick="go_FullScreen( this )" style="position: absolute; top: 86%; left: 90%;">
<img id="img_btn_fs" width = "40" src="https://i.stack.imgur.com/dI5kS.png" >
</div>
</div>
<div id="animatedgif_2" class="fx_fadeIn" style="position: relative; width: 640px; height: 360px;" >
<video width="100%" style="position: absolute; top: 0px" muted playsinline loop autoplay><source src="https://www.underthedeepdeepsea.com/wp-content/uploads/videos/NUM-still-life.mp4" type="video/mp4"></video></p>
<div id="btn_fs" onclick="go_FullScreen( this )" style="position: absolute; top: 86%; left: 90%;">
<img id="img_btn_fs" width = "40" src="https://i.stack.imgur.com/dI5kS.png" >
</div>
</div>
<script>
var bool_isFullscreen = false;
//# access DIV that is container for [ video + button image ].
var myVideoGIF; //# = document.getElementById("animatedgif");
//# access DIV that is a click "hotspot" to enter fullscreen.
var myBtn_FS; //# = document.getElementById("btn_fs");
//# access IMG for button that will change mode to fullscreen.
//var img_myBtn_FS; //# = document.getElementById("img_btn_fs");
window.addEventListener('fullscreenchange', on_FS_Change, false);
function on_FS_Change (evt)
{
//######################################
//# detect event for screen mode change
//#is "null" when page/element is not in Fullscreen
if( document.fullscreenElement != null )
{ bool_isFullscreen = true; }
//# assume is already in Fullscreen mode
else
{ bool_isFullscreen = false; exit_FullScreen(); }
}
function go_FullScreen( input )
{
//# NOTE : child elements are in order of appearance in setup
//# Parent == DIV as container
//# children[0] == VIDEO tag is first child element
//# children[1] == DIV for button icon is second child element
//##############################################################
//## Get access to the specific clicked item's Parent (container)
myVideoGIF = document.getElementById( input.parentNode.id );
myBtn_FS = myVideoGIF.children[1];
//########################################
//## Check if screen mode is : Fullscreen
//## If already Fullscreen then just do the "on exit fullscreen" code
//## then quit (RETURN) from this function (ignores rest of code below)
if( bool_isFullscreen == true )
{
exit_FullScreen(); //# handle on exit fullscreen
return; //# quit/exit code here...
}
//##############################################################
//## Will continue onto code below if NOT Fullscreen (no return)
myVideoGIF.requestFullscreen();
//#####################
//## ALIGN -- VERTICAL
//## Need to subtract : height of screen -minus- height of video
//## Then divide result by two to get central point
//# find the new fullscreen Width of video object
//# by temporay setting to "100w" ("vw" == viewport width)
myVideoGIF.children[0].style.width = "100vw";
//# formula = ( screen Height - video Height(eg: its clientHeight) )
//# then "Divide by 2" to get the central value from total
let align_vertical = ((screen.height - myVideoGIF.children[0].clientHeight) / 2);
myVideoGIF.children[0].style.top = align_vertical+"px"; //"5%";
//# reset back to 100% width for display inside Div's width
myVideoGIF.children[0].style.width = "100%";
//# set to true (helps "exit_FullScreen" function )
bool_isFullscreen = true;
}
function exit_FullScreen( )
{
myVideoGIF.children[0].style.top = "0px";
if( bool_isFullscreen == true )
{
bool_isFullscreen = false;
//#########################################
//# check IF browser can use this method...
if (document.exitFullscreen)
{
document.exitFullscreen()
.then(() => console.log("Document Exited from Full screen mode"))
.catch((err) => console.error(err));
}
//## OR ELSE try other browser options
/* for Safari */
else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); }
/* for IE11 */
else if (document.msExitFullscreen) { document.msExitFullscreen(); }
}
}
</script>
</body>
</html>
Old Answer:
This is not a final Answer, just a "super" comment for testing advice...
(1) Try adding this <div> code:
<div class="image fullscreen-button-only">
<video muted playsinline loop autoplay>
<source src="https://www.underthedeepdeepsea.com/wp-content/uploads/videos/NUM-still-life.mp4" type="video/mp4">
</video>
</div>
The result should be your page now has two videos (your original one and then also this new Div).
I will check the page for what is happening then advise further if needed...
(2) In Chrome you can try the below code to get fullscreen button only.
Note: It won't work in Firefox because it's Gecko engine but Chrome/Edge is using Webkit engine.
Copy/Paste shown code here for a quick testing
<!DOCTYPE html>
<html>
<style>
video::-webkit-media-controls-volume-control-container,
video::-webkit-media-controls-play-button,
video::-webkit-media-controls-timeline,
video::-webkit-media-controls-current-time-display,
video::-webkit-media-controls-time-remaining-display
{ display: none; }
</style>
<body>
<video width="550" height="310" oncontextmenu="return false;"
playsinline muted autoplay loop
disablepictureinpicture
controls controlsList="nodownload noplaybackrate noremoteplayback ">
<source src="https://www.underthedeepdeepsea.com/wp-content/uploads/videos/NUM-still-life.mp4" type="video/mp4">
</video>
</body>
</html>
Does that work (shows only Fullscreen button) in Chrome on Mac?
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
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.
I'm not very experienced in cross-browser issues, but I'm having this issue:
Scenerio : Let say i have div of width:800px, in that div i have 2 buttons ( left-araow--right-arrow ), onclick on any of the button I change image position in the div ( image move right or left,but stays in outer div )
Problem : When I re-size or reduce screen resolution then my CSS gets change; the image goes out of the div, and also the position of my buttons get change as well.
Any idea or solutions? Thanks.
EDIT : It is working fine in Firefox and in Opera, but not working in Google Chrome and IE.
Below is the html:
<div class="hand">
<div id="handinside"></div>
</div>
<div id="left" class="button"> left </div>
<div class="flip"></div>
<div id="right" class="button">right</div>
</div>
below is the CSS
.gameNavigation {
width: 220px;
margin: 0px auto 0px;
}
.button {
margin: 0 0 0 5px;
cursor: pointer;
width: 59px;
height: 29px;
float: left;
text-align: center;
background-color:red;
color: white;
}
.hand {
position:relative;
background-color:transparent;
left:0px;
width:140px;
height:210px;
}
Below is the jquery
$(".button").click(function() {
var $button = $(this);
var oldValue = $("#counter").val();
if ($button.text() == "right" ) {
//move right if the value is no more than 4
if(parseInt(oldValue) < 3){
var newVal = parseInt(oldValue) + 1;
$(".hand").animate({
"left": "+=222px"
}, "slow");
$(".coin").animate({
"left": "+=222px"
}, "slow");
//$(".block").stop();
}
}
else {
// move left and don't allow the value below zero
var test = 'test'
if (oldValue >= 1) {
var newVal = parseInt(oldValue) - 1;
}
if(parseInt(newVal) >= -1){
$(".hand").animate({
"left": "-=222px",
easing :'swing'
}, "slow");
$(".coin").animate({
"left": "-=222px",
easing : 'swing'
}, "slow");
}
}
$("#counter").val(newVal);
});
position your container div with relative positioning and then position your arrows with absolute positioning
Anyone know of a way that I can get CSS to make a PNG image with transparency look completely blacked out like a silhouette?
In other words-
Going from something like this:
To this:
It's for a lot of images which is why I'd like to avoid doing it via Photoshop.
You can apply to the image style like filter: contrast(0%) brightness(50%) to get a silhouette. Do not forget prefixes.
I don't see how it could be done with pure css. Javascript might be able to acheive it but you may consider using server side programming instead. With php you could make a duplicate of your original png on the server and replace the non-transparent pixels with a single color. It would be similar to a watermarking function.
I tried this code that uses a canvas, maybe you could refine it especially on lighter pixel inside the apple
<img id="canvasSource" src="apple.jpg" />
<br />
<canvas id="area" width="264" height="282"></canvas>
<!-- Javascript Code -->
<script type="text/javascript">
window.onload = function() {
var canvas = document.getElementById("area");
var context = canvas.getContext("2d");
var image = document.getElementById("canvasSource");
context.drawImage(image, 0, 0);
var imgd = context.getImageData(0, 0, 264, 282);
var pix = imgd.data;
var blackpixel = 21;
for (var i = 0, n = pix.length; i < n; i += 4) {
//console.log(pix[i], pix[i+1], pix[i+2]);
if (i > 3) {
if ((Math.abs(pix[i-3] - pix[i]) > 10) &&
(Math.abs(pix[i-2] - pix[i+1]) > 10) &&
(Math.abs(pix[i-1] - pix[i+2]) > 10)
) {
pix[i ] = blackpixel;
pix[i+1] = blackpixel;
pix[i+2] = blackpixel;
}
}
else {
if (pix[i] < 250 && pix[i+1] < 250 && pix[i+2] < 250) {
pix[i ] = blackpixel;
pix[i+1] = blackpixel;
pix[i+2] = blackpixel;
}
}
}
context.putImageData(imgd, 0, 0);
};
</script>
Nowdays, filter combined to mix-blend-mode could do too :
span {/* to be used to lay the 'blender mask' over img */
position: relative;
display: inline-block;
overflow:hidden;
}
span img {
display: block;/* erase gap */
max-width:45vw;
filter: contrast(150%);
}
span + span img {
filter: contrast(120%) saturate(0%);/* saturate(0%) is similar to grayscale(100%) */
}
span:before {
content: '';
z-index: 1;
height: 100%;
background: white;
position: absolute;
top: 0;
width: 100%;
display: block;
filter: contrast(10000%) brightness(0) saturate(100%) grayscale(100%);
mix-blend-mode: color-burn;/* bake it to black */
animation : span 2s infinite alternate;
}
#keyframes span {
from{
transform:translate(-100%,0)
}
25%,50% {
transform:translate(0,0);
}
to{
transform:translate(100%,0)
}
}
<span><img src="https://i.stack.imgur.com/somZ7.jpg"/></span>
<span><img src="https://i.stack.imgur.com/somZ7.jpg"/></span>