Đang tải trước hình ảnh. Tất cả các nhận xét đều có ghi chú "Tải trước hình ảnh - một ví dụ về tải trước hình ảnh trong HTML, JavaScript." Tải theo sự kiện

  • Dịch
  • Hướng dẫn

Tải hình ảnh nhanh và mượt mà là một trong những thành phần quan trọng của giao diện web tốt. Ngoài ra, ngày càng có nhiều trang web sử dụng ảnh lớn trong thiết kế; đối với những dự án như vậy, điều đặc biệt quan trọng là phải giám sát việc tải đồ họa chính xác. Bài viết này mô tả một số kỹ thuật sẽ giúp bạn kiểm soát việc tải hình ảnh.

Sử dụng vùng chứa cho mỗi hình ảnh Một phương pháp đơn giản có thể áp dụng cho bất kỳ hình ảnh nào trên trang web. Bí quyết là mỗi hình ảnh được gói trong một DIV, điều này ngăn cản việc tải từng hàng:


Sử dụng vùng chứa, bạn có thể kiểm soát tỷ lệ khung hình của hình ảnh và cũng có thể sử dụng chỉ báo tải, điều này rất thuận tiện nếu hình ảnh nặng.

Ví dụ: để đặt tỷ lệ khung hình thành 4:3, bạn có thể sử dụng CSS sau:

Img_wrapper(vị trí: tương đối; đệm-top: 75%; tràn: ẩn; ) .img_wrapper img(vị trí: tuyệt đối; top: 0; chiều rộng: 100%; độ mờ: 0; )
Để đảm bảo hình ảnh chỉ được hiển thị trên trình duyệt sau khi đã được tải đầy đủ, bạn cần thêm sự kiện onload cho hình ảnh và sử dụng JavaScript để xử lý sự kiện:


hàm imgLoaded(img)( var $img = $(img); $img.parent().addClass("loaded"); );
Mã chức năng bên trong thẻ ĐẦU phải được đặt ở cuối cùng, sau bất kỳ jQuery hoặc plugin nào khác. Sau khi hình ảnh được tải đầy đủ, nó phải được hiển thị trên trang:

Img_wrapper.loaded img( độ mờ: 1; )
Để có hiệu ứng làm cho hình ảnh trông mượt mà, bạn có thể sử dụng chuyển tiếp CSS3:

Img_wrapper img(vị trí: tuyệt đối; top: 0; chiều rộng: 100%; độ mờ: 0; -webkit-transition: độ mờ 150ms; -moz-transition: độ mờ 150ms; -ms-transition: độ mờ 150ms; chuyển tiếp: độ mờ 150ms; )
Một ví dụ trực tiếp về phương pháp này có sẵn.

Sử dụng vùng chứa cho nhiều hình ảnh Phương pháp trước đó hoạt động tốt cho hình ảnh riêng lẻ, nhưng điều gì sẽ xảy ra nếu có nhiều mục như vậy trên trang, chẳng hạn như thư viện ảnh hoặc thanh trượt? Không nên tải lên mọi thứ cùng một lúc - những bức ảnh có thể nặng nề. Để giải quyết vấn đề này, bạn có thể buộc JavaScript chỉ tải những gì bạn cần vào khoảnh khắc này thời gian hình ảnh. Đánh dấu HTML mẫu cho bản trình chiếu:


Chúng tôi sử dụng hàm slideLoaded() để kiểm soát quá trình:

Hàm slideLoaded(img)( var $img = $(img), $slideWrapper = $img.parent(), Total = $slideWrapper.find("img").length, phần trămLoaded = null; $img.addClass("loaded "); var đã tải = $slideWrapper.find(".loaded").length; if(loaded == tổng)( phần trămLoaded = 100; // PLUGIN TỨC THÌ $slideWrapper.easyFader(); ) else ( // THEO DÕI TIẾN ĐỘ phần trăm đã tải = đã tải/tổng ​​* 100);
Hình ảnh đã tải được chỉ định lớp đã tải và tiến trình tổng thể được hiển thị. Một lần nữa, JavaScript phải được đặt ở cuối thẻ HEAD, sau mọi thứ khác.

Bộ nhớ đệm Trên các trang web có đồ họa nặng, bạn có thể lý lịch, người dùng không chú ý, tải hình ảnh vào bộ đệm của trình duyệt. Ví dụ: có một trang web nhiều trang, trên một trong trang nội bộ có nhiều nội dung đồ họa. Trong trường hợp này, nên tải hình ảnh vào bộ nhớ đệm ngay cả trước khi người dùng chuyển sang trang mong muốn. địa chỉ của hình ảnh trong mảng:

var heroArray = [ "/uploads/hero_about.jpg", "/uploads/hero_history.jpg", "/uploads/hero_contact.jpg", "/uploads/hero_services.jpg" ]
Khi khách truy cập vào trang web, sau khi tải trang chủ, hình ảnh bắt đầu được tải vào bộ đệm. Để đảm bảo bộ nhớ đệm không can thiệp vào việc hiển thị nội dung hiện tại, bạn cần thêm chức năng JavaScript vào sự kiện tải cửa sổ:

Hàm preCacheHeros())( $.each(heroArray, function())( var img = new Image(); img.src = this; )); $(window).load(function())( preCacheHeros(); ));
Phương pháp này cải thiện khả năng sử dụng của trang web nhưng lại gây thêm tải cho máy chủ. Điều này phải được ghi nhớ khi thực hiện chức năng đó. Ngoài ra, cần phải tính đến những cách có thể khách truy cập vào trang web và lưu vào bộ nhớ đệm các hình ảnh trên các trang mà người dùng có nhiều khả năng truy cập nhất. Để hiểu những đường dẫn như vậy qua trang web, cần phải phân tích số liệu thống kê lưu lượng truy cập.

Phương pháp tải dựa trên sự kiện là hình ảnh bắt đầu được tải sau một sự kiện nhất định. Điều này làm tăng năng suất và tiết kiệm lưu lượng người dùng. Đánh dấu HTML:


Điều đáng chú ý là URL hình ảnh được chỉ định trong data-src chứ không phải trong src. Điều này là cần thiết để trình duyệt không tải hình ảnh xuống ngay lập tức. Thay vào đó, src được tải bằng pixel GIF trong suốt base64, giúp giảm số lượng chuyến đi khứ hồi tới máy chủ.

Tất cả những gì còn lại là thay đổi giá trị src thành data-src khi sự kiện mong muốn xảy ra. JavaScript cho phép bạn tải hình ảnh tăng dần:

Hàm lườiLoad())( var $images = $(".lazy_load"); $images.each(function())( var $img = $(this), src = $img.attr("data-src") ; $ img .on("load",imgLoaded($img)) .attr("src",src )); $(window).load(function())( lườiLoad(); );

Kết luận Không có một cách tốt nhấtđể quản lý việc tải hình ảnh trên trang web. Trong mỗi trường hợp cụ thể cần lựa chọn phương pháp phù hợp, đồng thời kết hợp nhiều phương pháp nếu phù hợp. Một trong những điểm chính mà bạn cần chú ý đến là hiệu suất và lưu lượng truy cập. Nói một cách đơn giản, trước hết bạn nên nghĩ xem nó sẽ như thế nào thuận tiện hơn cho người dùngđịa điểm.
Tại sao chúng ta cần tải trước hình ảnh? Thông thường, chúng tôi sử dụng nó để vẽ các giao diện và điều khiển trang web chất lượng cao. Ví dụ: Có một tập lệnh thư viện hoặc các khối văn bản có khả năng di chuyển (tại đây/tại đây). Mũi tên đồ họa có nhiệm vụ kiểm soát chuyển động. Khi bạn di chuột qua một mũi tên, hình ảnh của nó sẽ được thay thế bằng một hình ảnh khác.
Trình duyệt làm gì khi di chuột? Nó gửi một yêu cầu hình ảnh đến máy chủ. Ngay cả khi phản hồi rất nhanh, hiệu ứng “chớp mắt” vẫn sẽ được chú ý. Nếu bạn tải trước hình ảnh, điều này sẽ không xảy ra. bố cục hiện đại Cách tiếp cận này hiếm khi được sử dụng. Tốt nhất nên sử dụng CSS Sprites. Tuy nhiên, nếu điều này là không thể và bạn thực sự cần nó, chào mừng bạn đến với chú mèo.

Var imgPath = "/tpl/images/"; // đường dẫn tới thư mục có hình ảnh // danh sách hình ảnh var preloadImagesList = Array("about_hover.jpg", "news_hover.jpg", "photo_hover.jpg", "video_hover.jpg", "contacts_hover.jpg" / / / *******************************/ // chức năng tải trước hàm preloadImages(hình ảnh)( for(var i = 0; i< images.length; i++){ var image = images[i]; $("").attr("src", imgPath + image); )//for )//preloadImages /*************************** ********** ****/ //gọi hàm $().ready(function())( preloadImages(preloadImagesList); ))

Để chơi trò chơi, bạn cần tải trước khoảng 12 hình ảnh và những hình ảnh này có thể khác nhau tùy theo từng trường hợp. Tức là bây giờ tôi cần tải khoảng 12 hình ảnh (SVG) và ngày mai tôi sẽ cần thêm 12 hình ảnh khác. Vì vậy, tùy chọn đặt chúng vào là không phù hợp, vì trong trường hợp này bạn sẽ phải tải tất cả các hình ảnh liên tục và tôi chỉ cần 12 hình ảnh trong số đó nên tôi quyết định tải chúng. sử dụng JavaScript trước khi bắt đầu trò chơi. Để làm điều này, tôi đã triển khai một lớp nhỏ "AssetsPreloader", lớp này cho đến nay đã có phương pháp duy nhất"preload", lấy một mảng các đối tượng có dạng (src: "link", id: "id") và tải hình ảnh cần thiết qua sáng tạo dễ dàng một thể hiện của lớp Image() (bản địa).

Class AssetsPreloader ( static preload(arr) ( arr.map((a) => ( let img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. tài sản || ).push(img);

Tất cả hình ảnh được tải đều nằm trong thuộc tính nội dung tĩnh của lớp này.

Tiếp theo trong mã là hiển thị khung hình đầu tiên của trò chơi, nơi những hình ảnh này đã được sử dụng. Và nói chung, vấn đề là việc hiển thị không xảy ra. Việc thực thi mã đạt đến nó, tôi đã kiểm tra điều này và sau đó mã được thực thi, nhưng bản thân các hình ảnh không được vẽ. Theo tôi hiểu, điều này xảy ra do hình ảnh không có thời gian để tải (mặc dù chúng được tải từ đĩa). Tuy nhiên, nếu bạn yêu cầu vẽ khung đầu tiên trực tiếp từ bảng điều khiển của trình duyệt thì mọi thứ sẽ hoạt động bình thường và khung được vẽ bình thường.

Toàn bộ mã thường trông giống như thế này:

Class AssetsPreloader ( static preload(arr) ( arr.map((a) => ( let img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. nội dung || ).push(img); this.done = true; ) ) AssetsPreloader.preload([ (src: "images/image.svg", id: "id_of_image"), ... ]); // ... GAME.field.draw();

Cuối cùng, câu hỏi đặt ra là làm thế nào để tải hình ảnh (và các loại tệp khác nhau nói chung) một cách chính xác nhất có thể để cho đến khi chúng được tải, mã sẽ không được thực thi thêm. Hơn nữa, có lẽ sẽ có một loại thanh tiến trình nào đó trên màn hình vào lúc này (nghĩa là tập lệnh cũng không được đóng băng hoàn toàn). Điều đầu tiên tôi nghĩ đến là thêm tất cả phần còn lại của mã vào lệnh gọi lại phương thức preload(), nhưng ý tưởng này không thành công.

Hãy giúp tôi. Quan tâm không chỉ đến cách thức mà còn quan tâm đến cách nào là đúng nhất (cách thực hành tốt nhất, tất cả những điều đó).

tái bút Tệp tập lệnh được kết nối với trang có thuộc tính trì hoãn. Ví dụ: khi sử dụng async , việc hiển thị sẽ xảy ra hoặc không (tôi không thể nói nó phụ thuộc vào điều gì). Nhưng tôi không muốn thêm các trình xử lý để kiểm tra tải trang, mức độ sẵn sàng của DOM hoặc những thứ tương tự vào chính mã đó.

Để chơi trò chơi, bạn cần tải trước khoảng 12 hình ảnh và những hình ảnh này có thể khác nhau tùy theo từng trường hợp. Tức là bây giờ tôi cần tải khoảng 12 hình ảnh (SVG) và ngày mai tôi sẽ cần thêm 12 hình ảnh khác. Vì vậy, tùy chọn đặt chúng vào là không phù hợp, vì trong trường hợp này bạn sẽ phải tải tất cả các hình ảnh liên tục và tôi chỉ cần 12 hình ảnh trong số đó. Do đó, tôi quyết định tải chúng bằng JavaScript trước khi bắt đầu trò chơi. Để làm điều này, tôi đã triển khai một lớp nhỏ "AssetsPreloader", hiện tại, nó có một phương thức "tải trước" duy nhất, phương thức này nhận một mảng các đối tượng có dạng (src: "link", id: "id") và tải các hình ảnh cần thiết bằng cách tạo một thể hiện của lớp Image() (gốc).

Class AssetsPreloader ( static preload(arr) ( arr.map((a) => ( let img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. tài sản || ).push(img);

Tất cả hình ảnh được tải đều nằm trong thuộc tính nội dung tĩnh của lớp này.

Tiếp theo trong mã là hiển thị khung hình đầu tiên của trò chơi, nơi những hình ảnh này đã được sử dụng. Và nói chung, vấn đề là việc hiển thị không xảy ra. Việc thực thi mã đạt đến nó, tôi đã kiểm tra điều này và sau đó mã được thực thi, nhưng bản thân các hình ảnh không được vẽ. Theo tôi hiểu, điều này xảy ra do hình ảnh không có thời gian để tải (mặc dù chúng được tải từ đĩa). Tuy nhiên, nếu bạn yêu cầu vẽ khung đầu tiên trực tiếp từ bảng điều khiển của trình duyệt thì mọi thứ sẽ hoạt động bình thường và khung được vẽ bình thường.

Toàn bộ mã thường trông giống như thế này:

Class AssetsPreloader ( static preload(arr) ( arr.map((a) => ( let img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. nội dung || ).push(img); this.done = true; ) ) AssetsPreloader.preload([ (src: "images/image.svg", id: "id_of_image"), ... ]); // ... GAME.field.draw();

Cuối cùng, câu hỏi đặt ra là làm thế nào để tải hình ảnh (và các loại tệp khác nhau nói chung) một cách chính xác nhất có thể để cho đến khi chúng được tải, mã sẽ không được thực thi thêm. Hơn nữa, có lẽ sẽ có một loại thanh tiến trình nào đó trên màn hình vào lúc này (nghĩa là tập lệnh cũng không được đóng băng hoàn toàn). Điều đầu tiên tôi nghĩ đến là thêm tất cả phần còn lại của mã vào lệnh gọi lại phương thức preload(), nhưng ý tưởng này không thành công.

Hãy giúp tôi. Quan tâm không chỉ đến cách thức mà còn quan tâm đến cách nào là đúng nhất (cách thực hành tốt nhất, tất cả những điều đó).

tái bút Tệp tập lệnh được kết nối với trang có thuộc tính trì hoãn. Ví dụ: khi sử dụng async , việc hiển thị sẽ xảy ra hoặc không (tôi không thể nói nó phụ thuộc vào điều gì). Nhưng tôi không muốn thêm các trình xử lý để kiểm tra tải trang, mức độ sẵn sàng của DOM hoặc những thứ tương tự vào chính mã đó.

Tại sao bạn lại cần hình ảnh? Hãy tưởng tượng rằng bạn có một thành phần trên một trang web và bạn muốn hình nền của nó hiển thị hoặc thay đổi khi bạn di chuột qua nó. Về nguyên tắc, các vấn đề sẽ không phát sinh; mọi thứ có thể được giải quyết một cách đơn giản: khi tạo một trang web theo kiểu đánh dấu cho pseudo-class:hover của phần tử mong muốn, chúng tôi chỉ định đường dẫn đến hình ảnh được yêu cầu trong thuộc tính nền.

Nhưng có một lưu ý: nếu sự kiện di chuột xảy ra lần đầu tiên thì có thể mất thời gian để tải hình ảnh. Mặc dù khoảng thời gian này có thể nhỏ nhưng đôi khi bạn có thể nhận thấy độ trễ ngắn và khó chịu giữa việc di chuột qua một phần tử và hình ảnh được hiển thị đầy đủ. Rõ ràng là trong tương lai sẽ không có sự chậm trễ như vậy vì các trình duyệt sẽ lưu trữ hình ảnh một cách thiện chí. Tuy nhiên, như bạn đã biết, ấn tượng đầu tiên về trang web của bạn chỉ nên tích cực và không cần thiết phải làm hỏng nó bằng những chuyện vặt vãnh như vậy, đặc biệt là vì chúng có thể tránh được. Làm thế nào để giải quyết một vấn đề nhỏ nhưng độc đáo như vậy? Có nhiều phương pháp, ở đây studio web của chúng tôi sẽ chỉ giới thiệu cho bạn những phương pháp có thể giải quyết bằng css.

Kỹ thuật đầu tiên là tải ngay thành phần đồ họa, sau đó xóa nó khỏi vùng hiển thị bằng cách sử dụng thuộc tính vị trí nền, ví dụ: bằng cách đặt độ lệch x và y sau - -9999px -9999px. Khi sự kiện di chuột xảy ra, chúng tôi đã áp dụng giá trị thực, ví dụ: phía dưới bên trái.

Phải làm gì nếu phần tử đã có hình nền, và khi bạn di con trỏ chuột thì nó phải được thay đổi. Kỹ thuật trên không còn phù hợp như một giải pháp. Thông thường trong những trường hợp như vậy, sprite được sử dụng (kết hợp hình nền) khi vị trí nền được dịch chuyển. Nếu phương pháp này không có sẵn cho bạn, hãy thử cách sau. Áp dụng hình ảnh cho một thành phần khác tồn tại trên trang nhưng không có hình nền.

#phần tử ngẫu nhiên không nghi ngờ ( nền: url(images/grass.png) no-repeat -9999px -9999px; )

#grass:hover ( nền: url(images/grass.png) no-repeat; )

Ý tưởng là tạo ra các phần tử mới chỉ cần thiết để tải trước hình ảnh. Bạn sẽ nói rằng đây không phải là điều tốt nhất Cách tốt nhất, bởi vì số lượng hình nộm như vậy có thể rất lớn, nhưng giải pháp sẽ không được tinh tế. Và bạn sẽ hoàn toàn đúng. Chúng tôi không cần yếu tố bổ sung, vì chúng ta có thể yên tâm sử dụng những cái hiện có. Tất cả những gì chúng ta cần là sử dụng các lớp giả:after hoặc:Before.

#thứ gì đó:trước (

nội dung: url("./img.jpg");

khả năng hiển thị: ẩn;

Tùy chọn này cho chúng ta cơ hội tải trước hình ảnh mà không cần tạo các phần tử bổ sung.

Tất nhiên, bạn có thể sử dụng javascript cho những mục đích này, nhưng nếu các giải pháp trên đủ để bạn tạo một trang web thì tại sao không sử dụng chúng.