... и т. Д.Когда пользователь наводит курсор на одн" />

Можно ли клонировать изображение после загрузки в другие части страницы без загрузки?

javascript jquery html css image

1054 просмотра

7 ответа

Я столкнулся с простой проблемой. Пусть говорит, что мой пользователь загружает около 150 изображений с помощью простого <img data-image='1' src="myimg1.jpg"> <img data-image=2' src="myimg2.jpg">... и т. Д.

Когда пользователь наводит курсор на одно из своих изображений. Я хочу отобразить это myimg-thisimage.jpgв небольшом меню в нижней части экрана. На данный момент я изменяю атрибут src в моем меню следующим образом:

$('#info-poster').attr("src","myimage-thisimage.jpg");

Примечание: myimage-thisimage.jpg текущее наведение на изображение.

Но когда я это сделаю. Браузер перезагружает изображение (потому что есть небольшая задержка). Есть ли способ обойти эту загрузку, поскольку пользователь уже загрузил изображение, используя умный способ клонирования элемента DOM?

PS: кеш изображений браузера включен. Следовательно, кеш не является проблемой.

Редактировать: я знаю, один способ - создать 300 элементов изображения и скрыть остальные 150 из них. Но в сценарии (определенно возможном), где есть около 500 изображений, мне пришлось бы создать около 1000 элементов DOM, что было бы большой проблемой производительности.

Автор: Sai Krishna Deep Источник Размещён: 08.11.2019 10:57

Ответы (7)


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");
    });
});
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"/>

Автор: user6558785 Размещён: 22.08.2016 09:33

2 плюса

Эта строка является проблемой:

$('#info-poster').attr("src","myimage-thisimage.jpg");

Браузер перезагружает изображение, потому что вы переназначаете (плохая практика) атрибут «src».
Вместо этого вы можете использовать опции CSS для отображения / скрытия "myimage-thisimage.jpg".

Поскольку вы используете jQuery, мы можем использовать методы: hide / show .

Вы упомянули «клон», я не думаю, что вы имеете в виду клонирование HTML-элементов .

Пример: ( жить на 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>

Для более интересного «скрытия / показа» вы можете проверить эффекты jQuery .


Изменить - после того, как я прочитал ваш комментарий

Если вы хотите использовать атрибут «data-image» из элемента hovered , проверьте следующие объекты: event.target , event.currentTarget , эта

новая версия JS Bin .

Автор: Marian07 Размещён: 20.08.2016 07:31

1 плюс

Я считаю, что то, что вы хотите, возможно с помощью jQuery .clone()и .append()функции. Смотрите пример ниже.

jQuery.clone ()

jQuery.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>

Автор: Error-404-UserNotFound Размещён: 22.08.2016 04:56

1 плюс

Вы можете преобразовать запросы изображения на сервере, чтобы они отвечали строкой 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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";
}

демонстрация

jsFiddle

Автор: James Jithin Размещён: 22.08.2016 05:38

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(); });

Автор: Zay Lau Размещён: 20.08.2016 06:37

0 плюса

IDEA

начальная разметка

<img data-src='myimg1.jpg' data-image='1' src='placeholder.jpg'>

после динамической загрузки myimg1.jpg (*)

<img data-image='1' src='blob:asdfasdfasdfasdfadfa'>

Затем на «мышиный центр»

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
Автор: user943702 Размещён: 27.08.2016 04:28

0 плюса

Вы можете сохранить путь к каждому изображению в массиве, использовать итерацию массива Array.prototype.forEach(), установить backgroundкаждый <img>элемент с помощью url("/path/to/image"); на mouseoverкаждый <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;
}
<img class="img" width="100" height="100" src="" /><img class="img" width="100" height="100" /><img class="img" width="100" height="100" /><img class="img" width="100" height="100" /><img class="img" width="100" height="100" />
<div class="menu">
</div>

Автор: guest271314 Размещён: 29.08.2016 12:50
Вопросы из категории :
32x32