I have a script which generates a random number so that when setImg(); is called a randomly selected image appears:
<img src="" id="imgRand" alt="">
function setImg(){
var numRand = Math.floor(Math.random()*(6 - 1 + 1)) + 1;
document.getElementById("imgRand").src = "images/"+numRand+".jpg";
}
This all works fine, but when the image changes, it just 'appears'. I was wondering if there was any way to get it to fade from one to the other? Everything I've found online talks about setting styles on each individual image, but as Im using this random number script to source my images, I cant think of a way to adapt any of those solutions.
Any help is much appreciated, thanks!
I will provide you with an example using CSS3 transitions. You can adapt and improve it for your specific case.
My specific example works only with Webkit as it is written since the implementation of the transcription end callback is vendor dependent. You can fix this by using the correct vendor event handler names.
/* Fades an element to given opacity */
var fade = function(opacity, fn) {
this.addEventListener("webkitTransitionEnd", function end() {
this.removeEventListener("webkitTransitionEnd", end);
fn && fn.call(this);
}, false);
this.style.opacity = opacity;
};
/* Preloads an image */
var load = function(src, fn) {
var self = this, $img = new Image();
$img.onload = function() {
fn && fn.call(self);
};
$img.src = src;
};
/* Steps:
* 1. Fades out current image.
* 2. Preloads next image.
* 3. When loading of next image is complete, sets next image.
* 4. Fades in.
*/
var $img = document.getElementById("imgRand");
/* Fades out */
fade.call($img, 0, function() {
/* Get random dimensions */
var height = Math.ceil(Math.random() * 100) + 100;
var width = Math.ceil(Math.random() * 200) + 100;
var src = "http://placehold.it/" + width + "x" + height;
/* Preloading */
load.call(this, src, function() {
$img.setAttribute("src", src);
/* Fades in */
fade.call($img, 1);
});
});
You can see it here.
The img element has -webkit-transition-duration style property set to 1s.
The most complicated and overlooked part of this is image preloading. Because, unless you preload all images that you want to use, the animation won't be smooth. But at the same time the detection of when an image has been loaded is not an easy task and the method that I'm using is a naive one that most probably will fail for images in the browser's cache. I won't go into details about that, you can search SO for it.
Disclaimer: It is too freaking late. So, I will just dump the code here and come to it later. If there's doubts.
This can be done most easily using a library such as jQuery but here is a jsFiddle example. I use absolute positioning to have two images placed over the top of each other and give one of them an opacity of 0. Then I just toggle between the two and fade one in and one out using helper functions.
The html looks something like this:
<div id="imageHolder">
<img id="imgRand0" src="http://placehold.it/100x100" />
<img id="imgRand1" src="http://placehold.it/100x100" style="opacity:0;alpha(opacity:0);"/>
</div>
<button onclick="setImg()">New Image</button>
The CSS:
img {
position:absolute;
top:0;
left:0;
}
#imageHolder {
position:relative;
height:100px;
}
And the javascript (I use additional functions from this tutorial):
var counter = 0;
function setImg(){
var numRand = Math.floor(Math.random()*6) + 1;
//document.getElementById("imgRand").src = "images/"+numRand+".jpg";
counter = (counter + 1) % 2;
document.getElementById("imgRand" + counter).src = "http://placehold.it/100&text=" + numRand;
fade('imgRand0');
fade('imgRand1');
}
This was too long to put into a comment, but hopefully it will guide you in the right direction.
So, because you're replacing the src of imgRand with each call to setImg, the two images you're trying to cross-fade will not be present in the DOM at the same time. You will probably need to have two separate image tags that are stacked on top of each other with CSS.
Then you will need to set the src on the top image (the one you want to fade in) and hide this image with CSS or your image will just 'appear' as soon as you set the src.
Then you will want to fade the top image in incrementally by setting the opacity of the image until it's 100...
Sorry for such a crazy description, but it's probably far easier if you have jQuery available. I will go and hunt down an example and update this.
Update: If you have jQuery, this is a rudimentary example of what your script might look like: http://jsfiddle.net/tracyfu/W9wMh/ Some of the other solutions here might be better if you're confined to straight JS.
Related
I`m using the code to change background picture over time:
function getRandomInt(min, max)
{return Math.floor(Math.random()*(max-min+1))+min;}
function nextBackground()
{
var url = "url('images/" + getRandomInt(1, 33) + ".jpg')";
$body.css("background-image", url);
setTimeout(nextBackground, 7000);
}
setTimeout(nextBackground, 7000);
But I would like pictures to change not that sharply. Are there any way to do that?
If you use timing events with two overlaid images and have the opacity adjust slowly from 1 to 0, that should work for you I think.
This may be useful.
You could use CSS animationns with an animatable property... but this one isn't. The answers to this question should help you solve your problem, basically you should put your image behind the other one and turn the opacity of the old one up to 100% smoothly.
Hope it helped :)
You can fade the next image in by transitioning the property. Here's an example stripped down to the basics that does it on the background of a <div>, but you can change it to the background of the document, simply by changing the selector used in the nextBackground() function.
// If you put all the image paths into an array, the rest of the code gets much simpler
var images = ["https://images.seeklogo.net/2016/09/facebook-icon-preview-1.png",
"https://www.brandsoftheworld.com/sites/default/files/styles/logo-thumbnail/public/062012/twitter-bird-light-bgs.png?itok=HAQz1yQN",
"http://seeklogo.com/images/L/linkedin-icon-logo-05B2880899-seeklogo.com.gif",
"https://www.youtube.com/yt/brand/media/image/YouTube-logo-full_color.png",
"http://3835642c2693476aa717-d4b78efce91b9730bcca725cf9bb0b37.r51.cf1.rackcdn.com/Instagram_App_Large_May2016_200.png",
"http://lescalier-montreal.com/restaurant-bar/wp-content/uploads/2014/07/small-red-googleplus-icon.png"];
function getRandomInt() {
// No longer need min and max parameters, just the length of the array
return Math.floor(Math.random() * images.length);
}
function nextBackground(){
$("div").css("background-image", "url(" + images[getRandomInt()] + ")");
}
// For a continuously running timer, user setInterval, instead of setTimeout
setInterval(nextBackground, 1250);
div {
background-size:contain;
/*
CSS transitions cause properties that change to transition to the new value
There are numererous ways to configure the transition, but here, we're just
saying that any properties that change on the div should take 1 second to transition
from the old value to the new value.
*/
transition:1s;
height:250px;
width:250px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
I need to add a Transparent image on top of all images on a page. The goal is if a user were to do a simple right click and save of an image, they would save the transparent image.
I do realize this is not a guaranteed method and that none exist to prevent image theft but simply a measure that a client wants added to prevent your average non tech person from saving images.
Using JavaScript I would like to find all images or all images within a certain Div.
Apply a new image overlay on top of these images that will have the same width and height of the image they are covering
I am not sure how to do this with JavaScript and was hoping someone would have a quick fix or example. I was unable to find anything so far on Google or SO. Appreciate any help
I have this JS which gets all images on a page so far...
// Get all images on a Page
function checkimages() {
var images = document.images;
for (var i=0; i<images.length; i++){
var img =images[i].src;
// Add new transparent image on top of this image
alert(img);
}
}
I would advise you to work with jQuery (or similar library) to keep things easier. I would even write a small jquery extension to make it easy to recycle the code, and apply it on any div (or other wrapper), wich child images you want to be overlayed.
My code would look something like this:
// jquery plugin to create overlays
// src is the url of the overlay image
// apply to any container that contains images to be overlayed
$.fn.overlayImages = function(src) {
// loop trough the images
$(this).find('img').each(function() {
// cache some variables
var $img = $(this);
var $parent = $img.parent();
// make the parent relative, if not yet absolute or fixed, for easy positioning
if ($parent.css('position') !== 'fixed' && $parent.css('position') !== 'absolute') {
$parent.css('position', 'relative');
}
// get the position of the image
var position = $img.position();
// clone the image
var $overlay = $img.clone();
// set the styling, based on the img, for exact positioning
$overlay.css({
top: position.top,
left: position.left,
position: 'absolute',
width: $img.width(),
height: $img.height()
});
// change the src attribute for the overlay
$overlay.attr('src', src);
// insert the overlay to the DOM
$overlay.insertAfter($img);
});
}
// when the DOM is loaded (not just ready, the images need to be there to copy their position and size)
$(window).load(function() {
// apply the overlay plugin to the wrapper of the images
$('#replace-images').overlayImages("http://www.riptideinnovations.com/images/watermark.png");
});
I added the step by step explanation inside the code as comments, but do feel free to ask if you want any further explanation.
I set up a small fiddle to demonstrate: http://jsfiddle.net/pP96f/6/
I don't know if this would help, but you could make your images all div's with backgrounds like this:
<div style="background-image: url('<your_image>');"></div>
I have an Html/JavaScript application that contains N columns that need to be large enough contain all of the possible LI elements from all of the columns.
The simple solution seems to count the heights of all of the items in each column, compensate for padding, and then set the height to that total for each of the columns.
This works great when the LI elements contain plain text. Unfortunately, when the LI elements contain images instead, various browsers have problems. For example, when I first load the page in FireFox, it looks like the screenshot below, but upon another refresh, it works fine. It doesn't work as expected in Chrome either.
My application does not pre-populate the LI elements when the page loads - it uses JavaScript, as follows:
function populateUnsetAnswers(unsetCategoryAnswers) {
for (i in unsetCategoryAnswers) {
if (unsetCategoryAnswers.hasOwnProperty(i.toString())) {
$('#categoryQuestionArea #possibleAnswers').append(
categoryAnswerLiTag(unsetCategoryAnswers[i])
);
}
}
}
function categoryAnswerLiTag(unsetCategoryAnswer) {
var html = '<li id="' + unsetCategoryAnswer.id + '">';
if (unsetCategoryAnswer.image) {
html += '<img class="categoryAnswerImage" title="';
html += unsetCategoryAnswer.text;
html += '" src="/trainingdividend/rest/streaming/';
html += unsetCategoryAnswer.image.fileName;
html += '" style="height: ';
html += unsetCategoryAnswer.image.height;
html += ';';
html += '" />';
} else {
html += unsetCategoryAnswer.text
}
html += '</li>';
return html;
}
When the page is done loading, an ajax request fetches all of the objects to be put into LI elements, and then calls the first function above.
After all of the LI elements are created, I call this function right after it:
function resize() {
var currentHeight, totalHeight;
totalHeight = 0;
$("#categoryQuestionArea ul").children().each(function() {
currentHeight = $(this).height();
totalHeight += currentHeight + 13;
});
$("#categoryQuestionArea ul").height(totalHeight);
$("#categoryQuestionArea div#separator").css("padding-top", (totalHeight / 2) + "px");
}
Is there any way to tell jQuery, "Don't call resize() until all of the LI's are fully loaded and the images have rendered" ?
I think what's happening is that on the initial page load, the height of these LI elements is 0 or a small value because it doesn't contain the image, so my resize function is calculating the wrong result (I tested this with some alert statements). As long as the LIs are populated and the images have loaded, the total height is calculated just fine.
Any help? Thanks
To literally answer the question you asked, if you want to only call resize() when all images have finished loading, then you need to install onload handlers for those images and when you've recorded that the last one is now loaded, you can call the resize() function. You could do that like this (code explanation below):
var remainingAnswerImages = 0;
function categoryAnswerImageLoadHandler() {
--remainingAnswerImages;
if (remainingAnswerImages === 0) {
resize();
}
}
function populateUnsetAnswers(unsetCategoryAnswers) {
// add one extra to the image count so we won't have any chance
// at getting to zero before loading all the images
++remainingAnswerImages;
var possibleAnswers$ = $('#categoryQuestionArea #possibleAnswers');
for (i in unsetCategoryAnswers) {
if (unsetCategoryAnswers.hasOwnProperty(i.toString())) {
possibleAnswers$.append(categoryAnswerLiTag(unsetCategoryAnswers[i]));
}
}
// remove the one extra
--remainingAnswerImages;
// if we hit zero on the count, then there either were no images
// or all of them loaded immediately from the cache
// if the count isn't zero here, then the
// categoryAnswerImageLoadHandler() function will detect when it does hit zero
if (remainingAnswerImages === 0) {
resize();
}
}
function categoryAnswerLiTag(unsetCategoryAnswer) {
var obj = document.createElement("li");
obj.id = unsetCategoryAnswer.id;
if (unsetCategoryAnswer.image) {
// count this image
++remainingAnswerImages;
var img = new Image();
img.onload = img.onerror = img.onabort = categoryAnswerImageLoadHandler;
img.title = unsetCategoryAnswer.text;
img.style.height = unsetCategoryAnswer.image.height;
img.src = "/trainingdividend/rest/streaming/" + unsetCategoryAnswer.image.fileName;
obj.appendChild(img);
} else {
obj.innerHTML = unsetCategoryAnswer.text;
}
return obj;
}
By way of explanation, this code makes the following changes:
Add a variable remainingAnswerImages to keep track of how many images still need to be loaded.
Add an onload handler for each <img> tag that is created so we can keep track of when it's loaded.
Each time we generate the HTML for an tag with the onload handler, increment remainingAnswerImages.
When you're done adding all the HTML, check the remainingAnswerImages count to see if it's zero (this would only be the case if there were no images or if all images loaded immediately from the browser cache). If so, call resize() immediately.
In the onload handler which will be called for each image, decrement remainingAnswerImages and if the count has reached zero, call resize().
While adding images, add one extra to remainingAnswerImages as a gate to keep from getting to a zero count until we're done adding images. When done adding images, take that one extra out.
I also rewrote the categoryAnswerLiTag() function to just create the DOM objects directly rather than concat a bunch of strings together into HTML. In this case, the code is a lot cleaner to read and maintain.
I also moved the $('#categoryQuestionArea #possibleAnswers') out of your for loop since it resolves to the same thing every time. Better to do it once before the loop. Also, in most cases, this could be simplified to $('#possibleAnswers') since ids are supposed to be unique in the page.
Here is a jquery plugin that checks the images have loaded: https://github.com/alexanderdickson/waitForImages
Sample usage for your case would be:
$('#categoryQuestionArea').waitForImages(function() {
resize();
});
I would also just check for the total height of the <ul> instead of looping through the list items as you would have to manually change the script if either the padding, margins, or borders on the list items changes later on.
If you do have problems with images on the first page load maybe it is due to the fact that they are not cached and therefore not immediately available. So measuring their height will lead to bad results... did you debug the height that was fetched via jQuery (for example
currentHeight = $(this).height();
console.log(currentHeight);
The only way to do that is I think to observe the load events of all images (and probably the error as well) and count whether all request have been finished
try using
$('img').load(function(){
//put code here
});
I guess your HTML is screwed up. Particularly, your <img> tags.
Add the width and height attributes to your <img> tags. Everything will be magically solved.
See this jsfiddle to understand what I mean: http://jsfiddle.net/Ralt/Vwg7P/
Even though there is no image in there, the width and height attributes will occupy the space required for the image. As soon as the DOM is loaded.
This is rather a CSS problem, most probably due a fixed height, with items either floated or absolutely positioned.
There are number of ways to fix this.
Give a min-height instead of fixing a height.
#container { min-height: 100px; }
Clear the float and do not set any heights
#container { overflow: hidden; }
Use Scripts to add up to the height, once every element is added. Like the jQuery snippet below
$("#container").append($("#theimg"));
$("#container").height($("#container").height()+$("#theimg").height());
I think I might have a solution for you.
The main idea of my solution lies in CSS. You want to have 3 columns of the same height, right? You can have something like this: http://jsfiddle.net/agilius/NvzZp/46/
There is quite a lot of CSS there, but the main idea is this:
I simulate a 3 column layout under the actual content, with the .inner and .column classes.
The content is placed over (via z-index 2 > .inner zindex 1), with the same width as the columns that are under.
When content is added to the content zones, the height of the main #container updates.
Since .inner is top,left,right,bottom = 0, it updates, and since the .columns have 100% height, they update their height to match the #containers height.
Observations.
You can have padding, borders, margins in the .column class as you see fit.
No javascript is required.
Another simple Equal Height CSS solution:
LOGIC is very simple -
all of the columns/LI are floated
with .eH{ padding-bottom: X; margin-bottom: -X } and
wrapper/UL is .eW{overflow: hidden}
X= large arbitrary amount of px for factor of safety
EXAMPLE:
http://jsfiddle.net/rahen/TXVYD/4/
This sounds exactly like one of the problems i had when coding SudoSlider.
Below i've copied the code i solved it with. Just call autoheightwidth(i, 0, true) inside your resize() function.
The basic idea is that you do not know when the browser has completed loading the images, so instead of relying on a single height adjustment, you adjust the height every time something happens (mostly just that an image has been loaded).
It should work if you change the references of "obj" and "li" in the first 2 methods.
It's not very readable, but there was a big focus on size when i coded it.
// Automaticly adjust the height and width, i love this function.
// Before i had one function for adjusting height, and one for width.
function autoheightwidth(i, speed, axis) // Axis: true == height, false == width.
{
obj.ready(function() {// Not using .load(), because that only triggers when something is loaded.
adjustHeightWidth (i, speed, axis);
// Then i run it again after the images has been loaded. (If any)
// I know everything should be loaded, but just in case.
runOnImagesLoaded (li.eq(i), falsev, function(){
adjustHeightWidth (i, speed, axis);
});
});
};
function adjustHeightWidth (i, speed, axis)
{
var i = getRealPos(i); // I assume that the continuous clones, and the original element is the same height. So i allways adjust acording to the original element.
var target = li.eq(i);
// First i run it. In case there are no images to be loaded.
var b = target[axis ? "height" : "width"]();
obj.animate(
axis ? {height : b} : {width : b},
{
queue:falsev,
duration:speed,
easing:option[8]/*ease*/
}
);
}
function runOnImagesLoaded (target, allSlides, callback) // This function have to be rock stable, cause i use it ALL the time!
{
var elems = target.add(target.find('img')).filter('img');
var len = elems.length;
if (!len)
{
callback();
// No need to do anything else.
return this;
}
function loadFunction(that)
{
$(that).unbind('load').unbind('error');
// Webkit/Chrome (not sure) fix.
if (that.naturalHeight && !that.clientHeight)
{
$(that).height(that.naturalHeight).width(that.naturalWidth);
}
if (allSlides)
{
len--;
if (len == 0)
{
callback();
}
}
else
{
callback();
}
}
elems.each(function(){
var that = this;
$(that).load(function () {
loadFunction(that);
}).error(function () {
loadFunction(that);
});
/*
* Start ugly working IE fix.
*/
if (that.readyState == "complete")
{
$(that).trigger("load");
}
else if (that.readyState)
{
// Sometimes IE doesn't fire the readystatechange, even though the readystate has been changed to complete. AARRGHH!! I HATE IE, I HATE IT, I HATE IE!
that.src = that.src; // Do not ask me why this works, ask the IE team!
}
/*
* End ugly working IE fix.
*/
else if (that.complete)
{
$(that).trigger("load");
}
else if (that.complete === undefined)
{
var src = that.src;
// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
// data uri bypasses webkit log warning (thx doug jones)
that.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; // This is about the smallest image you can make.
that.src = src;
}
});
}
I think the Browser does not know the images' dimensions, because they are not loaded.
Either try to wrap the invocation of resize in a
jQuery(document).load( function funcName() {
...
} )
or give the image width and height attributes in the HTML img tags.
Maybe both
I want a simple image crossfade, similar to http://malsup.com/jquery/cycle/, but with a pre-loader. Is there a good jQuery plugin that does both? Also, I'm not looking for a load bar.
This question is close, but not the same => jQuery Crossfade Plugin
It would be great if it was a solution that defaulted to CSS3, but would otherwise fall back to JS to keep the processing native as possible.
Looking for something that..
will autoplay
without controls
will go to the next image based on time setting, ie. 5 seconds, unless the next image isn't loaded in which case it finishes loading the image and then displays it.
crossfade transition, not fade to black or white, but cross-fade. from the start it would fadein.
no thumbnails or galleries, etc. just the image
If images could be CSS background images, that would be best, so users can't drag out the image simply
Each panel needs to be clickable so a user could click the image and go to a part of the website.
Well, here's my poke at it. The preloader is in vanilla js and the slideshow loop is in jQuery. It's very simple to implement and the concept is even simpler.
Demo
a very simple Demo that illustrates the DOM manipulation approach
HTML
<!-- not much here... just a container -->
<div id="content"></div>
CSS
/* just the important stuff here. The demo has example styling. */
#content
{
position:relative;
}
#content img
{
position:absolute;
}
javascript/jQuery
// simple array
var images = [
"http://imaging.nikon.com/lineup/dslr/d90/img/sample/pic_003t.jpg",
"http://imaging.nikon.com/lineup/dslr/d90/img/sample/pic_005t.jpg",
"http://imaging.nikon.com/lineup/dslr/d90/img/sample/pic_001t.jpg"
];
// some adjustable variables
var delay = 2000;
var transition = 1000;
// the preloader
for(var i in images)
{
var img = document.createElement("img");
img.src = images[i];
img.onload = function(){
var parent = document.getElementById("content");
parent.insertBefore(this,parent.childNodes[0]);
if(i == images.length - 1)
{
i = 0;
startSlides();
}
}
}
// and the actual loop
function startSlides()
{
$("#content img:last").delay(delay).fadeTo(transition,0,function(){
$(this).insertBefore($(this).siblings(":first")).fadeTo(0,1);
startSlides();
});
}
The concept in brief is to fade the first image in a container, once complete change it's position in the DOM (effectively hiding it behind equal tree level siblings), and call the function again. The reason why this works is because it only fades the first child of the container, but on callback it changes what node that is constantly looping the nodes. This makes for a very small source file that is quite effective.
EDIT 1:
and 32 minutes tweaking later...
Demo 2
EDIT 2:
My oh so simple script is now very complicated :P I added in some scaling features that only work on modern browsers but are there if needed. This one also has a loading bar as it preloads the images (may or may not be desirable :P)
small images demo
large images demo
I think you can still do this with the jQuery cycle plugin; other than image preloading, even the jQuery cycle lite version does everything you want by default out-of-the-box.
And if you look here, you'll see that it's pretty simple to add a little Javascript that will add images (after the first two) as they load. You would need to modify the code a little (instead of stack.push(this), you'd want something like stack.push("<div style="background-image:url("+img.src+")"></div>"), for example) but I think it's totally doable.
Edit: here's a link to a SO question about how to make a div into a clickable link.
Edit 2: I liked Joseph's idea to just move the elements to a hidden DIV, so I updated my code a bit. It now also preserves the links each div points to as well: http://jsfiddle.net/g4Hmh/9/
Edit 3: Last update! http://jsfiddle.net/g4Hmh/12/
UPDATE Added the ability to load everything asynchronously.
A wrapper for the jQuery cycle plugin should suffice. You really just need something that monitors if the images loaded and then calls $(elem).cycle(/* options */). Here's my take:
$.fn.cycleWhenLoaded = function(options) {
var target = this,
images = options.images,
loaded = 0,
total = 0,
i;
if(images) {
for(i = 0; i < images.length; i ++) {
$('<img/>').attr('src', images[i]).appendTo(target);
}
}
this.find('> img').each(function(index) {
var img = new Image(),
source = this;
total ++;
if(index > 1)
$(this).hide();
img.onload = function() {
loaded ++;
if(loaded == total) {
target.trigger('preloadcomplete');
target.cycle(options);
}
};
setTimeout(function() {img.src = source.src}, 1);
});
return this;
};
This allows you to either do a simple delay load:
$('.slideshow').cycleWhenLoaded({
fx: 'fade'
});
Or you can do something more complicated and load your images in the script and capture the preload complete event:
$('.slideshow2').hide().cycleWhenLoaded({
fx: 'fade',
images: [
"http://cloud.github.com/downloads/malsup/cycle/beach1.jpg",
"http://cloud.github.com/downloads/malsup/cycle/beach2.jpg",
"http://cloud.github.com/downloads/malsup/cycle/beach3.jpg",
"http://cloud.github.com/downloads/malsup/cycle/beach4.jpg",
"http://cloud.github.com/downloads/malsup/cycle/beach5.jpg"
]
}).bind('preloadcomplete', function() { $(this).show(); });
You can see it in action here: http://fiddle.jshell.net/vmAEW/1/
I don't know how close this is to what you are looking for, but I figured since no one else did I would at least try to help. http://galleria.aino.se/
It at least has a preloader and a fade transition.
Are there any documents/tutorials on how to clip or cut a large image so that the user only sees a small portion of this image? Let's say the source image is 10 frames of animation, stacked end-on-end so that it's really wide. What could I do with Javascript to only display 1 arbitrary frame of animation at a time?
I've looked into this "CSS Spriting" technique but I don't think I can use that here. The source image is produced dynamically from the server; I won't know the total length, or the size of each frame, until it comes back from the server. I'm hoping that I can do something like:
var image = getElementByID('some-id');
image.src = pathToReallyLongImage;
// Any way to do this?!
image.width = cellWidth;
image.offset = cellWidth * imageNumber;
This can be done by enclosing your image in a "viewport" div. Set a width and height on the div (according to your needs), then set position: relative and overflow: hidden on it. Absolutely position your image inside of it and change the position to change which portions are displayed.
To display a 30x40 section of an image starting at (10,20):
<style type="text/css">
div.viewport {
overflow: hidden;
position: relative;
}
img.clipped {
display: block;
position: absolute;
}
</style>
<script type="text/javascript">
function setViewport(img, x, y, width, height) {
img.style.left = "-" + x + "px";
img.style.top = "-" + y + "px";
if (width !== undefined) {
img.parentNode.style.width = width + "px";
img.parentNode.style.height = height + "px";
}
}
setViewport(document.getElementsByTagName("img")[0], 10, 20, 30, 40);
</script>
<div class="viewport">
<img class="clipped" src="/images/clipped.png" alt="Clipped image"/>
</div>
The common CSS properties are associated with classes so that you can have multiple viewports / clipped images on your page. The setViewport(…) function can be called at any time to change what part of the image is displayed.
In answer to :
Alas, JavaScript simply isn't capable of extracting the properties of the image you'd require to do something like this. However, there may be salvation in the form of the HTML element combined with a bit of server-side scripting.
...
< ? (open php)
$large_image = 'path/to/large_image';
$full_w = imagesx($large_image);
$full_h = imagesy($large_image);
(close php) ? >
This can be done in Javascript, just google a bit :
var newimage = new Image();
newimage.src = document.getElementById('background').src;
var height = newimage.height;
var width = newimage.width;
This generates a new image from an existing one and captures this way in java script the original height and width properties of the original image (not the one id'ed as background.
In answer to :
The width/height properties of the document's image object are read only. If you could change them, however, you would only squish the frames, not cut the frames up like you desire. The kind of image manipulation you want can not be done with client-side javascript. I suggest cutting the images up on the server, or overlay a div on the image to hide the parts you do not wish to display.
...
var newimage = new Image();
newimage.src = document.getElementById('background').src;
var height = newimage.height;
var width = newimage.width;
newimage.style.height = '200px';
newimage.style.width = '200px';
newimage.height = '200px';
newimage.width = '200px';
and if wanted :
newimage.setAttribute('height','200px');
The doubled newimage.style.height and newimage.height is needed in certain circumstances in order to make sure that a IE will understand in time that the image is resized (you are going to render the thing immediately after, and the internal IE processing is too slow for that.)
Thanks for the above script I altered and implemented on http://morethanvoice.net/m1/reader13.php (right click menu... mouseover zoom lent) correct even in IE , but as you will notice the on mousemove image processing is too fast for the old styled IE, renders the position but only once the image. In any case any good idea is welcome.
Thanks to all for your attention, hope that the above codes can help someone...
Claudio Klemp
http://morethanvoice.net/m1/reader13.php
CSS also defines a style for clipping. See the clip property in the CSS specs.
The width/height properties of the document's image object are read only. If you could change them, however, you would only squish the frames, not cut the frames up like you desire. The kind of image manipulation you want can not be done with client-side javascript. I suggest cutting the images up on the server, or overlay a div on the image to hide the parts you do not wish to display.
What spriting does is essentially position a absolutely-positioned DIV inside another DIV that has overflow:hidden. You can do the same, all you need to do is resize the outer DIV depending on the size of each frame of the larger image. You can do that in code easily.
You can just set the inner DIV's style:
left: (your x-position = 0 or a negative integer * frame width)px
Most JavaScript Frameworks make this quite easy.
Alas, JavaScript simply isn't capable of extracting the properties of the image you'd require to do something like this. However, there may be salvation in the form of the HTML <canvas> element combined with a bit of server-side scripting.
PHP code to go about extracting the width and height of the really large image:
<?php
$large_image = 'path/to/large_image';
$full_w = imagesx($large_image);
$full_h = imagesy($large_image);
?>
From here, you'd then load the image into a <canvas> element, an example of which is documented here. Now, my theory was that you may be able to extract pixel data from a <canvas> element; assuming that you can, you would simply make sure to have some form of definite divider between the frames of the large image and then search for it within the canvas. Let's say you found the divider 110 pixels from the left of the image; you would then know that each "frame" was 110 pixels wide, and you've already got the full width stored in a PHP variable, so deciphering how much image you're working with would be a breeze.
The only speculative aspect to this method is whether or not JavaScript is capable of extracting color data from a specified location within an image loaded into a <canvas> element; if this is possible, then what you're trying to accomplish is entirely feasible.
I suppose you want to take a thumbnail for your image. You can use ImageThumbnail.js that created from prototype library in this way:
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript" src="ImageThumbnail.js"></script>
<input type="file" id="photo">
<img src="empty.gif" id="thumbnail" width="80" height="0">
<script type="text/javascript">
<!--
new Image.Thumbnail('thumbnail', 'photo');
//-->
</script>
for more information
try use haxcv library haxcv js by simple functions
go to https://docs.haxcv.org/Methods/cutImage to read more about his library
var Pixels = _("img").cutImage (x , y , width , height );
_("img").src (Pixels.src);
// return cut image
but try to include library first