我遇到了一个简单的问题。假设我的用户通过一个简单的<img data-image='1' src="myimg1.jpg">
<img data-image=2' src="myimg2.jpg">
等等来加载大约150张图片
当用户将鼠标悬停在其中一个图像上时。我希望在屏幕底部的小菜单中显示此myimg-thisimage.jpg
。截至目前,我将菜单中的src属性更改为:
$('#info-poster').attr("src","myimage-thisimage.jpg");
注意: myimage-thisimage.jpg
是当前悬停在图片上方。
但是,当我这样做的时候。浏览器正在重新加载图像(因为,有一个小的延迟)。是否有任何方法可以绕过此加载,因为用户已经使用克隆DOM元素的巧妙方式加载了图像?
PS:启用浏览器图片缓存。因此,缓存不是问题。
编辑:我知道一种方法是创建300个图像元素并隐藏其他150个图像元素。但在一个场景(绝对可能)中,有近500张图像,我将不得不创建大约1000个DOM元素,这将是一个很大的性能问题。
答案 0 :(得分:6)
您可以使用画布元素来显示缩略图,这样就可以复制图像并在本地缩放 。在下面的片段中我添加了两个画布,在第一个画面中缩放图像同时保持宽高比(我需要时使用Letterboxing和Pillarboxing技术);在第二个图像被拉伸。我还在底部添加了另一个被忽略的图像,因为它没有data-image属性。
重要的是不要使用drawImage的缩放算法,因为当你大量减少图像时会产生不平滑的结果。要实现此目的,请设置画布的逻辑大小以匹配图像的自然大小。然后通过调用drawImage方法将图像复制到画布。最后将画布的显示大小设置为所需的大小。这样浏览器就可以使用更好的算法来缩放图像。
以下是 drawImage()方法的 specification 的一些优秀引文:
如果原始图像数据是位图图像,则通过过滤原始图像数据来计算在目标矩形中的点处绘制的值。
用户代理可以使用任何过滤算法(例如双线性插值或最近邻居)。
function initCanvas(id,image,naturalWidth,naturalHeight){
var canvas = document.getElementById(id);
var ctx = canvas.getContext("2d");
// Set the logical size of the canvas to match the
// natural size of the image, this way we don't use
// the scaling algorithm of drawImage (It isn't good
// for reducing big images as it produces unsmooth results).
$(canvas).attr("width",naturalWidth) ;
$(canvas).attr("height",naturalHeight) ;
// Copy the image:
ctx.drawImage(image,0,0,naturalWidth,naturalHeight);
return canvas ;
}
function clearCanvas(id){
var canvas = document.getElementById(id);
var ctx = canvas.getContext("2d");
ctx.clearRect(0,0,canvas.width,canvas.height);
}
$(window).on("load", function( ){
var images = $("img").filter(function(){
var dataImage = $(this).data("image") ;
if( typeof dataImage != "number" ) return false ;
var number = parseInt(dataImage,10) ;
return number > 0 && dataImage === number ;
}) ;
images.on("mouseenter", function( ){
var naturalWidth = $(this).prop("naturalWidth") ;
var naturalHeight = $(this).prop("naturalHeight") ;
// Scaled thumbnail:
// Copy the image to canvas-scaled and get a reference to it:
var scaledCanvas = initCanvas("canvas-scaled",this,naturalWidth,naturalHeight);
// Calculate the display size of the canvas:
var hwfactor = naturalHeight/naturalWidth ;
var whfactor = naturalWidth/naturalHeight ;
var scaledWidth, scaledHeight ;
if( hwfactor >= 1 ){ // Pillarboxing
scaledHeight = "100px" ;
scaledWidth = (100*whfactor)+"px" ;
}
else{ // Letterboxing
scaledWidth = "100px" ;
scaledHeight = (100*hwfactor)+"px" ;
}
// Now we change the display size of the canvas.
// A better scaling algorithm will be used.
$(scaledCanvas).css("width",scaledWidth);
$(scaledCanvas).css("height",scaledHeight);
// Stretched thumbnail:
// Copy the image to canvas-stretched. The display size
// of canvas-stretched is already set in the style section.
initCanvas("canvas-stretched",this,naturalWidth,naturalHeight);
});
images.on("mouseleave", function( ){
clearCanvas("canvas-scaled");
clearCanvas("canvas-stretched");
});
});
body{
background: #000;
}
.wrapper img{
width: 100px ;
height: auto ;
}
#banner{
display: block ;
width: 100% ;
height: 40px ;
padding-top: 1pt ;
}
#canvas-stretched{
width: 100px ;
height: 100px ;
}
.canvas-wrapper{
display: -webkit-inline-flex ;
display: inline-flex ;
-webkit-justify-content: space-around ;
justify-content: space-around ;
-webkit-align-items: center ;
align-items: center ;
vertical-align: bottom ;
border: 1px solid #888 ;
width: 100px ;
height: 100px ;
overflow: hidden ;
}
.viewer{
display: inline-block ;
}
.viewer span{
color: #ddd ;
font-family: sans-serif ;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<span class="wrapper">
<img data-image="1" src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/550px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg"/>
<img data-image="2" src="https://upload.wikimedia.org/wikipedia/en/8/81/Megadrive_another_world.png"/>
<img data-image="3" src="https://upload.wikimedia.org/wikipedia/en/e/ee/TheKlingonHamlet.jpg"/>
</span>
<span class="viewer">
<span>scaled</span><br>
<div class="canvas-wrapper">
<canvas id="canvas-scaled"></canvas>
</div>
</span>
<span class="viewer">
<span>stretched</span><br>
<div class="canvas-wrapper">
<canvas id="canvas-stretched"></canvas>
</div>
</span>
<img id="banner" src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/The_southern_plane_of_the_Milky_Way_from_the_ATLASGAL_survey.jpg/320px-The_southern_plane_of_the_Milky_Way_from_the_ATLASGAL_survey.jpg"/>
答案 1 :(得分:3)
这一行是问题所在:
$('#info-poster').attr("src","myimage-thisimage.jpg");
浏览器正在重新加载图像,因为您重新设置了(不良做法)&#34; src&#34;属性。
相反,您可以使用CSS选项来显示/隐藏&#34; myimage-thisimage.jpg&#34;。
由于您使用jQuery,我们可以使用这些方法:hide/show。
你提到&#34;克隆&#34;,我不认为你是HTML elements clonning。
示例:(live on JS Bin)
<img id="dummy" width="200" height="150" data-image='1' src="http://europunkt.ro/wp-content/uploads/2016/06/romania.jpg">
<!-- Hidden by default -->
<img style="display:none" id="info-poster" width="200" height="150">
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<script>
var $dummy = $("#dummy");
var $infoPoster = $("#info-poster");
var infoPosterHasLoaded = false;
$dummy.on("mouseenter", function() {
// add the src attribute ONLY once
if(infoPosterHasLoaded === false){
$infoPoster.attr("src", "http://www.ilovemaramures.com/wp-content/uploads/2012/05/Pasul-Prislop.jpg")
infoPosterHasLoaded = true;
}
$infoPoster.show();
});
$dummy.on("mouseleave", function() {
$infoPoster.hide();
});
</script>
更加花哨的&#34;隐藏/显示&#34;你可以查看jQuery Effects。
修改 - 在我阅读您的评论之后
如果您想使用&#34;数据图像&#34;来自悬停元素的属性,请检查以下对象:event.target,event.currentTarget,this
新的JS Bin版本。
答案 2 :(得分:2)
您可以将服务器上的图像请求转换为使用base64字符串进行响应,该字符串可以存储在您自己的缓存中。
以下示例代码:
<强> HTML 强>
<img id="image1Id" src="" />
<input type="button" onclick='javascript:loadSomeThing("image1", "", "image1Id");' value="Load Image1" />
<强>脚本强>
var imageArray = [];
function loadSomeThing(key, someUrl, elementId) {
var imageData = imageArray[key];
if (!imageData) {
imageData = ajaxGetImageData(someUrl);
imageArray[key] = imageData;
}
document.getElementById(elementId).src = imageData;
}
function ajaxGetImageData(url) {
//Code to get base64 image string
return "data:image/jpeg;base64,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";
}
<强>演示强>
答案 3 :(得分:1)
我相信使用jQuery .clone()
和.append()
函数可以实现您的需求。请参阅下面的示例。
$(function() {
$('img#ToClone').click(function(){
var imageClone = $('#ToClone').clone();
var cloneDestination = $('#CloneTo');
cloneDestination.append(imageClone);
});
});
div
{
padding:2px;
background:blue;
}
div#CloneTo
{
background:green;
}
img{
height:50px;
width:50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<p>Click on the red square to clone it below.</p>
<img id="ToClone" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGlSURBVHhe7dCxTQQAEMRACiGk/86o4UmMxEpY/KW8R5ddtH575GnFOijWQbEOinVQrINiHRTroFgHxTr4Pdbbq2K/KNZgvyjWYL8o1mC/KNZgv3gq1uf7x389Fn5jvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgvyjWYL8o1mC/KNZgv3gq1utgvyjWYL8o1mC/KNZgvyjWYL/4452finVQrINiHRTroFgHxToo1kGxDor1tMfjC8KHtIEDA9XCAAAAAElFTkSuQmCC" />
</div>
<div id="CloneTo">
<p>Clone should appear here.</p>
<!-- The cloned image should appear here. -->
</div>
答案 4 :(得分:0)
您应该让浏览器执行缓存处理。
我建议您可以使用<img id="info-poster" src="myimage-thisimage.jpg" class="hide-on-load"/>
,因此如果您的浏览器要加载图片的新副本,则会在用户将鼠标悬停在其他图片上之前执行此操作。 (如果它是一个小/可接受的图像,用户可能必须在每次加载页面时下载它)
然后你可以简单地绑定$("img.bind-event").on("mouseenter", function() { $("#info-poster").show(); });
和$("img.bind-event").on("mouseleave", function() { $("#info-poster").hide(); });
答案 5 :(得分:0)
初始标记
<img data-src='myimg1.jpg' data-image='1' src='placeholder.jpg'>
myimg1.jpg动态加载后(*)
<img data-image='1' src='blob:asdfasdfasdfasdfadfa'>
然后在'mouseenter'上
infoPosterEl.src = thisImageEl.src
// update image src to an object url(e.g. "blob:") will not bother http comm.
(*)
// Fetch acutal image as blob
// Create object url for the blob
// Update this <img> src to the object url
答案 6 :(得分:0)
您可以存储数组中每个图像的路径,使用Array.prototype.forEach()
迭代数组,使用background
设置每个<img>
元素的url("/path/to/image")
;在使用mouseover
,{{1}的集合中的h <img>
元素索引的每个background-size
设置100% 100%
菜单元素的<img>
Array.prototype.slice()
}}。该方法应该最多一次从服务器请求每个图像,切换菜单元素处显示的图像以对应于悬停图像。
Array.prototype.splice()
var urls = ["http://placehold.it/100x100?text=1"
, "http://placehold.it/100x100?text=2"
, "http://placehold.it/100x100?text=3"
, "http://placehold.it/100x100?text=4"
, "http://placehold.it/100x100?text=5"]
, sources = []
, sizes = []
, imgs = document.querySelectorAll(".img")
, menu = document.querySelector(".menu");
function toggleImage(index) {
this.onmouseover = function() {
var curr = sizes.slice(0);
curr.splice(index, 1, "100% 100%");
menu.style.backgroundSize = curr.join(",");
}
}
urls.forEach(function(path, index) {
sources.push("url(" + path + ")");
sizes.push("0% 0%");
imgs[index].style.background = sources[index];
toggleImage.call(imgs[index], index);
});
menu.style.background = sources.join(",");
menu.style.backgroundSize = sizes.join(",");
.menu {
left: calc(100vw / 2 - 50px);
position: relative;
width: 75px;
height: 75px;
display: block;
}