是否可以在加载后在页面的其他部分加载后克隆图像?

Sai*_*eep 15 html javascript css jquery image

我遇到了一个简单的问题.让我说我的用户通过一个简单的<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");
Run Code Online (Sandbox Code Playgroud)

注意: myimage-thisimage.jpg当前是否在图像上方悬停.

但是,当我这样做.浏览器正在重新加载图像(因为,有一个小的延迟).是否有任何方法可以绕过此加载,因为用户已经使用克隆DOM元素的巧妙方式加载了图像?

PS:启用浏览器图像缓存.因此,缓存不是问题.

编辑:我知道一种方法是创建300个图像元素并隐藏其他150个图像元素.但在一个场景(绝对可能)中,有近500张图像,我将不得不创建大约1000个DOM元素,这将是一个很大的性能问题.

小智 6

您可以使用canvas元素显示缩略图,这样就可以在本地复制和缩放图像.在下面的片段中我添加了两个画布,在第一个画面中缩放图像同时保持宽高比(我需要时使用Letterboxing和Pillarboxing技术); 在第二个图像被拉伸.我还在底部添加了另一个被忽略的图像,因为它没有data-image属性.

重要的是不要使用drawImage的缩放算法,因为当你大量减少图像时会产生不平滑的结果.要实现此目的,请设置画布的逻辑大小以匹配图像的自然大小.然后通过调用drawImage方法将图像复制到画布.最后将画布的显示大小设置为所需的大小.这样浏览器就可以使用更好的算法来缩放图像.

以下是drawImage()方法规范中的一些优秀引用:

  • 您可以确定不会重新加载图像,并且必须使用图像的自然大小以避免使用drawImage进行缩放:

如果原始图像数据是位图图像,则通过过滤原始图像数据来计算在目标矩形中的点处绘制的值.

  • 浏览器决定使用哪种缩放算法.在写这篇文章的那一刻:Edge,Chrome和Firefox并没有比双线性或最近邻算法更好用.这可能会在未来发生变化:

用户代理可以使用任何过滤算法(例如双线性插值或最近邻居).

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");
    });
});
Run Code Online (Sandbox Code Playgroud)
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 ;
}
Run Code Online (Sandbox Code Playgroud)
<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"/>
Run Code Online (Sandbox Code Playgroud)


Zay*_*Lau 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(); });